steffen: server/kolab-horde-fbview/kolab-horde-fbview/fbview/kronolith/lib Day.php, NONE, 1.1 DayView.php, NONE, 1.1 Driver.php, NONE, 1.1 FBView.php, NONE, 1.1 Kronolith.php, NONE, 1.1 Storage.php, NONE, 1.1 WeekView.php, NONE, 1.1 api.php, NONE, 1.1 base.php, NONE, 1.1 prefs.php, NONE, 1.1 version.php, NONE, 1.1

cvs at intevation.de cvs at intevation.de
Mon Oct 31 12:43:20 CET 2005


Author: steffen

Update of /kolabrepository/server/kolab-horde-fbview/kolab-horde-fbview/fbview/kronolith/lib
In directory doto:/tmp/cvs-serv18388/kolab-horde-fbview/kolab-horde-fbview/fbview/kronolith/lib

Added Files:
	Day.php DayView.php Driver.php FBView.php Kronolith.php 
	Storage.php WeekView.php api.php base.php prefs.php 
	version.php 
Log Message:
Fbview in separate package

--- NEW FILE: Day.php ---
<?php
/**
 * The Kronolith_Day:: class provides an API for dealing with days.
 *
 * $Horde: kronolith/lib/Day.php,v 1.23 2004/04/03 03:40:07 chuck Exp $
 *
 * @author  Chuck Hagenbuch <chuck at horde.org>
 * @version $Revision: 1.1 $
 * @since   Kronolith 0.1
 * @package Kronolith
 */
class Kronolith_Day {

    var $month;
    var $mday;
    var $year;
    var $time;
    var $hours;

    function Kronolith_Day($month = null, $day = null, $year = null, $timestamp = null)
    {
        if (!empty($timestamp)) {
            $this->time = $timestamp;
        } else {
            if (empty($month)) {
                $month = date('n');
            }
            if (empty($year)) {
                $year = date('Y');
            }
            if (empty($day)) {
                $day = date('j');
            }

            // Now, compensate for any wrap around.
            $this->time = mktime(0, 0, 0, $month, $day, $year);
        }

        $this->month = date('n', $this->time);
        $this->year = date('Y', $this->time);
        $this->mday = date('j', $this->time);

        // Make the data array.
        $this->makeHours();
    }

    function makeHours()
    {
        $this->hours = array();

        $row = 0;
        for ($i = 0; $i < 48; $i++) {
            $this->hours[$i]['timestamp'] = mktime(0, $i * 30, 0, $this->month, $this->mday, $this->year);
        }
    }

    function getTime($format, $offset = 0)
    {
        return strftime($format,
                        mktime(0, 0, 0, $this->month, ($this->mday + $offset), $this->year));
    }

    function getTomorrow()
    {
        return mktime(0, 0, 0, $this->month, $this->mday + 1, $this->year);
    }

    function getStamp()
    {
        return mktime(0, 0, 0, $this->month, $this->mday, $this->year);
    }

    function isToday()
    {
        return (mktime(0, 0, 0, $this->month, $this->mday, $this->year) == mktime(0, 0, 0));
    }

    function isTomorrow()
    {
        return (mktime(0, 0, 0, $this->month, $this->mday - 1, $this->year) == mktime(0, 0, 0));
    }

}

--- NEW FILE: DayView.php ---
<?php

require_once KRONOLITH_BASE . '/lib/Day.php';

/**
 * The Kronolith_DayView:: class provides an API for viewing days.
 *
 * $Horde: kronolith/lib/DayView.php,v 1.129 2004/05/27 17:51:54 chuck Exp $
 *
 * @author  Chuck Hagenbuch <chuck at horde.org>
 * @author  Jan Schneider <jan at horde.org>
 * @version $Revision: 1.1 $
 * @since   Kronolith 0.1
 * @package Kronolith
 */
class Kronolith_DayView extends Kronolith_Day {

    var $_events = array();
    var $_all_day_events = array();
    var $_event_matrix = array();
    var $_parsed = false;
    var $_span = array();
    var $_totalspan = 0;
    var $_sidebyside = false;
    var $_currentCalendars = array();

    function Kronolith_DayView($month = null, $day = null, $year = null,
                               $timestamp = null, $events = null)
    {
        parent::Kronolith_Day($month, $day, $year, $timestamp);

        global $prefs;
        $this->_sidebyside = $prefs->getValue('show_shared_side_by_side');
        if ($this->_sidebyside) {
            $allCalendars = Kronolith::listCalendars();
            foreach ($GLOBALS['display_calendars'] as $cid) {
                 $this->_currentCalendars[$cid] = &$allCalendars[$cid];
                 $this->_all_day_events[$cid] = array();
            }
        } else {
            $this->_currentCalendars = array(0);
        }

        if (is_null($events)) {
            $events = Kronolith::listEvents($this,
                                            Kronolith::timestampToObject(mktime(23, 59, 59, $this->month, $this->mday, $this->year)),
                                            $GLOBALS['display_calendars']);
            $this->_events = array_pop($events);
        } else {
            $this->_events = $events;
        }
        if (!is_array($this->_events)) {
            $this->_events = array();
        }
    }

    function setEvents($events)
    {
        $this->_events = $events;
    }

