\documentclass{article}
\usepackage{ulem}
\pagestyle{headings}
\begin{document}
\tableofcontents

User Contributed PreferencesHooksCache user information between prefs\_init() callsSuppressing "whitelist" and "blacklist" menu items

\part{User Contributed Preferences}
Perhaps the greatest feature of Horde and all of it's modules is the flexibility to adapt to a myriad of different uses and I would expect that eventually, a more integrated system of managing 'defaults' will become part of the code but at this moment in time, the only way to effect settings system wide is to edit the various prefs.php file inside each module.

In general: Add any local changes to a prefs.local.php or a prefs.d/<name>,php file. Never change prefs.php because this file is overwritten on upgrade and contains vital system information about the preferences that must match the other parts of the system. For instance,

\texttt{kronolith/config/prefs.php} contains:\newline
\begin{verbatim}

// Address book(s) to use when expanding addresses ``
// Refer to turba/config/sources.php for possible source values
//
// You can provide default values this way:
//   'value' => json_encode(array('source_one', 'source_two'))
$_prefs['search_sources'] = array(
    'value' => ''
);
\end{verbatim}

To change the default value add the following PHP code to either \texttt{kronolith/config/prefs.local.php} or \texttt{kronolith/config/prefs.d/\textbf{name}.php} \texttt{name} can be any name you like, I prefer the local hostname:\newline
\begin{verbatim}

<?PHP
$_prefs['search_sources']['value'] = '["favourites"]';
\end{verbatim}

\section{Hooks}
You can provide default values by hooks, which are little PHP functions.

See CustomizingPreferencesH3\footnote{http://example.com/index.php?page=CustomizingPreferencesH3} for more ideas for preference hooks. Those use the old, no longer supported format from Horde 3, but still may provide some starting points for further customizations. If you port one of those Hooks to a recent Horde version, please add them here.

Since Horde 4 hooks are organized in classes, e.g. \texttt{config/hooks.php} uses \texttt{class Horde\_Hooks}, whereas  \texttt{kronolith/config/hooks.php} uses \texttt{class Kronolith\_Hooks}. See \texttt{config/hooks.php} for a description of hooks.

For instance to automatically prepare Kronolith's \texttt{search\_sources} with all address books the user has access to:

Enable the hook in the local prefs.php \texttt{kronolith/config/prefs.local.php}:\newline
<?PHP\newline
\$\_prefs['search\_sources']['hook'] = true;\newline
</code>

And add to  \texttt{kronolith/config/hooks.php}:\newline
\begin{verbatim}

<?PHP
class Kronolith_Hooks
{
    public function prefs_init($pref, $value, $username, $scope_ob)
    {
        if (is_null($username)) {    // not logged in
            return $value;
        }

        switch ($pref) {
        case 'search_sources':    // enable all sources by default
            if ($value == '') {
                $sources = $GLOBALS['registry']->call('contacts/sources');
                $value = json_encode(array_keys($sources));
                $scope_ob->set($pref, $value);
                $scope_ob->setDirty($pref, true);
            }
            return $value;
        }
    }
}
\end{verbatim}

Because the prefs\_init hook is called each time an user logins, line 12 shall prevent that the value is set to default each time, probably overwriting the user's choice. The empty string is the default value of the \texttt{search\_sources}.

Line 13 collects all address books from Turba, the user has access to. Line 14 prepares the string for the preference. These lines are very preference-specific.

Line 15 and 16 permanently write the settings into the preference storage of the user. The next time the user logins, \texttt{\$value} is no longer empty, hence, the \texttt{if()} block is skipped and any newly available address books are \textbf{not} automatically enabled. If you want to keep the preference changing until the user changes the setting manually, remove these two lines.

\section{Cache user information between prefs\_init() calls}
Because preference values are requested one after another, the function prefs\_init() is called for each preference you have set \texttt{hook = true}. If you query large latency databases, it can make sense to query all user data at once and cache the result for the next call of prefs\_init. You can use a Horde case for example like so:\newline
\begin{verbatim}

function my_userinfo($uid) {
    global $injector;
    $cache = $injector->getInstance('Horde_Cache');
    $key = 'my_userinfo.u.'.$uid;
    if($cache->exists($key)) {    // saved??
        return unserialize($cache->get($key));
    }

    $userinfo = false;

    // prepare the userinfo array here

    if(isset($userinfo)) {
        $cache->set($key, $userinfo, 20 * 60);
        return unserialize($userinfo);
    }
    return false;
}
\end{verbatim}

Save this function in a PHP file and use it in all prefs\_init() functions you need the user information, e.g. before the \texttt{switch(\$prefs)} statement:\newline
\begin{verbatim}

    require_once(HORDE_BASE . '/lib/my_lib.php');
    $info = my_userinfo($username);
    if(!isset($info) || $info === false || $info == '') {
        return $value; // error getting user information
    }
\end{verbatim}

\section{Suppressing "whitelist" and "blacklist" menu items}
As an administrator you may want to manage all SPAM controls at the server and if so, you'll want to remove these menu items so as not to confuse/frustrate your users.

File to edit: ../ingo/config/prefs.local.php

\begin{verbatim}


$_prefs['whitelist']['locked'] = true; 
$_prefs['spam']['locked'] = true; 

\end{verbatim}

File to edit: ../config/registry.local.php

\begin{verbatim}

$this->applications['ingo']['provides'] = array_diff(
     $this->applications['ingo']['provides'],
     array(
         'mail/blacklistFrom',
         'mail/showBlacklist',
         'mail/whitelistFrom',
         'mail/showWhitelist'
     )
);
\end{verbatim}

\end{document}
