<?php
/**
 * Class for auto-generating the preferences user interface and
 * processing the forms.
 *
 *
 * $Horde: horde/lib/PrefsUI.php,v 1.23 2003/08/21 13:15:21 jan Exp $
 *
 * Copyright 2001-2003 Chuck Hagenbuch <chuck@horde.org>
 *
 * See the enclosed file COPYING for license information (LGPL). If you
 * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
 *
 * @author  Chuck Hagenbuch <chuck@horde.org>
 * @version $Revision: 1.23 $
 * @since   Horde 2.1
 * @package horde.prefs
 */
class PrefsUI {

    /**
     * Determine whether or not a preferences group is editable.
     *
     * @access public
     *
     * @param string $group  The preferences group to check.
     *
     * @return boolean  Whether or not the group is editable.
     */
    function groupIsEditable($group)
    {
        global $prefs, $prefGroups;
        static $results;

        if (!isset($results)) {
            $results = array();
        }

        if (!array_key_exists($group, $results)) {
            if (!empty($group['url'])) {
                $results[$group] = true;
            } else {
                $results[$group] = false;
                if (isset($prefGroups[$group]['members'])) {
                    foreach ($prefGroups[$group]['members'] as $pref) {
                        if (!$prefs->isLocked($pref)) {
                            $results[$group] = true;
                            return true;
                        }
                    }
                }
            }
        }

        return $results[$group];
    }

    /**
     * Handle a preferences form submission if there is one, updating
     * any preferences which have been changed.
     *
     * @param optional string $group  The preferences group that was edited.
     *
     * @return boolean  Whether preferences have been updated.
     */
    function handleForm($group = null)
    {
        global $prefs, $prefGroups, $_prefs, $notification, $registry;

        $updated = false;

        /* Run through the action handlers */
        $actionID = Horde::getFormData('actionID');
        switch ($actionID) {
        case 'update_prefs':
            if (isset($group) && PrefsUI::groupIsEditable($group)) {
                $updated = false;

                foreach ($prefGroups[$group]['members'] as $pref) {
                    if (!$prefs->isLocked($pref) ||
                        ($_prefs[$pref]['type'] == 'special')) {
                        switch ($_prefs[$pref]['type']) {

                        /* These either aren't set or are set in other parts
                           of the UI. */
                        case 'implicit':
                        case 'link':
                            break;

                        case 'select':
                        case 'text':
                        case 'textarea':
                            $prefs->setValue($pref, Horde::getFormData($pref));
                            $updated = true;
                            break;

                        case 'enum':
                            $val = Horde::getFormData($pref);
                            if (isset($_prefs[$pref]['enum'][$val])) {
                                $prefs->setValue($pref, $val);
                                $updated = true;
                            } else {
                                $notification->push(_("An illegal value was specified."), 'horde.error');
                            }
                            break;

                        case 'multienum':
                            $vals = Horde::getFormData($pref);
                            $set = array();
                            $invalid = false;
                            foreach ($vals as $val) {
                                if (isset($_prefs[$pref]['enum'][$val])) {
                                    $set[] = $val;
                                } else {
                                    $invalid = true;
                                    continue;
                                }
                            }

                            if ($invalid) {
                                $notification->push(_("An illegal value was specified."), 'horde.error');
                            } else {
                                $prefs->setValue($pref, @serialize($set));
                                $updated = true;
                            }
                            break;

                        case 'number':
                            $num = Horde::getFormData($pref);
                            if (intval($num) != $num) {
                                $notification->push(_("This value must be a number."), 'horde.error');
                            } elseif ($num == 0) {
                                $notification->push(_("This number must be at least one."), 'horde.error');
                            } else {
                                $prefs->setValue($pref, $num);
                                $updated = true;
                            }
                            break;

                        case 'checkbox':
                            $val = Horde::getFormData($pref);
                            $prefs->setValue($pref, isset($val) ? 1 : 0);
                            $updated = true;
                            break;

                        case 'special':
                            /* Code for special elements must be written
                               specifically for each application. */
                            if (function_exists('handle_' . $pref)) {
                                $updated = call_user_func('handle_' . $pref, $updated);
                            }
                            break;

                        }
                    }
                }

                // Do anything that you need to do as a result of certain
                // preferences changing.
                if ($prefs->isDirty('language')) {
                    NLS::setLang($prefs->getValue('language'));
                    NLS::setTextdomain($registry->getApp(), $registry->getParam('fileroot') . '/locale', NLS::getCharset());
                }

                if ($updated) {
                    if (function_exists('prefs_callback')) {
                        prefs_callback();
                    }
                    $notification->push(_("Your options have been updated."), 'horde.message');
                    $group = null;
                }
            }
            break;
        }

        return $updated;
    }