    function html($template_path = KRONOLITH_TEMPLATES)
    {
        global $prefs, $print_view, $cManager;

        if (!$this->_parsed) {
            $this->parse();
        }

        $hours = $this->hours;
        $started = false;
        $first_row = true;

        $colors = $cManager->colors();

        if ($this->_sidebyside) {
            require $template_path . '/day/head_side_by_side.inc';
        } else {
            require $template_path . '/day/head.inc';
        }
        $row = '';
        if (Kronolith::getDefaultCalendar(PERMS_EDIT)) {
            $addeventurl = Horde::applicationUrl('addevent.php');
            $addeventurl = Util::addParameter($addeventurl, 'timestamp', $hours[0]['timestamp']);
            $addeventurl = Util::addParameter($addeventurl, 'allday', '1');
            $addeventurl = Util::addParameter($addeventurl, 'url', Horde::selfUrl(true));
            $addeventurl = Horde::link($addeventurl, _("Create a New Event"), 'hour') . _("All day") . '</a>';
        } else {
            $addeventurl = '<span class="hour">' . _("All day") . '</span>';
        }

        /* The all day events are not listed in different columns, but
         * in different rows.  In side by side view we do not spread
         * an event over multiple rows if there are different numbers
         * of all day events for different calendars.  We just put one
         * event in a single row with no rowspan.  We put in a rowspan
         * in the row after the last event to fill all remaining
         * rows. */
        $rowspan = ($this->_all_day_maxrowspan) ? ' rowspan="' . $this->_all_day_maxrowspan . '" ' : '';
        for ($k = 0; $k < $this->_all_day_maxrowspan; $k++) {
            $row = '';
            foreach ($this->_currentCalendars as $cid => $cal) {
                if (count($this->_all_day_events[$cid]) === $k) {
                    // There are no events or all events for this
                    // calendar have already been printed.
                    $row .= '<td class="allday" width="1%" rowspan="' . ($this->_all_day_maxrowspan - $k) . '" colspan="'.  $this->_span[$cid] . '"> </td>';
                } elseif (count($this->_all_day_events[$cid]) > $k) {
                    // We have not printed every all day event
                    // yet. Put one into this row.
                    $event = $this->_all_day_events[$cid][$k];
                    $categoryColor = isset($colors[$event->getCategory()]) ? $colors[$event->getCategory()] : '#ccffcc';
                    $row .= '<td class="day-eventbox" style="background-color: ' . $categoryColor . '; ';
                    $row .= 'border-color:' . Kronolith::borderColor($categoryColor) . '" ';
                    $row .= 'onmouseover="javascript:style.backgroundColor=\'' . Kronolith::highlightColor($categoryColor) . '\'" ';
                    $row .= 'onmouseout="javascript:style.backgroundColor=\'' . $categoryColor . '\'" ';
                    $row .= 'valign="top" colspan="' . $this->_span[$cid] . '">';
                    $row .= $event->getLink($this->getStamp());
                    $row .= '</td>';
                }
            }
            require $template_path . '/day/all_day.inc';
            $first_row = false;
        }

        if ($first_row) {
            $row .= '<td colspan="' . $this->_totalspan. '"> </td>';
            require $template_path . '/day/all_day.inc';
        }

        $first_row = true;
        for ($i = 0; $i < 48; $i++) {
            if ($i >= $prefs->getValue('day_hour_end') && $i > $this->last) {
                break;
            }
            if ($i < $this->first && $i < $prefs->getValue('day_hour_start')) {
                continue;
            }

            $row = '';
            $hspan = 0;
            if ($prefs->getValue('half') && $i % 2 != 0) {
                $time = ':30';
                $hourclass = 'halfhour';
            } else {
                $time = date(($prefs->getValue('twentyFour')) ? 'G' : 'ga', $hours[$i]['timestamp']);
                $hourclass = 'hour';
            }
            $style = ((($prefs->getValue('half')) ? $i : floor($i / 2)) % 2) ? 'item1' : 'item0';

            foreach ($this->_currentCalendars as $cid => $cal) {
                foreach ($this->_event_matrix[$cid][$i] as $key) {
                    $event = $this->_events[$key];
                    $start = mktime(floor($i / 2), ($i % 2) * 30, 0, $this->month, $this->mday, $this->year);

                    // Since we've made sure that this event's overlap
                    // is a factor of the total span, we get this
                    // event's individual span by dividing the total
                    // span by this event's overlap.
                    $span = $this->_span[$cid] / $event->overlap;
                    $hspan += $span;

                    $categoryColor = isset($colors[$event->getCategory()]) ? $colors[$event->getCategory()] : $colors['_default_'];
                    if ($event->startTimestamp >= $start && $event->startTimestamp < $start + 60 * 30 || $start == $this->getStamp()) {
                        $row .= '<td class="day-eventbox" style="background-color: ' . $categoryColor . '; ';
                        $row .= 'border-color:' . Kronolith::borderColor($categoryColor) . '" ';
                        $row .= 'onmouseover="javascript:style.backgroundColor=\'' . Kronolith::highlightColor($categoryColor) . '\'" ';
                        $row .= 'onmouseout="javascript:style.backgroundColor=\'' . $categoryColor . '\'" ';
                        $row .= 'width="' . round((90 / count($this->_currentCalendars)) * ($span / $this->_span[$cid]))  . '%" ';
                        $row .= 'valign="top" colspan="' . $span . '" rowspan="' . $event->rowspan . '">';
                        $row .= $event->getLink($this->getStamp());
                        $row .= ' </td>';
                    }
                }

                $diff = $this->_span[$cid] - $hspan;
                if ($diff > 0) {
                    for ($t = 0; $t < $diff; $t ++) {
                        $row .= '<td colspan="1" class="' . $style . '"> </td>';
                    }
                }
            }

            if (Kronolith::getDefaultCalendar(PERMS_EDIT)) {
                $addeventurl = Horde::applicationUrl('addevent.php');
                $addeventurl = Util::addParameter($addeventurl, 'timestamp', $hours[$i]['timestamp']);
                $addeventurl = Util::addParameter($addeventurl, 'url', Horde::selfUrl(true));
                $addeventurl = Horde::link($addeventurl, _("Create a New Event"), $hourclass);
            } else {
                $addeventurl = '';
            }

            if ($prefs->getValue('half')) {
                $rowspan = false;
                require $template_path . '/day/row.inc';
            } else {
                $rowspan = true;
                if ($i % 2) {
                    require $template_path . '/day/row_half.inc';
                } else {
                    require $template_path . '/day/row.inc';
                }
            }

            $first_row = false;
        }
        require $template_path . '/day/foot.inc';
    }

    /**
     * This function runs through the events and tries to figure out
     * what should be on each line of the output table. This is a
     * little tricky.
     *
     * @access public
     */
    function parse()
    {
        global $prefs;

        $tmp = array();
        $this->_all_day_maxrowspan = 0;

        // Separate out all day events and do some initialization/prep
        // for parsing.
        foreach ($this->_currentCalendars as $cid => $cal) {
            $this->_all_day_events[$cid] = array();
            $this->_all_day_rowspan[$cid] = 0;
        }

        foreach ($this->_events as $key => $event) {
            // If we have side_by_side we only want to include the
            // event in the proper calendar.
            if ($this->_sidebyside) {
                $cid = $event->getCalendar();
            } else {
                $cid = 0;
            }

            // All day events are easy; store them seperately.
            if ($event->isAllDay()) {
                $this->_all_day_events[$cid][] = $event;
                $this->_all_day_rowspan[$cid]++;
                $this->_all_day_maxrowspan = max($this->_all_day_maxrowspan, $this->_all_day_rowspan[$cid]);
            } else {
                // Initialize the number of events that this event
                // overlaps with.
                $event->overlap = 0;

                // Initialize this event's vertical span.
                $event->rowspan = 0;

                // Make sure that we're using the current date for
                // recurring events.
                if (!$event->hasRecurType(KRONOLITH_RECUR_NONE)) {
                    $event->start->mday = $this->mday;
                    $event->start->month = $this->month;
                    $event->start->year = $this->year;
                    $event->setStartTimestamp(Kronolith::objectToTimestamp($event->start));
                    $event->setEndTimestamp($event->startTimestamp + $event->durMin * 60);
                }
                $tmp[] = $event;
            }
        }
        $this->_events = $tmp;

        // Initialize the set of different rowspans needed.
        $spans = array(1 => true);

        // Track the last half-hour in which we have an event.
        $this->last = 0;
        $this->first = 48;

        // Run through every half-hour slot, adding in entries for
        // every event that we have here.
        for ($i = 0; $i < 48; $i++) {
            // Initialize this slot in the event matrix.
            foreach ($this->_currentCalendars as $cid => $cal) {
                $this->_event_matrix[$cid][$i] = array();
            }

            // Calculate the start and end timestamps for this slot.
            $start = mktime(floor($i / 2), ($i % 2) * 30, 0, $this->month, $this->mday, $this->year);
            $end = $start + (60 * 30);

            // Search through our events.
            foreach ($this->_events as $key => $event) {
                // If we have side_by_side we only want to include the
                // event in the proper calendar.
                if ($this->_sidebyside) {
                    $cid = $event->getCalendar();
                } else {
                    $cid = 0;
                }

                // If the event falls anywhere inside this slot, add
                // it, make sure other events know that they overlap
                // it, and increment the event's vertical span.
                if (($event->endTimestamp > $start && $event->startTimestamp < $end ) ||
                    ($event->endTimestamp == $event->startTimestamp && $event->startTimestamp == $start)) {

                    // Make sure we keep the latest hour than an event
                    // reaches up-to-date.
                    if ($i > $this->last) {
                        $this->last = $i;
                    }

                    // Make sure we keep the first hour than an event
                    // reaches up-to-date.
                    if ($i < $this->first) {
                        $this->first = $i;
                    }

                    // Add this event to the events which are in this
                    // row.
                    $this->_event_matrix[$cid][$i][] = $key;

                    // Increment the event's vertical span.
                    $this->_events[$key]->rowspan++;
                }
            }

            foreach ($this->_currentCalendars as $cid => $cal) {
                // Update the number of events that events in this row
                // overlap with.
                foreach ($this->_event_matrix[$cid][$i] as $ev) {
                    $this->_events[$ev]->overlap = max($this->_events[$ev]->overlap,
                                                    count($this->_event_matrix[$cid][$i]));
                }

                // Update the set of rowspans to include the value for
                // this row.
                $spans[$cid][count($this->_event_matrix[$cid][$i])] = true;
            }
        }

        foreach ($this->_currentCalendars as $cid => $cal) {
            // Sort every row by event duration, so that longer events are
            // farther to the left.
            for ($i = 0; $i <= $this->last; $i++) {
                if (count($this->_event_matrix[$cid][$i])) {
                    usort($this->_event_matrix[$cid][$i], array($this, '_sortByDuration'));
                }
            }

            // Now that we have the number of events in each row, we
            // can calculate the total span needed.
            $span[$cid] = 1;

            // Turn keys into array values.
            $spans[$cid] = array_keys($spans[$cid]);

            // Start with the biggest one first.
            rsort($spans[$cid]);
            foreach ($spans[$cid] as $s) {
                // If the number of events in this row doesn't divide
                // cleanly into the current total span, we need to
                // multiply the total span by the number of events in
                // this row.
                if ($span[$cid] % $s != 0) {
                    $span[$cid] *= $s;
                }
            }
            $this->_totalspan += $span[$cid];
        }
        // Set the final span.
        $this->_span = $span;

        // We're now parsed and ready to go.
        $this->_parsed = true;
    }

