\documentclass{article}
\usepackage{ulem}
\pagestyle{headings}
\begin{document}
\part{ Replacing APIs with your own solutions}
Horde applications are loosely coupled with each other through the application APIs. Each application provides a set of external API methods that can be called from other Horde applications through the Horde Registry, or even externally through the Horde RPC interfaces. See the Registry wiki page\footnote{http://example.com/index.php?page=Doc/Dev/Registry} for details.

If you want to provide some functionality through your own or some external code, all you need to do it to register you own code in the Horde Registry and provide the required API methods. For example, if you have your own address book or CRM solution, you could replace Horde's address book module Turba with that program.

Here is a real world example. Say we have a CRM system that is providing contacts. First create a small application stub, a Horde mini-application. We call it "crm" and need the following 3 files to become a working Horde module:

\begin{verbatim}

horde/config/registry.d/crm.php
horde/crm/config/conf.php
horde/crm/lib/api.php
\end{verbatim}

The \texttt{registry.d/} directory exists since Horde 3.2. For earlier versions, add the code from \texttt{crm.php} directly to \texttt{horde/config/registry.php}. The directory in newer versions is more flexible since you can update the \texttt{registry.php} configuration file more easily when upgrading to newer Horde versions if you didn't customize it. The name of the file in registry.d is arbitrary. For changes to a file in \texttt{registry.d/} to take effect, a user must log out and in again. Amendments to \texttt{registry.php} or \texttt{registry.local.php} are effective immediately.

The \texttt{conf.php} can be empty. The \texttt{registry.d/crm.php} file looks like:

\begin{verbatim}

<?php
$this->applications['crm'] = array(
    'fileroot' => dirname(__FILE__) . '/../../crm',
    'webroot' => $this->applications['horde']['webroot'] . '/crm',
    'name' => 'CRM',
    'status' => 'notoolbar',
    'provides' => array('contacts'),
);
\end{verbatim}

This entry registers an application called "crm" at the Horde Registry, hides it from the toolbar (we only want to use it internally, i.e. it doesn't have a UI), and propagates the "contacts" API. This means that all methods calls to the contacts API will be delegated to the crm module. Turba provides a \textbf{lot} of methods through the contacts API, just take a look at \texttt{turba/lib/api.php} to get an impression. You don't have to implement all these methods in your crm module though, because a) not all methods are used in all Horde modules (see below), and b) you can also tell the registry to only provide certain methods of the contacts API. To achieve that, change the \texttt{'provides'} entry to a less generic value:

\begin{verbatim}

'provides' => array('contacts/search', 'contacts/show'),
\end{verbatim}

This tells the Registry that your are only providing the "search" and "show" methods of the "contacts" API. The other methods may be provided by other modules, by Turba, or not at all. \texttt{'provides'} entries with method names take precedence over generic entries, i.e. if for Turba you have \texttt{'provides' => array('contacts')} in the registry configuration and \texttt{'provides' => array('contacts/search', 'contacts/show')} for your own module, than these two method will be routed to your module, all other "contacts/" calls will be delegated to Turba.

The \texttt{Api.php} file finally provides the actual method definitions. At least for Horde5+ it is no longer necessary to include method signatures. The file implements a class that offers the registered services:

\begin{verbatim}

<?php
/**
 * CRM external API interface.
 *
 * This file defines CRM's external Horde API interface. Other Horde
 * applications will interact with CRM through this API.
 */

class CRM_Api extends Horde_Registry_Api
{
        public function search($args = array(), $type)
        {
                // do something
        }
        public function show($args = array())
        {
                // do something
        }

}

\end{verbatim}

It's a good idea to start with the function definitions already provided through existing Horde modules, to get some impression which functionality exactly is expected, how returned or incoming data structures look like, and how to deal with errors.

\section{ API methods called from the several applications}
This section is going to build a list of all Horde applications and the API methods they call. With this list you could easily see which methods you might have to implement if want your application to work with a certain set of Horde modules. Please remember, you don't \textbf{have to} implement all methods. If a method doesn't exist, the functionality simply isn't available in the Horde module that would call it.

Of course, you can provide additional API services or functions that may be used outside the Horde framework, i.e. by another Horde application.

\subsection{ Horde}
'*/browse'\newline
'*/changeLanguage'\newline
'*/delete'\newline
'*/getActionTimestamp'\newline
'*/import'\newline
'*/list'\newline
'*/listAlarms'\newline
'*/listBy'\newline
'*/listTagInfo'\newline
'*/removeUserData'\newline
'*/replace'\newline
'*/shareHelp'\newline
'clients/clientFields'\newline
'clients/fields'\newline
'clients/getClientSource'\newline
'contacts/import'\newline
'contacts/sources'\newline
'forwards/summary'\newline
'horde/admin\_list'\newline
'images/listGalleries'\newline
'images/listImages'\newline
'images/searchTags'\newline
'mail/compose'\newline
'news/searchTags'\newline
'sms/compose'\newline
'telephony/dial'\newline
'tickets/addTicket'\newline
'vacation/summary'

\subsection{ Chora}
\subsection{ DIMP}
\subsection{ Forwards}
\subsection{ IMP}
'calendar/delete'\newline
'calendar/eventFromGUID'\newline
'calendar/getFreeBusy'\newline
'calendar/import'\newline
'calendar/import\_vfreebusy'\newline
'calendar/show'\newline
'calendar/updateAttendee'\newline
'contacts/add'\newline
'contacts/fields'\newline
'contacts/getField'\newline
'contacts/import'\newline
'contacts/search'\newline
'contacts/show'\newline
'contacts/sources'\newline
'files/returnFromSelectlist'\newline
'files/selectlistResults'\newline
'images/saveImage'\newline
'images/selectGalleries'\newline
'mail/canApplyFilters'\newline
'mail/showBlacklist'\newline
'mail/showFilters'\newline
'mail/showWhitelist'\newline
'notes/import'\newline
'notes/listNotepads'\newline
'notes/show'\newline
'tasks/import'\newline
'tasks/listTasklists'\newline
'tasks/show'

\subsection{ Ingo}
\subsection{ Jeta}
\subsection{ Kronolith}
\subsection{ MIMP}
\subsection{ Mnemo}
\subsection{ Nag}
\subsection{ Passwd}
\subsection{ Turba}
\subsection{ Vacation}
\end{document}