    /**
     * Generate the UI for the preferences interface, either for a
     * specific group, or the group selection interface.
     *
     * @access public
     *
     * @param optional string $group  The group to generate the UI for.
     */
    function generateUI($group = null)
    {
        global $browser, $conf, $prefs, $prefGroups, $_prefs, $registry;

        /* Assign variables to hold select lists. */
        if (!$prefs->isLocked('language')) {
            $GLOBALS['language_options'] = &$GLOBALS['nls']['languages'];
        }

        if (!empty($group) && PrefsUI::groupIsEditable($group)) {
            require $registry->getParam('templates', 'horde') . '/prefs/begin.inc';
            foreach ($prefGroups[$group]['members'] as $pref) {
                if (!$prefs->isLocked($pref)) {
                    /* Get the help link. */
                    if (array_key_exists('help', $_prefs[$pref]) &&
                        $_prefs[$pref]['help'] &&
                        $conf['user']['online_help'] &&
                        $browser->hasFeature('javascript')) {
                        $helplink = Help::link($registry->getApp(), $_prefs[$pref]['help']);
                    } else {
                        $helplink = null;
                    }

                    switch ($_prefs[$pref]['type']) {
                    case 'implicit':
                        break;

                    case 'special':
                        require $registry->getParam('templates', $registry->getApp()) . "/prefs/$pref.inc";
                        break;

                    default:
                        require $registry->getParam('templates', 'horde') . '/prefs/' . $_prefs[$pref]['type'] . '.inc';
                        break;
                    }
                }
            }
            require $registry->getParam('templates', 'horde') . '/prefs/end.inc';
        } else {
            $columns = array();
            foreach ($prefGroups as $group => $gvals) {
                $col = $gvals['column'];
                unset($gvals['column']);
                $columns[$col][$group] = $gvals;
            }
            $span = round(100 / count($columns));
            require $registry->getParam('templates', 'horde') . '/prefs/overview.inc';
        }
    }

    /**
     * Generate the content of the title bar navigation cell (previous
     * | next option group).
     *
     * @access public
     *
     * @param          string $group        Current option group.
     * @param optional string $attributes   The optional <td> attributes.
     */
    function generateNavigationCell($group, $attributes = 'class="header" align="right"')
    {
        global $prefGroups;

        // search for previous and next group.
        $previous = null;
        $next = null;
        $last = null;
        $first = null;
        $found = false;
        $finish = false;
        foreach ($prefGroups as $pgroup => $gval) {
            if (PrefsUI::groupIsEditable($pgroup)) {
                if (!$first) {
                    $first = $pgroup;
                }
                if (!$found) {
                    if ($pgroup == $group) {
                        $previous = $last;
                        $found = true;
                    }
                } else {
                    if (!$finish) {
                        $finish = true;
                        $next = $pgroup;
                    }
                }
                $last = $pgroup;
            }
        }
        if (!$previous) {
            $previous = $last;
        }
        if (!$next) {
            $next = $first;
        }
        if ($next == $previous) return;

        echo "<td $attributes><span class='smallheader'>";
        if (!empty($prefGroups[$previous]['url'])) {
            echo Horde::link(Horde::url($prefGroups[$previous]['url']),
                             _("Previous options"), 'menuitem');
            echo '&lt;&lt; ' . $prefGroups[$previous]['label'];
        } else {
            echo Horde::link(Horde::addParameter(Horde::applicationUrl('prefs.php'), 'group', $previous),
                             _("Previous options"), 'menuitem');
            echo '&lt;&lt; ' . $prefGroups[$previous]['label'];
        }
        echo '</a>&nbsp;|&nbsp;';
        if (!empty($prefGroups[$next]['url'])) {
            echo Horde::link(Horde::url($prefGroups[$next]['url']),
                             _("Next options"), 'menuitem');
            echo $prefGroups[$next]['label'] . ' &gt;&gt;';
        } else {
            echo Horde::link(Horde::addParameter(Horde::applicationUrl('prefs.php'), 'group', $next),
                             _("Next options"), 'menuitem');
            echo $prefGroups[$next]['label'] . ' &gt;&gt;';
        }
        echo '</a></span></td>';
    }

}