    function link($offset = 0)
    {
        $url = Horde::applicationUrl('day.php');
        $url = Util::addParameter($url, 'month', $this->getTime('%m', $offset));
        $url = Util::addParameter($url, 'mday', ltrim($this->getTime('%d', $offset)));
        $url = Util::addParameter($url, 'year', $this->getTime('%Y', $offset));

        return $url;
    }

    function _sortByDuration($evA, $evB)
    {
        $durA = $this->_events[$evA]->rowspan;
        $durB = $this->_events[$evB]->rowspan;

        if ($durA > $durB) {
            return -1;
        } elseif ($durA == $durB) {
            return 0;
        } else {
            return 1;
        }
    }

}

--- NEW FILE: Driver.php ---
<?php

require_once 'Horde/History.php';

/**
 * Kronolith_Driver:: defines an API for implementing storage backends
 * for Kronolith.
 *
 * $Horde: kronolith/lib/Driver.php,v 1.74 2004/05/26 20:58:12 chuck Exp $
 *
 * @author  Chuck Hagenbuch <chuck at horde.org>
 * @version $Revision: 1.1 $
 * @since   Kronolith 0.1
 * @package Kronolith
 */
class Kronolith_Driver {

    /**
     * A hash containing any parameters for the current driver.
[...1778 lines suppressed...]
        return $link;
    }

    function nextRecurrence($afterDate, $weekstart = KRONOLITH_SUNDAY)
    {
        $driver = &$this->getDriver();
        return $driver->nextRecurrence($this->eventID, $afterDate, $weekstart);
    }

    function getCalendar()
    {
        return $this->_calendar;
    }

    function setCalendar($calendar)
    {
        $this->_calendar = $calendar;
    }

}

--- NEW FILE: FBView.php ---
<?php

require_once 'Horde/Template.php';

/**
 * This class represent a view of multiple free busy information sets.
 *
 * Copyright 2003-2004 Mike Cochrane <mike at graftonhall.co.nz>
 *
 * See the enclosed file COPYING for license information.
 *
 * $Horde: kronolith/lib/FBView.php,v 1.5 2004/05/03 02:29:50 chuck Exp $
 *
 * @author  Mike Cochrane <mike at graftonhall.co.nz>
 * @package Kronolith
 */
class Kronolith_FreeBusy_View {

    var $_requiredMembers = array();
    var $_optionalMembers = array();

    function addRequiredMember(&$vFreebusy)
    {
        $this->_requiredMembers[] = $vFreebusy;
    }

    function addOptionalMember(&$vFreebusy)
    {
        $this->_optionalMembers[] = $vFreebusy;
    }

    /**
     * Attempts to return a concrete Kronolith_FreeBusy_View instance based on $view.
     *
     * @param string    $view       The type of concrete Kronolith_FreeBusy_View subclass
     *                              to return.
     *
     * @return mixed    The newly created concrete Kronolith_FreeBusy_View instance, or
     *                  false on an error.
     */
    function &factory($view)
    {
        $driver = basename($view);
        require_once dirname(__FILE__) . '/FBView/' . $view . '.php';
        $class = 'Kronolith_FreeBusy_View_' . $view;
        if (class_exists($class)) {
            return $ret = &new $class($user, $params);
        } else {
            return false;
        }
    }

    /**
     * Attempts to return a reference to a concrete
     * Kronolith_FreeBusy_View instance based on $view.  It will only
     * create a new instance if no Kronolith_FreeBusy_View instance
     * with the same parameters currently exists.
     *
     * This method must be invoked as: $var = &Kronolith_FreeBusy_View::singleton()
     *
     * @param string    $view       The type of concrete Kronolith_FreeBusy_View subclass
     *                              to return.
     *
     * @return mixed    The created concrete Kronolith_FreeBusy_View instance, or
     *                  false on an error.
     */
    function &singleton($view)
    {
        static $instances;

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

        if (!isset($instances[$view])) {
            $instances[$view] = &Kronolith_FreeBusy_View::factory($view);
        }

        return $instances[$view];
    }

}

--- NEW FILE: Kronolith.php ---
<?php

require_once KRONOLITH_BASE . '/lib/Driver.php';

define('KRONOLITH_RECUR_NONE',          0);
define('KRONOLITH_RECUR_DAILY',         1);
define('KRONOLITH_RECUR_WEEKLY',        2);
define('KRONOLITH_RECUR_DAY_OF_MONTH',  3);
define('KRONOLITH_RECUR_WEEK_OF_MONTH', 4);
define('KRONOLITH_RECUR_YEARLY',        5);

define('KRONOLITH_MONDAY',    0);
define('KRONOLITH_TUESDAY',   1);
define('KRONOLITH_WEDNESDAY', 2);
define('KRONOLITH_THURSDAY',  3);
define('KRONOLITH_FRIDAY',    4);
define('KRONOLITH_SATURDAY',  5);
define('KRONOLITH_SUNDAY',    6);

[...1427 lines suppressed...]
            $this->hour += 24;
        }

        while ($this->hour > 23) {
            $this->mday++;
            $this->hour -= 24;
        }

        while ($this->mday > Date_Calc::daysInMonth($this->month, $this->year)) {
            $this->month++;
            $this->mday -= Date_Calc::daysInMonth($this->month - 1, $this->year);
        }

        while ($this->month > 12) {
            $this->year++;
            $this->month -= 12;
        }
    }

}

--- NEW FILE: Storage.php ---
<?php

/**
 * Kronolith_Storage:: defines an API for storing free/busy information
 *
 * @author  Mike Cochrane <mike at graftonhall.co.nz>
 * @package Kronolith
 */
class Kronolith_Storage {

    /**
     * String containing the current username.
     * @var string $_user
     */
    var $_user = '';

    /**
     * Attempts to return a concrete Kronolith_Storage instance based on $driver.
     *
     * @param string    $driver     The type of concrete Kronolith_Storage subclass
     *                              to return.  The is based on the storage
     *                              driver ($driver).  The code is dynamically
     *                              included.
     *
     * @param string    $user       The name of the user who owns the free/busy
     *                              information
     *
     * @param array     $params     (optional) A hash containing any additional
     *                              configuration or connection parameters a
     *                              subclass might need.
     *
     * @return mixed    The newly created concrete Kronolith_Storage instance, or
     *                  false on an error.
     */
    function &factory($user = null, $driver = null, $params = null)
    {
        if (is_null($user)) {
            $user = Auth::getAuth();
        }

        if (is_null($driver)) {
            $driver = $GLOBALS['conf']['storage']['driver'];
        }

        $driver = basename($driver);

        if (is_null($params)) {
            $params = Horde::getDriverConfig('storage', $driver);
        }

        require_once dirname(__FILE__) . '/Storage/' . $driver . '.php';
        $class = 'Kronolith_Storage_' . $driver;
        if (class_exists($class)) {
            return $ret = &new $class($user, $params);
        } else {
            return false;
        }
    }

    /**
     * Attempts to return a reference to a concrete Kronolith_Storage instance
     * based on $driver.  It will only create a new instance if no
     * Kronolith_Storage instance with the same parameters currently exists.
     *
     * This should be used if multiple storage sources are required.
     *
     * This method must be invoked as: $var = &Kronolith_Storage::singleton()
     *
     * @param string    $driver     The type of concrete Kronolith_Storage subclass
     *                              to return.  The is based on the storage
     *                              driver ($driver).  The code is dynamically
     *                              included.
     *
     * @param string    $user       The name of the user who owns the free/busy
     *                              information
     *
     * @param array     $params     (optional) A hash containing any additional
     *                              configuration or connection parameters a
     *                              subclass might need.
     *
     * @return mixed    The created concrete Kronolith_Storage instance, or false
     *                  on error.
     */
    function &singleton($user = null, $driver = null, $params = null)
    {
        static $instances;

        if (is_null($user)) {
            $user = Auth::getAuth();
        }

        if (is_null($driver)) {
            $driver = $GLOBALS['conf']['storage']['driver'];
        }

        if (is_null($params)) {
            $params = Horde::getDriverConfig('storage', $driver);
        }

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

        $signature = serialize(array($user, $driver, $params));
        if (!isset($instances[$signature])) {
            $instances[$signature] = &Kronolith_Storage::factory($user, $driver, $params);
        }

        return $instances[$signature];
    }
}

--- NEW FILE: WeekView.php ---
<?php
/**
 * The Kronolith_WeekView:: class provides an API for viewing weeks.
 *
 * $Horde: kronolith/lib/WeekView.php,v 1.78 2004/05/27 17:51:54 chuck Exp $
 *
 * @author  Chuck Hagenbuch <chuck at horde.org>, Jan Schneider <jan at horde.org>
 * @version $Revision: 1.1 $
 * @since   Kronolith 0.1
 * @package Kronolith
 */
class Kronolith_WeekView {

    var $parsed = false;
    var $days = array();
    var $week = null;
    var $year = null;
    var $startDay = 0;
    var $endDay = 6;
    var $_sidebyside = false;
    var $_currentCalendars = array();

    function Kronolith_WeekView($week = null, $year = null, $startDay = null, $endDay = null)
    {
        if (empty($year)) {
            $year = date('Y');
        }
        if (empty($week)) {
            $week = Kronolith::weekOfYear(null, null, $year);
            if ($week == 1 && date('n') == 12) {
                $year++;
            }
        } else {
            if ($week < 1) {
                $year--;
                $week += Kronolith::weeksInYear($year);
            } elseif ($week > Kronolith::weeksInYear($year)) {
                $week -= Kronolith::weeksInYear($year);
                $year++;
            }
        }

        $this->year = $year;
        $this->week = $week;

        if (isset($startDay)) {
            $this->startDay = $startDay;
        }
        if (isset($endDay)) {
            $this->endDay = $endDay;
        }

        $firstDayOfWeek = Kronolith::firstDayOfWeek($week, $year);
        $firstDay = $firstDayOfWeek + Date_Calc::dateToDays(1, 1, $year) - 1;

        require_once KRONOLITH_BASE . '/lib/DayView.php';
        for ($i = $this->startDay; $i <= $this->endDay; $i++) {
            list($day, $month, $year) = explode('/', Date_Calc::daysToDate($firstDay + $i, '%d/%m/%Y'));
            $this->days[$i] = &new Kronolith_DayView($month, $day, $year, null, array());
        }

        list($sday, $smonth, $syear) = explode('/', Date_Calc::daysToDate($firstDay + $this->startDay, '%d/%m/%Y'));
        list($eday, $emonth, $eyear) = explode('/', Date_Calc::daysToDate($firstDay + $this->endDay, '%d/%m/%Y'));
        $startDate = Kronolith::timeStampToObject(mktime(0, 0, 0, $smonth, $sday, $syear));
        $endDate = Kronolith::timeStampToObject(mktime(23, 59, 59, $emonth, $eday, $eyear));
        $allevents = Kronolith::listEvents($startDate, $endDate, $GLOBALS['display_calendars']);
        for ($i = $this->startDay; $i <= $this->endDay; $i++) {
            $this->days[$i]->setEvents(isset($allevents[$this->days[$i]->getStamp()]) ?
                                       $allevents[$this->days[$i]->getStamp()] :
                                       array());
        }
        $this->_sidebyside = $this->days[$this->startDay]->_sidebyside;
        $this->_currentCalendars = $this->days[$this->startDay]->_currentCalendars;
    }

    function html($template_path = KRONOLITH_TEMPLATES)
    {
        global $prefs, $print_view, $cManager;

        $more_timeslots = $prefs->getValue('time_between_days');
        $include_all_events = !$prefs->getValue('show_shared_side_by_side');

        if (!$this->parsed) {
            $this->parse();
        }

        $hours = $this->days[$this->startDay]->hours;
        $cid = 0;
        if ($this->_sidebyside) {
            require $template_path . '/week/head_side_by_side.inc';
        } else {
            require $template_path . '/week/head.inc';
        }

        $event_count = 0;
        for ($j = $this->startDay; $j <= $this->endDay; $j++) {
            foreach ($this->_currentCalendars as $cid => $cal) {
                $event_count = max($event_count, count($this->days[$j]->_all_day_events[$cid]));
                reset($this->days[$j]->_all_day_events[$cid]);
            }
        }

        if ($more_timeslots) {
            $addeventurl = null;
        } else {
            $addeventurl = _("All day");
        }
        $rowspan = ' rowspan="1"';

        $first_row = true;
        $row = '';

        $colors = $cManager->colors();

        for ($j = $this->startDay; $j <= $this->endDay; $j++) {
            $row .= '<td class="hour" align="right">' . ($more_timeslots ? _("All day") : ' ') . '</td>';
            $row .= '<td colspan="' . $this->days[$j]->_totalspan . '" valign="top" style="padding:0px"><table border="0" width="100%" cellspacing="0" cellpadding="0">';
            if ($this->days[$j]->_all_day_maxrowspan > 0) {
                for ($k = 0; $k < $this->days[$j]->_all_day_maxrowspan; $k++) {
                    $row .= '<tr>';
                    foreach ($this->days[$j]->_currentCalendars as $cid => $cal) {
                        if (count($this->days[$j]->_all_day_events[$cid]) === $k) {
                            $row .= '<td rowspan="' . ($this->days[$j]->_all_day_maxrowspan - $k) . '" width="'. round(99/count($this->days[$j]->_currentCalendars)) . '%"> </td>';
                        } elseif (count($this->days[$j]->_all_day_events[$cid]) > $k) {
                            $event = $this->days[$j]->_all_day_events[$cid][$k];
                            $categoryColor = isset($colors[$event->getCategory()]) ? $colors[$event->getCategory()] : '#ccffcc';
                            $row .= '<td class="week-eventbox" style="background-color: ' . $categoryColor . '; ';
                            $row .= 'border-color: ' . Kronolith::borderColor($categoryColor) . '" ';
                            $row .= 'onmouseover="javascript:style.backgroundColor=\'' . Kronolith::highlightColor($categoryColor) . '\'" ';
                            $row .= 'onmouseout="javascript:style.backgroundColor=\'' . $categoryColor . '\'" ';
                            $row .= 'width="' . round(99/count($this->days[$j]->_currentCalendars)) . '%" ';
                            $row .= 'valign="top">';
                            $row .= $event->getLink($this->days[$j]->getStamp());
                            $row .= '</td>';
                        }
                    }
                    $row .= '</tr>';
                }
            } else {
                $row .= '<tr><td colspan="' . count($this->_currentCalendars) . '"> </td></tr>';
            }
            $row .= '</table></td>';
        }

        require $template_path . '/day/all_day.inc';

        $addeventurl = null;
        $rows = array();
        for ($i = 0; $i < 48; $i++) {
            if ($i >= $prefs->getValue('day_hour_end') && $i > $this->last) {
                break;
            }
            if ($i < $this->first && $i < $prefs->getValue('day_hour_start')) {
                continue;
            }

            if ($prefs->getValue('half') && $i % 2 != 0) {
                $time = ':30';
                $hourclass = 'halfhour';
            } else {
                $time = date(($prefs->getValue('twentyFour')) ? 'G' : 'ga', $hours[$i]['timestamp']);
                $hourclass = 'hour';
            }
            $style = ((($prefs->getValue('half')) ? $i : floor($i / 2)) % 2) ? 'item1' : 'item0';

            $row = '';
            for ($j = $this->startDay; $j <= $this->endDay; $j++) {
                // Add spacer between days, or timeslots.
                if ($more_timeslots) {
                    if ($prefs->getValue('half')) {
                        if ($i % 2 == 0) {
                            $row .= '<td align="right" class="hour">' . $time . '</td>';
                        } else {
                            $row .= '<td align="right" class="halfhour">' . $time . '</td>';
                        }
                    } else {
                        if ($i % 2 == 0) {
                            $row .= '<td rowspan="2" align="right" class="hour">' . $time . '</td>';
                        }
                    }
                } else {
                    $row .= '<td width="1%" class="text"> </td>';
                }
                foreach ($this->_currentCalendars as $cid => $cal) {
                    $hspan = 0;
                    foreach ($this->days[$j]->_event_matrix[$cid][$i] as $key) {
                        $event = $this->days[$j]->_events[$key];
                        if ($include_all_events || $event->getCalendar() == $cid) {
                            $start = mktime(floor($i/2), ($i % 2) * 30, 0, $this->days[$j]->month, $this->days[$j]->mday, $this->days[$j]->year);

                            // Since we've made sure that this event's
                            // overlap is a factor of the total span,
                            // we get this event's individual span by
                            // dividing the total span by this event's
                            // overlap.
                            $span = $this->days[$j]->_span[$cid] / $event->overlap;
                            $hspan += $span;

                            $categoryColor = isset($colors[$event->getCategory()]) ? $colors[$event->getCategory()] : $colors['_default_'];
                            if ($event->startTimestamp >= $start && $event->startTimestamp < $start + 60 * 30 || $start == $this->days[$j]->getStamp()) {
                                $row .= '<td class="week-eventbox" style="background-color: ' . $categoryColor . '; ';
                                $row .= 'border-color: ' . Kronolith::borderColor($categoryColor) . '" ';
                                $row .= 'onmouseover="javascript:style.backgroundColor=\'' . Kronolith::highlightColor($categoryColor) . '\'" ';
                                $row .= 'onmouseout="javascript:style.backgroundColor=\'' . $categoryColor . '\'" ';
                                $row .= 'valign="top" ';
                                $row .= 'width="' . floor(((90 / count($this->days)) / count($this->_currentCalendars)) * ($span / $this->days[$j]->_span[$cid])) . '%"';
                                $row .= 'colspan="' . $span . '" rowspan="' . $event->rowspan . '">';
                                $row .= $event->getLink($this->days[$j]->getStamp());
                                $row .= ' </td>';
                            }
                        }
                    }
                    $diff = $this->days[$j]->_span[$cid] - $hspan;

                    if ($diff > 0) {
                        for ($t = 0; $t < $diff; $t++) {
                            $row .= '<td colspan="1" class="' . $style . '"> </td>';
                        }
                    }
                }
            }

            if ($prefs->getValue('half')) {
                $rowspan = false;
                require $template_path . '/day/row.inc';
            } else {
                $rowspan = true;
                if ($i % 2) {
                    require $template_path . '/day/row_half.inc';
                } else {
                    require $template_path . '/day/row.inc';
                }
            }

            $first_row = false;
        }
        require $template_path . '/day/foot.inc';
    }

    /**
     * Parse all events for all of the days that we're handling; then
     * run through the results to get the total horizontal span for
     * the week, and the latest event of the week.
     *
     * @access public
     *
     * @return void
     */
    function parse()
    {
        for ($i = $this->startDay; $i <= $this->endDay; $i++) {
            $this->days[$i]->parse();
        }

        $this->totalspan = 0;
        $this->span = array();
        for ($i = $this->startDay; $i <= $this->endDay; $i++) {
            $this->totalspan += $this->days[$i]->_totalspan;
            foreach ($this->_currentCalendars as $cid => $key) {
                if (isset($this->span[$cid])) {
                    $this->span[$cid] += $this->days[$i]->_span[$cid];
                } else {
                    $this->span[$cid] = $this->days[$i]->_span[$cid];
                }
            }
        }

        $this->last = 0;
        $this->first = 48;
        for ($i = $this->startDay; $i <= $this->endDay; $i++) {
            if ($this->days[$i]->last > $this->last) {
                $this->last = $this->days[$i]->last;
            }
            if ($this->days[$i]->first < $this->first) {
                $this->first = $this->days[$i]->first;
            }
        }
    }

    function link($offset = 0)
    {
        $scriptName = basename($_SERVER['PHP_SELF']);
        $week = $this->week + $offset;
        $year = $this->year;
        if ($week < 1) {
            $year--;
            $week += Kronolith::weeksInYear($year);
        } elseif ($week > Kronolith::weeksInYear($year)) {
            $week -= Kronolith::weeksInYear($year);
            $year++;
        }
        $url = Util::addParameter($scriptName, 'week', $week);
        $url = Util::addParameter($url, 'year', $year);
        return Horde::applicationUrl($url);
    }

}

--- NEW FILE: api.php ---
<?php
/**
 * Kronolith external API interface.
 *
 * $Horde: kronolith/lib/api.php,v 1.113 2004/05/29 21:12:47 jan Exp $
 *
 * This file defines Kronolith's external API interface. Other
 * applications can interact with Kronolith through this API.
 *
 * @package Kronolith
 */

$_services['show'] = array(
    'link' => '%application%/viewevent.php?calendar=|calendar|' .
                ini_get('arg_separator.output') . 'eventID=|event|' .
                ini_get('arg_separator.output') . 'guid=|guid|'
);

$_services['block'] = array(
    'args' => array('type' => 'string', 'params' => 'stringArray'),
    'type' => 'stringArray'
);

$_services['defineBlock'] = array(
    'args' => array('type' => 'string'),
    'type' => 'string'
);

$_services['getFreeBusy'] = array(
    'args' => array('startstamp' => 'int', 'endstamp' => 'int', 'calendar' => 'string'),
    'type' => 'stringArray'
);

$_services['listCalendars'] = array(
    'args' => array('owneronly' => 'boolean', 'permission' => 'int'),
    'type' => 'stringArray'
);

$_services['list'] = array(
    'args' => array(),
    'type' => 'stringArray'
);

$_services['listBy'] = array(
    'args' => array('action' => 'string', 'timestamp' => 'int'),
    'type' => 'stringArray'
);

$_services['import'] = array(
    'args' => array('content' => 'string', 'contentType' => 'string', 'calendar' => 'string'),
    'type' => 'integer'
);

$_services['export'] = array(
    'args' => array('guid' => 'string', 'contentType' => 'string'),
    'type' => 'string'
);

$_services['remove'] = array(
    'args' => array('guid' => 'string'),
    'type' => 'boolean'
);

$_services['replace'] = array(
    'args' => array('guid' => 'string', 'content' => 'string', 'contentType' => 'string'),
    'type' => 'boolean'
);

$_services['eventFromGUID'] = array(
    'args' => array('guid' => 'string'),
    'type' => 'object'
);

$_services['updateAttendee'] = array(
    'args' => array('response' => 'object'),
    'type' => 'boolean'
);


/**
 * Return the requested block and include needed libs.
 */
function &_kronolith_block($block, $params)
{
    @define('KRONOLITH_BASE', dirname(__FILE__) . '/..');
    require_once KRONOLITH_BASE . '/lib/base.php';

    if (is_a(($blockClass = _kronolith_defineBlock($block)), 'PEAR_Error')) {
        return $blockClass;
    }

    return $ret = &new $blockClass($params);
}

function _kronolith_defineBlock($block)
{
    @define('KRONOLITH_BASE', dirname(__FILE__) . '/..');

    $blockClass = 'Horde_Block_Kronolith_' . $block;
    include_once KRONOLITH_BASE . '/lib/Block/' . $block . '.php';
    if (class_exists($blockClass)) {
        return $blockClass;
    } else {
        return PEAR::raiseError(sprintf(_("%s not found."), $blockClass));
    }
}

function _kronolith_listCalendars($owneronly = false, $permission = null)
{
    require_once dirname(__FILE__) . '/base.php';
    if (!isset($permission)) {
        $permission = PERMS_SHOW;
    }
    return array_keys(Kronolith::listCalendars($owneronly, $permission));
}

function _kronolith_list()
{
    require_once dirname(__FILE__) . '/base.php';
    $ids = Kronolith::listEventIds(0, new Kronolith_Date(array('year' => 9999, 'month' => 12, 'day' => 31)));
    if (is_a($ids, 'PEAR_Error')) {
        return $ids;
    }

    $guids = array();
    foreach ($ids as $cal) {
        $guids = array_merge($guids, array_keys($cal));
    }

    return $guids;
}

/**
 * Returns an array of GUIDs for events that have had $action happen
 * since $timestamp.
 *
 * @param integer $timestamp  The time to start the search.
 * @param string  $action     The action to check for - add, modify, or delete.
 *
 * @return array  An array of GUIDs matching the action and time criteria.
 */
function &_kronolith_listBy($action, $timestamp)
{
    require_once dirname(__FILE__) . '/base.php';
    require_once 'Horde/History.php';

    $history = &Horde_History::singleton();
    $histories = $history->getByTimestamp('>', $timestamp, array(array('op' => '=', 'field' => 'action', 'value' => $action)), 'kronolith');
    if (is_a($histories, 'PEAR_Error')) {
        return $histories;
    }

    return array_keys($histories);
}

/**
 * Import an event represented in the specified contentType.
 *
 * @param string $content      The content of the event.
 * @param string $contentType  What format is the data in? Currently supports:
 *                             text/x-icalendar
 *                             text/x-vcalendar
 *                             text/x-vevent
 * @param string $calendar     (optional) What calendar should the event be added to?
 *
 * @return string  The new GUID, or false on failure.
 */
function _kronolith_import($content, $contentType, $calendar = null)
{
    require_once dirname(__FILE__) . '/base.php';
    global $kronolith;

    if (!isset($calendar)) {
        $calendar = Kronolith::getDefaultCalendar(PERMS_EDIT);
    }
    if (!array_key_exists($calendar, Kronolith::listCalendars(false, PERMS_EDIT))) {
        return PEAR::raiseError(_("Permission Denied"));
    }
    $kronolith->open($calendar);

    switch ($contentType) {
    case 'text/calendar':
    case 'text/x-icalendar':
    case 'text/x-vcalendar':
    case 'text/x-vevent':
        if (!is_a($content, 'Horde_iCalendar_vevent')) {
            require_once 'Horde/iCalendar.php';
            $iCal = &new Horde_iCalendar();
            if (!$iCal->parsevCalendar($content)) {
                return PEAR::raiseError(_("There was an error importing the iCalendar data."));
            }

            $components = $iCal->getComponents();
            switch (count($components)) {
            case 0:
                return PEAR::raiseError(_("No iCalendar data was found."));

            case 1:
                $content = $components[0];
                if (!is_a($content, 'Horde_iCalendar_vevent')) {
                    return PEAR::raiseError(_("vEvent not found."));
                }
                break;

            default:
                return PEAR::raiseError(_("Multiple iCalendar components found; only one vEvent is supported."));
            }
        }

        $event = &$kronolith->getEvent();
        $event->fromiCalendar($content);

        $guid = $content->getAttribute('UID');
        if (!is_a($guid, 'PEAR_Error')) {
            $event->setID($guid);
        }

        $eventId = $event->save();
        break;

    default:
        return false;
    }

    if (is_a($eventId, 'PEAR_Error')) {
        return $eventId;
    }

    return $kronolith->getGUID($eventId);
}

/**
 * Export an event, identified by GUID, in the requested contentType.
 *
 * @param string $guid         Identify the event to export.
 * @param string $contentType  What format should the data be in? Currently supports:
 *                             text/x-icalendar
 *                             text/x-vcalendar
 *
 * @return string  The requested data.
 */
function _kronolith_export($guid, $contentType)
{
    require_once dirname(__FILE__) . '/base.php';
    global $kronolith, $kronolith_shares;

    $event = $kronolith->getByGUID($guid);
    if (is_a($event, 'PEAR_Error')) {
        return $event;
    }

    if (!array_key_exists($event->getCalendar(), Kronolith::listCalendars(false, PERMS_EDIT))) {
        return PEAR::raiseError(_("Permission Denied"));
    }

    switch ($contentType) {
    case 'text/calendar':
    case 'text/x-icalendar':
    case 'text/x-vcalendar':
        require_once 'Horde/Data.php';
        $vcs = &Horde_Data::singleton('icalendar');
        $identity = &$kronolith_shares->getIdentityByShare($kronolith_shares->getShare($event->getCalendar()));
        $data = array($event->toiCalendar($vcs, $identity));
        return $vcs->exportData($data);
    }

    return false;
}

/**
 * Delete an event identified by GUID.
 *
 * @param string $guid  Identify the event to delete.
 *
 * @return boolean  Success or failure.
 */
function _kronolith_remove($guid)
{
    require_once dirname(__FILE__) . '/base.php';
    global $kronolith;

    $event = $kronolith->getByGUID($guid);
    if (is_a($event, 'PEAR_Error')) {
        return $event;
    }

    if (!array_key_exists($event->getCalendar(), Kronolith::listCalendars(false, PERMS_DELETE))) {
        return PEAR::raiseError(_("Permission Denied"));
    }

    return $kronolith->deleteEvent($event->getID());
}

/**
 * Replace the event identified by GUID with the content represented
 * in the specified contentType.
 *
 * @param string $guid         Idenfity the event to replace.
 * @param string $content      The content of the event.
 * @param string $contentType  What format is the data in? Currently supports:
 *                             text/x-icalendar
 *                             text/x-vcalendar
 *                             text/x-vevent
 *
 * @return boolean  Success or failure.
 */
function _kronolith_replace($guid, $content, $contentType)
{
    require_once dirname(__FILE__) . '/base.php';
    global $kronolith;

    $event = $kronolith->getByGUID($guid);
    if (is_a($event, 'PEAR_Error')) {
        return $event;
    }

    if (!array_key_exists($event->getCalendar(), Kronolith::listCalendars(false, PERMS_EDIT))) {
        return PEAR::raiseError(_("Permission Denied"));
    }

    switch ($contentType) {
    case 'text/calendar':
    case 'text/x-icalendar':
    case 'text/x-vcalendar':
    case 'text/x-vevent':
        if (!is_a($content, 'Horde_iCalendar_vevent')) {
            require_once 'Horde/iCalendar.php';
            $iCal = &new Horde_iCalendar();
            if (!$iCal->parsevCalendar($content)) {
                return PEAR::raiseError(_("There was an error importing the iCalendar data."));
            }

            $components = $iCal->getComponents();
            switch (count($components)) {
            case 0:
                return PEAR::raiseError(_("No iCalendar data was found."));

            case 1:
                $content = $components[0];
                if (!is_a($content, 'Horde_iCalendar_vevent')) {
                    return PEAR::raiseError(_("vEvent not found."));
                }
                break;

            default:
                return PEAR::raiseError(_("Multiple iCalendar components found; only one vEvent is supported."));
            }
        }

        $event->fromiCalendar($content);

        $guid = $content->getAttribute('UID');
        if (!is_a($guid, 'PEAR_Error')) {
            $event->setID($guid);
        }

        $eventId = $event->save();
        break;

    default:
        return false;
    }

    return is_a($eventId, 'PEAR_Error') ? $eventId : true;
}

/**
 * Generate FreeBusy information for a given time period.
 *
 * @param integer $startstamp  (optional) The start of the time period to retrieve.
 * @param integer $endstamp    (optional) The end of the time period to retrieve.
 * @param string  $calendar    (optional) The calendar to view free/busy
 *                             slots for. Defaults to the user's default calendar.
 *
 * @return object Horde_iCalendar_vfreebusy  A freebusy object that covers the
 *                                           specified time period.
 */
function _kronolith_getFreeBusy($startstamp = null, $endstamp = null, $calendar = null)
{
    require_once dirname(__FILE__) . '/base.php';

    if (is_null($calendar)) {
        $calendar = Kronolith::getDefaultCalendar();
    }

    return Kronolith::generateFreeBusy($calendar, $startstamp, $endstamp, true);
}

/**
 * Retrieve a Kronolith_Event object, given an event GUID.
 *
 * @param string $guid    The events' GUID.
 *
 * @return object   A valid Kronolith_Event on success, or a PEAR_Error on failure.
 */
function &_kronolith_eventFromGUID($guid)
{
    require_once dirname(__FILE__) . '/base.php';
    global $kronolith;

    $event = $kronolith->getByGUID($guid);
    if (is_a($event, 'PEAR_Error')) {
        return $event;
    }

    if (!array_key_exists($event->getCalendar(), Kronolith::listCalendars(false, PERMS_SHOW))) {
        return PEAR::raiseError(_("Permission Denied"));
    }

    return $event;
}

/**
 * Update an attendees response status for a specified event.
 *
 * @param object $response    A Horde_iCalender_vevent objext, with a valid
 *                            UID attribute that points to an existing event.
 *                            This is typically the vEvent portion of an iTip
 *                            meeting-request response, with the attendees'
 *                            response in an ATTENDEE parameter.
 *
 * @return mixed   (boolean) true on success.
 *                 (object)  PEAR_Error on failure.
 */
function _kronolith_updateAttendee($response)
{
    require_once dirname(__FILE__) . '/base.php';
    global $kronolith;

    $guid = $response->getAttribute('UID');
    if (is_a($guid, 'PEAR_Error')) {
        return $guid;
    }

    $event = $kronolith->getByGUID($guid);
    if (is_a($event, 'PEAR_Error')) {
        return $event;
    }

    if (!array_key_exists($event->getCalendar(), Kronolith::listCalendars(false, PERMS_EDIT))) {
        return PEAR::raiseError(_("Permission Denied"));
    }

    $atnames = $response->getAttribute('ATTENDEE');
    $atparms = $response->getAttribute('ATTENDEE', true);

    if (!is_array($atnames)) {
        $atnames = array($atnames);
    }
    foreach ($atnames as $index => $attendee) {
        $event->addAttendee(str_replace('MAILTO:', '', $attendee), KRONOLITH_PART_IGNORE, Kronolith::responseFromICal($atparms[$index]['PARTSTAT']));
    }

    $res = $event->save();
    if (is_a($res, 'PEAR_Error')) {
        return $res;
    }

    return true;
}

--- NEW FILE: base.php ---
<?php
/**
 * Kronolith base inclusion file.
 *
 * $Horde: kronolith/lib/base.php,v 1.112 2004/05/22 02:28:54 chuck Exp $
 *
 * This file brings in all of the dependencies that every Kronolith
 * script will need, and sets up objects that all scripts use.
 */

/* Check for a prior definition of HORDE_BASE (perhaps by an
 * auto_prepend_file definition for site customization). */
if (!defined('HORDE_BASE')) {
    @define('HORDE_BASE', dirname(__FILE__) . '/../..');
}

/* Load the Horde Framework core, and set up inclusion paths. */
require_once HORDE_BASE . '/lib/core.php';

/* Registry. */
$registry = &Registry::singleton();
if (is_a(($pushed = $registry->pushApp('kronolith', !defined('AUTH_HANDLER'))), 'PEAR_Error')) {
    if ($pushed->getCode() == 'permission_denied') {
        Horde::authenticationFailureRedirect(); 
    }
    Horde::fatal($pushed, __FILE__, __LINE__, false);
}
$conf = &$GLOBALS['conf'];
@define('KRONOLITH_TEMPLATES', $registry->getParam('templates'));

/* Find the base file path of Kronolith. */
@define('KRONOLITH_BASE', dirname(__FILE__) . '/..');

/* Kronolith base library. */
require_once KRONOLITH_BASE . '/lib/Kronolith.php';

/* Notification system. */
require_once KRONOLITH_BASE . '/lib/Notification/Listener/status.php';
$notification = &Notification::singleton();
$notification->attach('status', null, 'Notification_Listener_status_kronolith');

/* Horde base libraries. */
require_once 'Horde/Image.php';
require_once 'Horde/Help.php';

/* Categories. */
require_once 'Horde/Prefs/CategoryManager.php';
$GLOBALS['cManager'] = &new Prefs_CategoryManager();

/* PEAR Date_Calc. */
require_once 'Date/Calc.php';

/* Start compression, if requested. */
Horde::compressOutput();

/* Set the timezone variable, if available. */
NLS::setTimeZone();

/* Create a share instance. */
require_once 'Horde/Share.php';
$GLOBALS['kronolith_shares'] = &Horde_Share::singleton($registry->getApp());

/* Update the preference for what calendars to display. If the user
 * doesn't have any selected calendars to view then fall back to an
 * available calendar. */
$GLOBALS['display_calendars'] = unserialize($GLOBALS['prefs']->getValue('display_cals'));
$GLOBALS['display_remote_calendars'] = unserialize($GLOBALS['prefs']->getValue('display_remote_cals'));
if (($d_cal = Util::getFormData('display_cal')) !== null) {
    if (substr($d_cal, 0, 7) == 'remote_') {
        $d_cal = urldecode(substr($d_cal, 7));
        if (in_array($d_cal, $GLOBALS['display_remote_calendars'])) {
            $key = array_search($d_cal, $GLOBALS['display_remote_calendars']);
            unset($GLOBALS['display_remote_calendars'][$key]);
        } else {
            $GLOBALS['display_remote_calendars'][] = $d_cal;
        }
    } else {
        if (in_array($d_cal, $GLOBALS['display_calendars'])) {
            $key = array_search($d_cal, $GLOBALS['display_calendars']);
            unset($GLOBALS['display_calendars'][$key]);
        } else {
            $GLOBALS['display_calendars'][] = $d_cal;
        }
    }
}

/* Make sure all shares exists now to save on checking later. */
$GLOBALS['all_calendars'] = Kronolith::listCalendars();
$calendar_keys = array_values($GLOBALS['display_calendars']);
$GLOBALS['display_calendars'] = array();
foreach ($calendar_keys as $id) {
    if (isset($GLOBALS['all_calendars'][$id])) {
        $GLOBALS['display_calendars'][] = $id;
    }
}

/* Make sure all the remote calendars still exist. */
$_temp = $GLOBALS['display_remote_calendars'];
$_all = unserialize($GLOBALS['prefs']->getValue('remote_cals'));
$GLOBALS['display_remote_calendars'] = array();
foreach ($_all as $id) {
    if (in_array($id['url'], $_temp)) {
        $GLOBALS['display_remote_calendars'][] = $id['url'];
    }
}
$GLOBALS['prefs']->setValue('display_remote_cals', serialize($GLOBALS['display_remote_calendars']));

if (count($GLOBALS['display_calendars']) == 0) {
    $cals = Kronolith::listCalendars(true);
    if (!Auth::getAuth()) {
        /* All calendars for guests. */
        $GLOBALS['display_calendars'] = array_keys($cals);
    } elseif (!count($cals)) {
        /* Create a personal calendar. */
        $GLOBALS['display_calendars'] = array(Auth::getAuth());

        /* If this share doesn't exist then create it. */
        if (!$GLOBALS['kronolith_shares']->exists(Auth::getAuth())) {
            require_once 'Horde/Identity.php';
            $identity = &Identity::singleton();
            $name = $identity->getValue('fullname');
            if (trim($name) == '') {
                $name = Auth::removeHook(Auth::getAuth());
            }
            $share = &$GLOBALS['kronolith_shares']->newShare(Auth::getAuth());
            $share->set('owner', Auth::getAuth());
            $share->set('name', sprintf(_("%s's Calendar"), $name));
            $GLOBALS['kronolith_shares']->addShare($share);
            $GLOBALS['all_calendars'][Auth::getAuth()] = $share;
        }
    }
}

$GLOBALS['prefs']->setValue('display_cals', serialize($GLOBALS['display_calendars']));

/* Create a calendar backend object. */
$GLOBALS['kronolith'] = &Kronolith_Driver::factory();

--- NEW FILE: prefs.php ---
<?php
/**
 * $Horde: kronolith/lib/prefs.php,v 1.3 2004/05/18 19:57:58 chuck Exp $
 *
 * Copyright 2001-2004 Jon Parise <jon at horde.org>
 *
 * See the enclosed file COPYING for license information (GPL).  If you
 * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
 */

function handle_remote_cal_management($updated)
{
    global $prefs;

    $calName = Util::getFormData('remote_name');
    $calUrl  = Util::getFormData('remote_url');
    $calActionID = Util::getFormData('remote_action', 'add');

    if ($calActionID == 'add') {
        if (!empty($calName) && !empty($calUrl)) {
            $cals = unserialize($prefs->getValue('remote_cals'));
            $cals[] = array('name' => $calName,
                            'url'  => $calUrl);
            $prefs->setValue('remote_cals', serialize($cals));                
            $updated = true;
            return false;
        }
    } else if ($calActionID == 'delete') {
        $cals = unserialize($prefs->getValue('remote_cals'));
        foreach ($cals as $key => $cal) {
            if ($cal['url'] == $calUrl) {
                unset($cals[$key]);
                break;
            }
        }
        $prefs->setValue('remote_cals', serialize($cals));                
        $updated = true;
        return false;
    }
    return true;
}

function handle_shareselect($updated)
{
    $default_share = Util::getFormData('default_share');
    if (!is_null($default_share)) {
        $sharelist = Kronolith::listCalendars();
        if ((is_array($sharelist)) > 0 && isset($sharelist[$default_share])) {
            $GLOBALS['prefs']->setValue('default_share', $default_share);
            return true;
        }
    }

    return false;
}

if (!$prefs->isLocked('day_hour_start') || !$prefs->isLocked('day_hour_end')) {
    $day_hour_start_options = array();
    for ($i = 0; $i <= 48; $i++) {
        $day_hour_start_options[$i] = date(($prefs->getValue('twentyFour')) ? 'G:i' : 'g:ia', mktime(0, $i * 30, 0));
    }
    $day_hour_end_options = $day_hour_start_options;
}

--- NEW FILE: version.php ---
<?php define('KRONOLITH_VERSION', '2.0-cvs') ?>





More information about the commits mailing list