');
tbody.append(tr);
}
// Insert day cell.
td = $('').attr({ id: 'kronolithMonth' + dateString })
.addClass('kronolithMonthDay')
.jqmData('date', dateString);
if (day.getMonth() != date.getMonth()) {
td.addClass('kronolithMinicalEmpty');
}
// Highlight today.
if (day.dateString() == today.dateString()) {
td.addClass('kronolithToday');
}
td.html(day.getDate());
tr.append(td);
day.next().day();
}
},
/**
* Parses a date attribute string into a Date object.
*
* For other strings use Date.parse().
*
* @param string date A yyyyMMdd date string.
*
* @return Date A date object.
*/
parseDate: function(date)
{
var d = new Date(date.substr(0, 4), date.substr(4, 2) - 1, date.substr(6, 2));
if (date.length == 12) {
d.setHours(date.substr(8, 2));
d.setMinutes(date.substr(10, 2));
}
return d;
},
storeCache: function(events, calendar, dates, createCache)
{
events = events || {};
//calendar[0] == type, calendar[1] == calendar name
calendar = calendar.split('|');
if (!KronolithMobile.ecache[calendar[0]]) {
if (!createCache) {
return;
}
KronolithMobile.ecache[calendar[0]] = {};
}
if (!KronolithMobile.ecache[calendar[0]][calendar[1]]) {
if (!createCache) {
return;
}
KronolithMobile.ecache[calendar[0]][calendar[1]] = {};
}
var calHash = KronolithMobile.ecache[calendar[0]][calendar[1]];
// Create empty cache entries for all dates.
if (!!dates) {
var day = dates[0].clone(), date;
while (!day.isAfter(dates[1])) {
date = day.dateString();
if (!calHash[date]) {
if (!createCache) {
return;
}
if (!KronolithMobile.cacheStart || KronolithMobile.cacheStart.isAfter(day)) {
KronolithMobile.cacheStart = day.clone();
}
if (!KronolithMobile.cacheEnd || KronolithMobile.cacheEnd.isBefore(day)) {
KronolithMobile.cacheEnd = day.clone();
}
calHash[date] = {};
}
day.add(1).day();
}
}
var cal = calendar.join('|');
$.each(events, function(key, date) {
// We might not have a cache for this date if the event lasts
// longer than the current view
if (typeof calHash[key] == 'undefined') {
return;
}
// Store useful information in event objects.
$.each(date, function(k, event) {
event.calendar = cal;
event.start = Date.parse(event.s);
event.end = Date.parse(event.e);
event.sort = event.start.toString('HHmmss')
+ (240000 - parseInt(event.end.toString('HHmmss'), 10)).toPaddedString(6);
event.id = k;
});
// Store events in cache.
$.extend(calHash[key], date);
});
},
/**
* Return all events for a single day from all displayed calendars merged
* into a single hash.
*
* @param string date A yyyymmdd date string.
*
* @return Hash An event hash which event ids as keys and event objects as
* values.
*/
getCacheForDate: function(date, calendar)
{
if (calendar) {
var cals = calendar.split('|');
return KronolithMobile.ecache[cals[0]][cals[1]][date];
}
var events = {};
$.each(KronolithMobile.ecache, function(key, type) {
$.each(type, function(id, cal) {
if (!Kronolith.conf.calendars[key][id].show) {
return;
}
if (typeof cal[date] != 'undefined') {
$.extend(events, cal[date]);
}
});
});
return events;
},
/**
* Handle swipe events for the current view.
*/
handleSwipe: function(map)
{
switch (KronolithMobile.view) {
case 'day':
if (map.type == 'swipeleft') {
KronolithMobile.showNextDay();
} else {
KronolithMobile.showPrevDay();
}
break;
case 'month':
if (map.type == 'swipeleft') {
KronolithMobile.showNextMonth();
} else {
KronolithMobile.showPrevMonth();
}
}
},
/**
* Event handler for the pagebeforechange event that implements loading of
* deep-linked pages.
*
* @param object e Event object.
* @param object data Event data.
*/
toPage: function(e, data)
{
switch (data.options.parsedUrl.view) {
case 'minical-next':
KronolithMobile.showNextMonth();
e.preventDefault();
break;
case 'minical-prev':
KronolithMobile.showPrevMonth();
e.preventDefault();
break;
case 'nextday':
KronolithMobile.showNextDay();
e.preventDefault();
break;
case 'prevday':
KronolithMobile.showPrevDay();
e.preventDefault();
break;
}
},
/**
*/
loadPage: function()
{
switch (HordeMobile.currentPage()) {
case 'monthview':
KronolithMobile.view = "month";
// (re)build the minical only if we need to
if (!$("#kronolithMinicalDate").jqmData("date") ||
($("#kronolithMinicalDate").jqmData("date").toString("M") != KronolithMobile.date.toString("M"))) {
KronolithMobile.moveToMonth(KronolithMobile.date);
}
break;
case 'overview':
KronolithMobile.view = "overview";
if (!KronolithMobile.haveOverview) {
KronolithMobile.loadEvents(KronolithMobile.date, KronolithMobile.date.clone().addDays(7), "overview");
KronolithMobile.haveOverview = true;
}
break;
case null:
break;
case 'dayview':
default:
KronolithMobile.view = "day";
$("#kronolithDayDate").html(KronolithMobile.date.toString("ddd") + " " + KronolithMobile.date.toString("d"));
KronolithMobile.loadEvents(KronolithMobile.date, KronolithMobile.date, "day");
break;
}
},
onDocumentReady: function()
{
KronolithMobile.date = new Date();
// Build list of calendars we want.
$.each(Kronolith.conf.calendars, function(key, value) {
$.each(value, function(cal, info) {
if (info.show) {
KronolithMobile.calendars.push([key, cal]);
}
});
});
// Bind click and swipe events
$('body').bind('swipeleft', KronolithMobile.handleSwipe)
.bind('swiperight', KronolithMobile.handleSwipe);
$(document).bind('pageshow', KronolithMobile.loadPage)
.bind('pagebeforechange', KronolithMobile.toPage)
.on("pageshow", "#eventview", function(event, ui) {
KronolithMobile.view = "event";
});
$('#kronolith-minical').on('click', 'td', function(e) {
KronolithMobile.selectMonthDay($(e.target).jqmData('date'));
});
// Load initial view.
KronolithMobile.loadPage();
}
};
$(KronolithMobile.onDocumentReady);
kronolith-4.2.13/js/views.js 0000664 0000765 0000024 00000000744 12654566222 012660 0 ustar var eventTabs = null;
function ShowTab(tab)
{
if (eventTabs === null) {
eventTabs = $('page').select('.tabset ul li');
}
eventTabs.each(function(c) {
var t = $(c.id.substring(3));
if (!t) {
return;
}
if (c.id == 'tab' + tab) {
c.addClassName('horde-active');
t.show();
} else {
c.removeClassName('horde-active');
t.hide();
}
});
return false;
}
kronolith-4.2.13/lib/Ajax/Application/Handler.php 0000664 0000765 0000024 00000201556 12654566222 016537 0 ustar
* @author Jan Schneider
* @author Gonçalo Queirós
* @category Horde
* @license http://www.horde.org/licenses/gpl GPL
* @package Kronolith
*/
class Kronolith_Ajax_Application_Handler extends Horde_Core_Ajax_Application_Handler
{
protected $_external = array('embed');
/**
* Just polls for alarm messages and keeps session fresh for now.
*/
public function poll()
{
return false;
}
/**
* Returns a list of all calendars.
*/
public function listCalendars()
{
Kronolith::initialize();
$all_external_calendars = $GLOBALS['calendar_manager']->get(Kronolith::ALL_EXTERNAL_CALENDARS);
$result = new stdClass;
$auth_name = $GLOBALS['registry']->getAuth();
// Calendars. Do some twisting to sort own calendar before shared
// calendars.
foreach (array(true, false) as $my) {
foreach ($GLOBALS['calendar_manager']->get(Kronolith::ALL_CALENDARS) as $id => $calendar) {
$owner = ($auth_name && ($calendar->owner() == $auth_name));
if (($my && $owner) || (!$my && !$owner)) {
$result->calendars['internal'][$id] = $calendar->toHash();
}
}
// Tasklists
if (Kronolith::hasApiPermission('tasks')) {
foreach ($GLOBALS['registry']->tasks->listTasklists($my, Horde_Perms::SHOW, false) as $id => $tasklist) {
if (isset($all_external_calendars['tasks/' . $id])) {
$owner = ($auth_name &&
($tasklist->get('owner') == $auth_name));
if (($my && $owner) || (!$my && !$owner)) {
$result->calendars['tasklists']['tasks/' . $id] =
$all_external_calendars['tasks/' . $id]->toHash();
}
}
}
}
}
// Resources
if (!empty($GLOBALS['conf']['resource']['driver'])) {
foreach (Kronolith::getDriver('Resource')->listResources() as $resource) {
if ($resource->get('type') != Kronolith_Resource::TYPE_GROUP) {
$rcal = new Kronolith_Calendar_Resource(array(
'resource' => $resource
));
$result->calendars['resource'][$resource->get('calendar')] = $rcal->toHash();
} else {
$rcal = new Kronolith_Calendar_ResourceGroup(array(
'resource' => $resource
));
$result->calendars['resourcegroup'][$resource->getId()] = $rcal->toHash();
}
}
}
// Timeobjects
foreach ($all_external_calendars as $id => $calendar) {
if ($calendar->api() != 'tasks' && $calendar->display()) {
$result->calendars['external'][$id] = $calendar->toHash();
}
}
// Remote calendars
foreach ($GLOBALS['calendar_manager']->get(Kronolith::ALL_REMOTE_CALENDARS) as $url => $calendar) {
$result->calendars['remote'][$url] = $calendar->toHash();
}
// Holidays
foreach ($GLOBALS['calendar_manager']->get(Kronolith::ALL_HOLIDAYS) as $id => $calendar) {
$result->calendars['holiday'][$id] = $calendar->toHash();
}
return $result;
}
/**
* TODO
*/
public function listEvents()
{
global $session;
$start = new Horde_Date($this->vars->start);
$end = new Horde_Date($this->vars->end);
$result = $this->_signedResponse($this->vars->cal);
if (!($kronolith_driver = $this->_getDriver($this->vars->cal))) {
return $result;
}
try {
$session->close();
$events = $kronolith_driver->listEvents($start, $end, array(
'show_recurrence' => true,
'json' => true)
);
$session->start();
if (count($events)) {
$result->events = $events;
}
} catch (Exception $e) {
$GLOBALS['notification']->push($e, 'horde.error');
}
return $result;
}
/**
* Returns a JSON object representing the requested event.
*
* Request variables used:
* - cal: The calendar id
* - id: The event id
* - date: The date of the event we are requesting [OPTIONAL]
* - rsd: The event start date of the instance of a recurring event, if
* requesting a specific instance.
* - red: The event end date of the instance of a recurring event, if
* requesting a specific instance.
*/
public function getEvent()
{
$result = new stdClass;
if (!($kronolith_driver = $this->_getDriver($this->vars->cal)) ||
!isset($this->vars->id)) {
return $result;
}
try {
$event = $kronolith_driver->getEvent($this->vars->id, $this->vars->date);
$event->setTimezone(true);
$result->event = $event->toJson(null, true, $GLOBALS['prefs']->getValue('twentyFour') ? 'H:i' : 'h:i A');
// If recurring, we need to format the dates of this instance, since
// Kronolith_Driver#getEvent will return the start/end dates of the
// original event in the series.
if ($event->recurs() && $this->vars->rsd) {
$rs = new Horde_Date($this->vars->rsd);
$result->event->rsd = $rs->strftime('%x');
$re = new Horde_Date($this->vars->red);
$result->event->red = $re->strftime('%x');
}
} catch (Horde_Exception_NotFound $e) {
$GLOBALS['notification']->push(_("The requested event was not found."), 'horde.error');
} catch (Exception $e) {
$GLOBALS['notification']->push($e, 'horde.error');
}
return $result;
}
/**
* Save a new or update an existing event from the AJAX event detail view.
*
* Request parameters used:
* - event: The event id.
* - cal: The calendar id.
* - targetcalendar: If moving events, the targetcalendar to move to.
* - as_new: Save an existing event as a new event.
* - recur_edit: If editing an instance of a recurring event series,
* how to apply the edit [current|future|all].
* - rstart: If editing an instance of a recurring event series,
* the original start datetime of this instance.
* - rend: If editing an instance of a recurring event series,
* the original ending datetime of this instance.
* - sendupdates: Should updates be sent to attendees?
* - cstart: Start time of the client cache.
* - cend: End time of the client cache.
*/
public function saveEvent()
{
global $injector, $notification, $registry;
$result = $this->_signedResponse($this->vars->targetcalendar);
if (!($kronolith_driver = $this->_getDriver($this->vars->targetcalendar))) {
return $result;
}
if ($this->vars->as_new) {
unset($this->vars->event);
}
if (!$this->vars->event) {
$perms = $injector->getInstance('Horde_Core_Perms');
if ($perms->hasAppPermission('max_events') !== true &&
$perms->hasAppPermission('max_events') <= Kronolith::countEvents()) {
Horde::permissionDeniedError(
'kronolith',
'max_events',
sprintf(
_("You are not allowed to create more than %d events."),
$perms->hasAppPermission('max_events')
)
);
return $result;
}
}
if ($this->vars->event &&
$this->vars->cal &&
$this->vars->cal != $this->vars->targetcalendar) {
if (strpos($kronolith_driver->calendar, '\\')) {
list($target, $user) = explode(
'\\', $kronolith_driver->calendar, 2
);
} else {
$target = $kronolith_driver->calendar;
$user = $registry->getAuth();
}
$kronolith_driver = $this->_getDriver($this->vars->cal);
// Only delete the event from the source calendar if this user has
// permissions to do so.
try {
$sourceShare = Kronolith::getInternalCalendar(
$kronolith_driver->calendar
);
$share = Kronolith::getInternalCalendar($target);
if ($sourceShare->hasPermission($registry->getAuth(), Horde_Perms::DELETE) &&
(($user == $registry->getAuth() &&
$share->hasPermission($registry->getAuth(), Horde_Perms::EDIT)) ||
($user != $registry->getAuth() &&
$share->hasPermission($registry->getAuth(), Kronolith::PERMS_DELEGATE)))) {
$kronolith_driver->move($this->vars->event, $target);
$kronolith_driver = $this->_getDriver($this->vars->targetcalendar);
}
} catch (Exception $e) {
$notification->push(
sprintf(
_("There was an error moving the event: %s"),
$e->getMessage()
),
'horde.error'
);
return $result;
}
}
if ($this->vars->as_new) {
$event = $kronolith_driver->getEvent();
} else {
try {
$event = $kronolith_driver->getEvent($this->vars->event);
} catch (Horde_Exception_NotFound $e) {
$notification->push(
_("The requested event was not found."),
'horde.error'
);
return $result;
} catch (Exception $e) {
$notification->push($e);
return $result;
}
}
if (!$event->hasPermission(Horde_Perms::EDIT)) {
$notification->push(
_("You do not have permission to edit this event."),
'horde.warning'
);
return $result;
}
$removed_attendees = $old_attendees = array();
if ($this->vars->recur_edit && $this->vars->recur_edit != 'all') {
switch ($this->vars->recur_edit) {
case 'current':
$attributes = new stdClass();
$attributes->rstart = $this->vars->rstart;
$attributes->rend = $this->vars->rend;
$this->_addException($event, $attributes);
// Create a copy of the original event so we can read in the
// new form values for the exception. We also MUST reset the
// recurrence property even though we won't be using it, since
// clone() does not do a deep copy. Otherwise, the original
// event's recurrence will become corrupt.
$newEvent = clone($event);
$newEvent->recurrence = new Horde_Date_Recurrence($event->start);
$newEvent->readForm($event);
// Create an exception event from the new properties.
$exception = $this->_copyEvent($event, $newEvent, $attributes);
$exception->start = $newEvent->start;
$exception->end = $newEvent->end;
// Save the new exception.
$attributes->cstart = $this->vars->cstart;
$attributes->cend = $this->vars->cend;
$result = $this->_saveEvent(
$exception,
$event,
$attributes);
break;
case 'future':
$instance = new Horde_Date($this->vars->rstart, $event->timezone);
$exception = clone($instance);
$exception->mday--;
if ($event->end->compareDate($exception) > 0) {
// Same as 'all' since this is the first recurrence.
$this->vars->recur_edit = 'all';
return $this->saveEvent();
} else {
$event->recurrence->setRecurEnd($exception);
$newEvent = $kronolith_driver->getEvent();
$newEvent->readForm();
$newEvent->uid = null;
$result = $this->_saveEvent(
$newEvent, $event, $this->vars, true
);
}
}
} else {
try {
$old_attendees = $event->attendees;
$event->readForm();
$removed_attendees = array_diff(
array_keys($old_attendees),
array_keys($event->attendees)
);
$result = $this->_saveEvent($event);
} catch (Exception $e) {
$notification->push($e);
return $result;
}
}
if (($result !== true) && $this->vars->sendupdates) {
$type = $event->status == Kronolith::STATUS_CANCELLED
? Kronolith::ITIP_CANCEL
: Kronolith::ITIP_REQUEST;
Kronolith::sendITipNotifications($event, $notification, $type);
}
// Send a CANCEL iTip for attendees that have been removed, but only if
// the entire event isn't being marked as cancelled (which would be
// caught above).
if (!empty($removed_attendees)) {
$to_cancel = array();
foreach ($removed_attendees as $email) {
$to_cancel[$email] = $old_attendees[$email];
}
$cancelEvent = clone $event;
Kronolith::sendITipNotifications(
$cancelEvent, $notification, Kronolith::ITIP_CANCEL, null, null, $to_cancel
);
}
Kronolith::notifyOfResourceRejection($event);
return $result;
}
/**
* TODO
*/
public function quickSaveEvent()
{
$cal = explode('|', $this->vars->cal, 2);
try {
$event = Kronolith::quickAdd($this->vars->text, $cal[1]);
return $this->_saveEvent($event);
} catch (Horde_Exception $e) {
$GLOBALS['notification']->push($e);
$result = $this->_signedResponse($this->vars->cal);
$result->error = true;
return $result;
}
}
/**
* Update event details as a result of a drag/drop operation (which would
* only affect the event's start/end times).
*
* Uses the following request variables:
*
* -cal: The calendar id.
* -id: The event id.
* -att: Attribute hash of changed values. Can contain:
* -start: A new start datetime for the event.
* -end: A new end datetime for the event.
* -offDays: An offset of days to apply to the event.
* -offMins: An offset of minutes to apply to the event.
* -rstart: The orginal start datetime of a series instance.
* -rend: The original end datetime of a series instance.
* -rday: A new start value for a series instance (used when
* dragging on the month view where only the date can
* change, and not the start/end times).
* -u: Send update to attendees.
*
*/
public function updateEvent()
{
$result = $this->_signedResponse($this->vars->cal);
if (!($kronolith_driver = $this->_getDriver($this->vars->cal)) ||
!isset($this->vars->id)) {
return $result;
}
try {
$oevent = $kronolith_driver->getEvent($this->vars->id);
} catch (Exception $e) {
$GLOBALS['notification']->push($e, 'horde.error');
return $result;
}
if (!$oevent) {
$GLOBALS['notification']->push(_("The requested event was not found."), 'horde.error');
return $result;
} elseif (!$oevent->hasPermission(Horde_Perms::EDIT)) {
$GLOBALS['notification']->push(_("You do not have permission to edit this event."), 'horde.warning');
return $result;
}
$attributes = Horde_Serialize::unserialize($this->vars->att, Horde_Serialize::JSON);
// If this is a recurring event, need to create an exception.
if ($oevent->recurs()) {
$this->_addException($oevent, $attributes);
$event = $this->_copyEvent($oevent, null, $attributes);
} else {
$event = clone($oevent);
}
foreach ($attributes as $attribute => $value) {
switch ($attribute) {
case 'start':
$newDate = new Horde_Date($value);
$newDate->setTimezone($event->start->timezone);
$event->start = clone($newDate);
break;
case 'end':
$newDate = new Horde_Date($value);
$newDate->setTimezone($event->end->timezone);
$event->end = clone($newDate);
if ($event->end->hour == 23 &&
$event->end->min == 59 &&
$event->end->sec == 59) {
$event->end->mday++;
$event->end->hour = $event->end->min = $event->end->sec = 0;
}
break;
case 'offDays':
$event->start->mday += $value;
$event->end->mday += $value;
break;
case 'offMins':
$event->start->min += $value;
$event->end->min += $value;
break;
}
}
$result = $this->_saveEvent($event, ($oevent->recurs() ? $oevent : null), $attributes);
if ($this->vars->u) {
Kronolith::sendITipNotifications($event, $GLOBALS['notification'], Kronolith::ITIP_REQUEST);
}
return $result;
}
/**
* Deletes an event, or an instance of an event series from the backend.
*
* Uses the following request variables:
*
* - cal: The calendar id.
* - id: The event id.
* - r: If this is an event series, what type of deletion to
* perform [future | current | all].
* - rstart: The start time of the event instance being removed, if
* this is a series instance.
* - cstart: The start date of the client event cache.
* - cend: The end date of the client event cache.
* - sendupdates: Send cancellation notice to attendees?
*
*/
public function deleteEvent()
{
$result = new stdClass;
$instance = null;
if (!($kronolith_driver = $this->_getDriver($this->vars->cal)) ||
!isset($this->vars->id)) {
return $result;
}
try {
$event = $kronolith_driver->getEvent($this->vars->id);
if (!$event->hasPermission(Horde_Perms::DELETE)) {
$GLOBALS['notification']->push(_("You do not have permission to delete this event."), 'horde.warning');
return $result;
}
$range = null;
if ($event->recurs() && $this->vars->r != 'all') {
switch ($this->vars->r) {
case 'future':
// Deleting all future instances.
// @TODO: Check if we need to find future exceptions
// that are after $recurEnd and remove those as well.
$instance = new Horde_Date($this->vars->rstart, $event->timezone);
$recurEnd = clone($instance);
$recurEnd->hour = 0;
$recurEnd->min = 0;
$recurEnd->sec = 0;
$recurEnd->mday--;
if ($event->end->compareDate($recurEnd) > 0) {
$kronolith_driver->deleteEvent($event->id);
$result = $this->_signedResponse($this->vars->cal);
$result->events = array();
} else {
$event->recurrence->setRecurEnd($recurEnd);
$result = $this->_saveEvent($event, $event, $this->vars);
}
$range = Kronolith::RANGE_THISANDFUTURE;
break;
case 'current':
// Deleting only the current instance.
$instance = new Horde_Date($this->vars->rstart, $event->timezone);
$event->recurrence->addException(
$instance->year, $instance->month, $instance->mday);
$result = $this->_saveEvent($event, $event, $this->vars);
}
} else {
// Deleting an entire series, or this is a single event only.
$kronolith_driver->deleteEvent($event->id);
$result = $this->_signedResponse($this->vars->cal);
$result->events = array();
$result->uid = $event->uid;
}
if ($this->vars->sendupdates) {
Kronolith::sendITipNotifications(
$event, $GLOBALS['notification'], Kronolith::ITIP_CANCEL, $instance, $range);
}
$result->deleted = true;
} catch (Horde_Exception_NotFound $e) {
$GLOBALS['notification']->push(_("The requested event was not found."), 'horde.error');
} catch (Exception $e) {
$GLOBALS['notification']->push($e, 'horde.error');
}
return $result;
}
/**
* TODO
*/
public function searchEvents()
{
$query = Horde_Serialize::unserialize($this->vars->query, Horde_Serialize::JSON);
if (!isset($query->start)) {
$query->start = new Horde_Date($_SERVER['REQUEST_TIME']);
}
if (!isset($query->end)) {
$query->end = null;
}
switch ($this->vars->time) {
case 'all':
$query->start = null;
$query->end = null;
break;
case 'future':
$query->start = new Horde_Date($_SERVER['REQUEST_TIME']);
$query->end = null;
break;
case 'past':
$query->start = null;
$query->end = new Horde_Date($_SERVER['REQUEST_TIME']);
break;
}
$tagger = new Kronolith_Tagger();
$cals = Horde_Serialize::unserialize($this->vars->cals, Horde_Serialize::JSON);
$events = array();
foreach ($cals as $cal) {
if (!($kronolith_driver = $this->_getDriver($cal))) {
continue;
}
try {
$result = $kronolith_driver->search($query, true);
if ($result) {
$events[$cal] = $result;
}
} catch (Exception $e) {
$GLOBALS['notification']->push($e, 'horde.error');
}
$split = explode('|', $cal);
if ($split[0] == 'internal') {
$result = $tagger->search($query->title, array('type' => 'event', 'calendar' => $split[1]));
foreach ($result['events'] as $uid) {
Kronolith::addSearchEvents($events[$cal], $kronolith_driver->getByUID($uid), $query, true);
}
}
}
$result = new stdClass;
$result->view = 'search';
$result->query = $this->vars->query;
if ($events) {
$result->events = $events;
}
return $result;
}
/**
* TODO
*/
public function listTasks()
{
if (!$GLOBALS['registry']->hasMethod('tasks/listTasks')) {
return false;
}
$result = new stdClass;
$result->list = $this->vars->list;
$result->type = $this->vars->type;
try {
$tasks = $GLOBALS['registry']->tasks
->listTasks(array(
'tasklists' => $this->vars->list,
'completed' => $this->vars->type == 'incomplete' ? 'future_incomplete' : $this->vars->type,
'include_tags' => true,
'external' => false,
'json' => true
));
if (count($tasks)) {
$result->tasks = $tasks;
}
} catch (Exception $e) {
$GLOBALS['notification']->push($e, 'horde.error');
}
return $result;
}
/**
* TODO
*/
public function getTask()
{
if (!$GLOBALS['registry']->hasMethod('tasks/getTask') ||
!isset($this->vars->id) ||
!isset($this->vars->list)) {
return false;
}
$result = new stdClass;
try {
$task = $GLOBALS['registry']->tasks->getTask($this->vars->list, $this->vars->id);
if ($task) {
$result->task = $task->toJson(true, $GLOBALS['prefs']->getValue('twentyFour') ? 'H:i' : 'h:i A');
} else {
$GLOBALS['notification']->push(_("The requested task was not found."), 'horde.error');
}
} catch (Exception $e) {
$GLOBALS['notification']->push($e, 'horde.error');
}
return $result;
}
/**
* TODO
*/
public function saveTask()
{
if (!$GLOBALS['registry']->hasMethod('tasks/updateTask') ||
!$GLOBALS['registry']->hasMethod('tasks/addTask')) {
return false;
}
$id = $this->vars->task_id;
$list = $this->vars->old_tasklist;
$task = $this->vars->task;
$result = $this->_signedResponse('tasklists|tasks/' . $task['tasklist']);
$due = trim($task['due_date'] . ' ' . $task['due_time']);
if (!empty($due)) {
try {
$due = Kronolith::parseDate($due);
$task['due'] = $due->timestamp();
} catch (Exception $e) {
$GLOBALS['notification']->push($e, 'horde.error');
return $result;
}
}
if ($task['alarm']['on']) {
$value = $task['alarm']['value'];
$unit = $task['alarm']['unit'];
if ($value == 0) {
$value = $unit = 1;
}
$task['alarm'] = $value * $unit;
if (isset($task['alarm_methods']) && isset($task['methods'])) {
foreach (array_keys($task['methods']) as $method) {
if (!in_array($method, $task['alarm_methods'])) {
unset($task['methods'][$method]);
}
}
foreach ($task['alarm_methods'] as $method) {
if (!isset($task['methods'][$method])) {
$task['methods'][$method] = array();
}
}
} else {
$task['methods'] = array();
}
} else {
$task['alarm'] = 0;
$task['methods'] = array();
}
unset($task['alarm_methods']);
if (!isset($task['completed'])) {
$task['completed'] = false;
}
if ($this->vars->recur && !empty($due)) {
$task['recurrence'] = Kronolith_Event::readRecurrenceForm($due, 'UTC');
}
$task['tags'] = Horde_Util::getFormData('tags');
try {
$ids = ($id && $list)
? $GLOBALS['registry']->tasks->updateTask($list, $id, $task)
: $GLOBALS['registry']->tasks->addTask($task);
if (!$id) {
$id = $ids[0];
}
$task = $GLOBALS['registry']->tasks->getTask($task['tasklist'], $id);
$result->tasks = array($id => $task->toJson(false, $GLOBALS['prefs']->getValue('twentyFour') ? 'H:i' : 'h:i A'));
$result->type = $task->completed ? 'complete' : 'incomplete';
$result->list = $task->tasklist;
} catch (Exception $e) {
$GLOBALS['notification']->push($e, 'horde.error');
return $result;
}
if ($due &&
$kronolith_driver = $this->_getDriver('tasklists|tasks/' . $task->tasklist)) {
try {
$event = $kronolith_driver->getEvent('_tasks' . $id);
$end = clone $due;
$end->hour = 23;
$end->min = $end->sec = 59;
$start = clone $due;
$start->hour = $start->min = $start->sec = 0;
$events = array();
Kronolith::addEvents($events, $event, $start, $end, true, true);
if (count($events)) {
$result->events = $events;
}
} catch (Horde_Exception_NotFound $e) {
} catch (Exception $e) {
$GLOBALS['notification']->push($e, 'horde.error');
}
}
return $result;
}
/**
* TODO
*/
public function quickSaveTask()
{
if (!$GLOBALS['registry']->hasMethod('tasks/quickAdd')) {
return false;
}
$result = $this->_signedResponse(
'tasklists|tasks/' . $this->vars->tasklist);
try {
$ids = $GLOBALS['registry']->tasks->quickAdd($this->vars->text);
$result->type = 'incomplete';
$result->list = $this->vars->tasklist;
$result->tasks = array();
foreach ($ids as $uid) {
$task = $GLOBALS['registry']->tasks->export($uid, 'raw');
$result->tasks[$task->id] = $task->toJson(
false,
$GLOBALS['prefs']->getValue('twentyFour') ? 'H:i' : 'h:i A'
);
}
} catch (Exception $e) {
$GLOBALS['notification']->push($e, 'horde.error');
}
return $result;
}
/**
* TODO
*/
public function deleteTask()
{
$result = new stdClass;
if (!$GLOBALS['registry']->hasMethod('tasks/deleteTask') ||
!isset($this->vars->id) ||
!isset($this->vars->list)) {
return $result;
}
try {
$GLOBALS['registry']->tasks->deleteTask($this->vars->list, $this->vars->id);
$result->deleted = true;
} catch (Exception $e) {
$GLOBALS['notification']->push($e, 'horde.error');
}
return $result;
}
/**
* TODO
*/
public function toggleCompletion()
{
$result = new stdClass;
if (!$GLOBALS['registry']->hasMethod('tasks/toggleCompletion')) {
return $result;
}
try {
$result->toggled = $GLOBALS['registry']->tasks->toggleCompletion($this->vars->id, $this->vars->list);
} catch (Exception $e) {
$GLOBALS['notification']->push($e, 'horde.error');
}
return $result;
}
/**
* Generate a list of most frequently used tags for the current user.
*/
public function listTopTags()
{
$tagger = new Kronolith_Tagger();
$result = new stdClass;
$result->tags = array();
$tags = $tagger->getCloud($GLOBALS['registry']->getAuth(), 10, true);
foreach ($tags as $tag) {
$result->tags[] = $tag['tag_name'];
}
return $result;
}
/**
* Return fb information for the requested attendee or resource.
*
* Uses the following request parameters:
*
* -email: The attendee's email address.
* -resource: The resource id.
*
*/
public function getFreeBusy()
{
$result = new stdClass;
if ($this->vars->email) {
try {
$result->fb = Kronolith_FreeBusy::get($this->vars->email, true);
} catch (Exception $e) {
$GLOBALS['notification']->push($e->getMessage(), 'horde.warning');
}
} elseif ($this->vars->resource) {
try {
$resource = Kronolith::getDriver('Resource')
->getResource($this->vars->resource);
try {
$result->fb = $resource->getFreeBusy(null, null, true, true);
} catch (Horde_Exception $e) {
// Resource groups can't provide FB information.
$result->fb = null;
}
} catch (Exception $e) {
$GLOBALS['notification']->push($e->getMessage(), 'horde.warning');
}
}
return $result;
}
/**
* TODO
*/
public function searchCalendars()
{
$result = new stdClass;
$result->events = 'Searched for calendars: ' . $this->vars->title;
return $result;
}
/**
* TODO
*/
public function saveCalendar()
{
$calendar_id = $this->vars->calendar;
$result = new stdClass;
switch ($this->vars->type) {
case 'internal':
$info = array();
foreach (array('name', 'color', 'description', 'tags') as $key) {
$info[$key] = $this->vars->$key;
}
// Create a calendar.
if (!$calendar_id) {
if (!$GLOBALS['registry']->getAuth() ||
$GLOBALS['prefs']->isLocked('default_share')) {
return $result;
}
try {
$calendar = Kronolith::addShare($info);
Kronolith::readPermsForm($calendar);
if ($calendar->hasPermission($GLOBALS['registry']->getAuth(), Horde_Perms::SHOW)) {
$wrapper = new Kronolith_Calendar_Internal(array('share' => $calendar));
$result->saved = true;
$result->id = $calendar->getName();
$result->calendar = $wrapper->toHash();
}
} catch (Exception $e) {
$GLOBALS['notification']->push($e, 'horde.error');
return $result;
}
$GLOBALS['notification']->push(sprintf(_("The calendar \"%s\" has been created."), $info['name']), 'horde.success');
break;
}
// Update a calendar.
try {
$calendar = $GLOBALS['injector']->getInstance('Kronolith_Shares')->getShare($calendar_id);
$original_name = $calendar->get('name');
$original_owner = $calendar->get('owner');
Kronolith::updateShare($calendar, $info);
Kronolith::readPermsForm($calendar);
if ($calendar->get('owner') != $original_owner) {
$result->deleted = true;
}
if ($calendar->hasPermission($GLOBALS['registry']->getAuth(), Horde_Perms::SHOW)) {
$wrapper = new Kronolith_Calendar_Internal(array('share' => $calendar));
$result->saved = true;
$result->calendar = $wrapper->toHash();
}
} catch (Exception $e) {
$GLOBALS['notification']->push($e, 'horde.error');
return $result;
}
if ($calendar->get('name') != $original_name) {
$GLOBALS['notification']->push(sprintf(_("The calendar \"%s\" has been renamed to \"%s\"."), $original_name, $calendar->get('name')), 'horde.success');
} else {
$GLOBALS['notification']->push(sprintf(_("The calendar \"%s\" has been saved."), $original_name), 'horde.success');
}
break;
case 'tasklists':
$calendar = array();
foreach (array('name', 'color', 'description') as $key) {
$calendar[$key] = $this->vars->$key;
}
// Create a task list.
if (!$calendar_id) {
if (!$GLOBALS['registry']->getAuth() ||
$GLOBALS['prefs']->isLocked('default_share')) {
return $result;
}
try {
$tasklistId = $GLOBALS['registry']->tasks->addTasklist($calendar['name'], $calendar['description'], $calendar['color']);
$tasklists = $GLOBALS['registry']->tasks->listTasklists(true);
if (!isset($tasklists[$tasklistId])) {
$GLOBALS['notification']->push(_("Added task list not found."), 'horde.error');
return $result;
}
$tasklist = $tasklists[$tasklistId];
Kronolith::readPermsForm($tasklist);
if ($tasklist->hasPermission($GLOBALS['registry']->getAuth(), Horde_Perms::SHOW)) {
$wrapper = new Kronolith_Calendar_External_Tasks(array('api' => 'tasks', 'name' => $tasklistId, 'share' => $tasklist));
// Update external calendars caches.
$all_external = $GLOBALS['session']->get('kronolith', 'all_external_calendars');
$all_external[] = array('a' => 'tasks', 'n' => $tasklistId, 'd' => $tasklist->get('name'));
$GLOBALS['session']->set('kronolith', 'all_external_calendars', $all_external);
$display_external = $GLOBALS['calendar_manager']->get(Kronolith::DISPLAY_EXTERNAL_CALENDARS);
$display_external[] = 'tasks/' . $tasklistId;
$GLOBALS['calendar_manager']->set(Kronolith::DISPLAY_EXTERNAL_CALENDARS, $display_external);
$GLOBALS['prefs']->setValue('display_external_cals', serialize($display_external));
$all_external = $GLOBALS['calendar_manager']->get(Kronolith::ALL_EXTERNAL_CALENDARS);
$all_external['tasks/' . $tasklistId] = $wrapper;
$GLOBALS['calendar_manager']->set(Kronolith::ALL_EXTERNAL_CALENDARS, $all_external);
$result->saved = true;
$result->id = 'tasks/' . $tasklistId;
$result->calendar = $wrapper->toHash();
}
} catch (Exception $e) {
$GLOBALS['notification']->push($e, 'horde.error');
return $result;
}
$GLOBALS['notification']->push(sprintf(_("The task list \"%s\" has been created."), $calendar['name']), 'horde.success');
break;
}
// Update a task list.
$calendar_id = substr($calendar_id, 6);
try {
$GLOBALS['registry']->tasks->updateTasklist($calendar_id, $calendar);
$tasklists = $GLOBALS['registry']->tasks->listTasklists(true, Horde_Perms::EDIT);
$tasklist = $tasklists[$calendar_id];
$original_owner = $tasklist->get('owner');
Kronolith::readPermsForm($tasklist);
if ($tasklist->get('owner') != $original_owner) {
$result->deleted = true;
}
if ($tasklist->hasPermission($GLOBALS['registry']->getAuth(), Horde_Perms::SHOW)) {
$wrapper = new Kronolith_Calendar_External_Tasks(array('api' => 'tasks', 'name' => $calendar_id, 'share' => $tasklist));
$result->saved = true;
$result->calendar = $wrapper->toHash();
}
} catch (Exception $e) {
$GLOBALS['notification']->push($e, 'horde.error');
return $result;
}
if ($tasklist->get('name') != $calendar['name']) {
$GLOBALS['notification']->push(sprintf(_("The task list \"%s\" has been renamed to \"%s\"."), $tasklist->get('name'), $calendar['name']), 'horde.success');
} else {
$GLOBALS['notification']->push(sprintf(_("The task list \"%s\" has been saved."), $tasklist->get('name')), 'horde.success');
}
break;
case 'remote':
$calendar = array();
foreach (array('name', 'desc', 'url', 'color', 'user', 'password') as $key) {
$calendar[$key] = $this->vars->$key;
}
try {
Kronolith::subscribeRemoteCalendar($calendar, $calendar_id);
} catch (Exception $e) {
$GLOBALS['notification']->push($e, 'horde.error');
return $result;
}
if ($calendar_id) {
$GLOBALS['notification']->push(sprintf(_("The calendar \"%s\" has been saved."), $calendar['name']), 'horde.success');
} else {
$GLOBALS['notification']->push(sprintf(_("You have been subscribed to \"%s\" (%s)."), $calendar['name'], $calendar['url']), 'horde.success');
$result->id = $calendar['url'];
}
$wrapper = new Kronolith_Calendar_Remote($calendar);
$result->saved = true;
$result->calendar = $wrapper->toHash();
break;
case 'resource':
foreach (array('name', 'description', 'response_type') as $key) {
$info[$key] = $this->vars->$key;
}
if (!$calendar_id) {
// New resource
// @TODO: Groups.
if (!$GLOBALS['registry']->isAdmin() &&
!$GLOBALS['injector']->getInstance('Horde_Core_Perms')->hasAppPermission('resource_management')) {
$GLOBALS['notification']->push(_("You are not allowed to create new resources."), 'horde.error');
return $result;
}
$resource = Kronolith_Resource::addResource(new Kronolith_Resource_Single($info));
} else {
try {
$rdriver = Kronolith::getDriver('Resource');
$resource = $rdriver->getResource($rdriver->getResourceIdByCalendar($calendar_id));
if (!($resource->hasPermission($GLOBALS['registry']->getAuth(), Horde_Perms::EDIT))) {
$GLOBALS['notification']->push(_("You are not allowed to edit this resource."), 'horde.error');
return $result;
}
foreach (array('name', 'description', 'response_type', 'email') as $key) {
$resource->set($key, $this->vars->$key);
}
$resource->save();
} catch (Kronolith_Exception $e) {
$GLOBALS['notification']->push($e->getMessage(), 'horde.error');
return $result;
}
}
$wrapper = new Kronolith_Calendar_Resource(array('resource' => $resource));
$result->calendar = $wrapper->toHash();
$result->saved = true;
$result->id = $resource->get('calendar');
$GLOBALS['notification']->push(sprintf(_("The resource \"%s\" has been saved."), $resource->get('name'), 'horde.success'));
break;
case 'resourcegroup':
if (empty($calendar_id)) {
// New resource group.
$resource = Kronolith_Resource::addResource(
new Kronolith_Resource_Group(array(
'name' => $this->vars->name,
'description' => $this->vars->description,
'members' => $this->vars->members)
)
);
} else {
$driver = Kronolith::getDriver('Resource');
$resource = $driver->getResource($calendar_id);
$resource->set('name', $this->vars->name);
$resource->set('description', $this->vars->description);
$resource->set('members', $this->vars->members);
$resource->save();
}
$wrapper = new Kronolith_Calendar_ResourceGroup(array('resource' => $resource));
$result->calendar = $wrapper->toHash();
$result->saved = true;
$result->id = $resource->get('calendar');
$GLOBALS['notification']->push(sprintf(_("The resource group \"%s\" has been saved."), $resource->get('name'), 'horde.success'));
break;
}
return $result;
}
/**
* TODO
*/
public function deleteCalendar()
{
$calendar_id = $this->vars->calendar;
$result = new stdClass;
switch ($this->vars->type) {
case 'internal':
try {
$calendar = $GLOBALS['injector']->getInstance('Kronolith_Shares')->getShare($calendar_id);
} catch (Exception $e) {
$GLOBALS['notification']->push($e, 'horde.error');
return $result;
}
try {
Kronolith::deleteShare($calendar);
} catch (Exception $e) {
$GLOBALS['notification']->push(sprintf(_("Unable to delete \"%s\": %s"), $calendar->get('name'), $e->getMessage()), 'horde.error');
return $result;
}
$GLOBALS['notification']->push(sprintf(_("The calendar \"%s\" has been deleted."), $calendar->get('name')), 'horde.success');
break;
case 'tasklists':
$calendar_id = substr($calendar_id, 6);
$tasklists = $GLOBALS['registry']->tasks->listTasklists(true);
if (!isset($tasklists[$calendar_id])) {
$GLOBALS['notification']->push(_("You are not allowed to delete this task list."), 'horde.error');
return $result;
}
try {
$GLOBALS['registry']->tasks->deleteTasklist($calendar_id);
} catch (Exception $e) {
$GLOBALS['notification']->push(sprintf(_("Unable to delete \"%s\": %s"), $tasklists[$calendar_id]->get('name'), $e->getMessage()), 'horde.error');
return $result;
}
$GLOBALS['notification']->push(sprintf(_("The task list \"%s\" has been deleted."), $tasklists[$calendar_id]->get('name')), 'horde.success');
break;
case 'remote':
try {
$deleted = Kronolith::unsubscribeRemoteCalendar($calendar_id);
} catch (Exception $e) {
$GLOBALS['notification']->push($e, 'horde.error');
return $result;
}
$GLOBALS['notification']->push(sprintf(_("You have been unsubscribed from \"%s\" (%s)."), $deleted['name'], $deleted['url']), 'horde.success');
break;
case 'resource':
try {
$rdriver = Kronolith::getDriver('Resource');
$resource = $rdriver->getResource($rdriver->getResourceIdByCalendar($calendar_id));
if (!($resource->hasPermission($GLOBALS['registry']->getAuth(), Horde_Perms::DELETE))) {
$GLOBALS['notification']->push(_("You are not allowed to delete this resource."), 'horde.error');
return $result;
}
$name = $resource->get('name');
$rdriver->delete($resource);
} catch (Kronolith_Exception $e) {
$GLOBALS['notification']->push($e->getMessage(), 'horde.error');
return $result;
}
$GLOBALS['notification']->push(sprintf(_("The resource \"%s\" has been deleted."), $name), 'horde.success');
break;
case 'resourcegroup':
try {
$rdriver = Kronolith::getDriver('Resource');
$resource = $rdriver->getResource($calendar_id);
if (!($resource->hasPermission($GLOBALS['registry']->getAuth(), Horde_Perms::DELETE))) {
$GLOBALS['notification']->push(_("You are not allowed to delete this resource."), 'horde.error');
return $result;
}
$name = $resource->get('name');
$rdriver->delete($resource);
} catch (Kronolith_Exception $e) {
$GLOBALS['notification']->push($e->getMessage(), 'horde.error');
return $result;
}
$GLOBALS['notification']->push(sprintf(_("The resource \"%s\" has been deleted."), $name), 'horde.success');
}
$result->deleted = true;
return $result;
}
/**
* Returns the information for a shared internal calendar.
*/
public function getCalendar()
{
$result = new stdClass;
$all_calendars = $GLOBALS['calendar_manager']->get(Kronolith::ALL_CALENDARS);
if (!isset($all_calendars[$this->vars->cal]) && !$GLOBALS['conf']['share']['hidden']) {
$GLOBALS['notification']->push(_("You are not allowed to view this calendar."), 'horde.error');
return $result;
} elseif (!isset($all_calendars[$this->vars->cal])) {
// Subscribing to a "hidden" share, check perms.
$kronolith_shares = $GLOBALS['injector']->getInstance('Kronolith_Shares');
$share = $kronolith_shares->getShare($this->vars->cal);
if (!$share->hasPermission($GLOBALS['registry']->getAuth(), Horde_Perms::READ)) {
$GLOBALS['notification']->push(_("You are not allowed to view this calendar."), 'horde.error');
return $result;
}
$calendar = new Kronolith_Calendar_Internal(array('share' => $share));
} else {
$calendar = $all_calendars[$this->vars->cal];
}
$result->calendar = $calendar->toHash();
return $result;
}
/**
* TODO
*/
public function getRemoteInfo()
{
$params = array('timeout' => 15);
if ($user = $this->vars->user) {
$params['user'] = $user;
$params['password'] = $this->vars->password;
}
if (!empty($GLOBALS['conf']['http']['proxy']['proxy_host'])) {
$params['proxy'] = $GLOBALS['conf']['http']['proxy'];
}
$result = new stdClass;
try {
$driver = $GLOBALS['injector']->getInstance('Kronolith_Factory_Driver')->create('Ical', $params);
$driver->open($this->vars->url);
if ($driver->isCalDAV()) {
$result->success = true;
// TODO: find out how to retrieve calendar information via CalDAV.
} else {
$ical = $driver->getRemoteCalendar(false);
$result->success = true;
try {
$name = $ical->getAttribute('X-WR-CALNAME');
$result->name = $name;
} catch (Horde_Icalendar_Exception $e) {}
try {
$desc = $ical->getAttribute('X-WR-CALDESC');
$result->desc = $desc;
} catch (Horde_Icalendar_Exception $e) {}
}
} catch (Exception $e) {
if ($e->getCode() == 401) {
$result->auth = true;
} else {
$GLOBALS['notification']->push($e, 'horde.error');
}
}
return $result;
}
/**
* TODO
*/
public function saveCalPref()
{
return false;
}
/**
* Return a list of available resources.
*
* @return array A hash of resource_id => resource sorted by resource name.
*/
public function getResourceList()
{
$data = array();
$resources = Kronolith::getDriver('Resource')
->listResources(Horde_Perms::READ, array(), 'name');
foreach ($resources as $resource) {
$data[] = $resource->toJson();
}
return $data;
}
/**
* Handle output of the embedded widget: allows embedding calendar widgets
* in external websites.
*
* The following arguments are required:
* - calendar: The share_name for the requested calendar.
* - container: The DOM node to populate with the widget.
* - view: The view (block) we want.
*
* The following are optional (and are not used for all views)
* - css
* - days
* - maxevents: The maximum number of events to show.
* - months: The number of months to include.
*/
public function embed()
{
global $page_output, $registry;
/* First, determine the type of view we are asking for */
$view = $this->vars->view;
/* The DOM container to put the HTML in on the remote site */
$container = $this->vars->container;
/* The share_name of the calendar to display */
$calendar = $this->vars->calendar;
/* Deault to showing only 1 month when we have a choice */
$count_month = $this->vars->get('months', 1);
/* Default to no limit for the number of events */
$max_events = $this->vars->get('maxevents', 0);
/* Default to one week */
$count_days = $this->vars->get('days', 7);
if ($this->vars->css == 'none') {
$nocss = true;
}
/* Build the block parameters */
$params = array(
'calendar' => $calendar,
'maxevents' => $max_events,
'months' => $count_month,
'days' => $count_days
);
/* Call the Horde_Block api to get the calendar HTML */
$title = $registry->call('horde/blockTitle', array('kronolith', $view, $params));
$results = $registry->call('horde/blockContent', array('kronolith', $view, $params));
/* Some needed paths */
$js_path = $registry->get('jsuri', 'kronolith');
/* Local js */
$jsurl = Horde::url($js_path . '/embed.js', true);
/* Horde's js */
$hjs_path = $registry->get('jsuri', 'horde');
$hjsurl = Horde::url($hjs_path . '/tooltips.js', true);
$pturl = Horde::url($hjs_path . '/prototype.js', true);
/* CSS */
if (empty($nocss)) {
$page_output->addThemeStylesheet('embed.css');
Horde::startBuffer();
$page_output->includeStylesheetFiles(array('nobase' => true), true);
$css = Horde::endBuffer();
} else {
$css = '';
}
/* Escape the text and put together the javascript to send back */
$container = Horde_Serialize::serialize($container, Horde_Serialize::JSON);
$results = Horde_Serialize::serialize('' . $title . ' ' . $results . ' ', Horde_Serialize::JSON);
$js = <<');
}
if (typeof Horde_ToolTips == 'undefined') {
Horde_ToolTips_Autoload = false;
document.write('');
}
kronolith = new Object();
kronolithNodes = new Array();
document.write('');
document.write('$css');
}
kronolithNodes[kronolithNodes.length] = $container;
kronolith[$container] = $results;
EOT;
return new Horde_Core_Ajax_Response_Raw($js, 'text/javascript');
}
public function toTimeslice()
{
$driver = $this->_getDriver($this->vars->cal);
$event = $driver->getEvent($this->vars->e);
try {
Kronolith::toTimeslice($event, $this->vars->t, $this->vars->c);
} catch (Kronolith_Exception $e) {
$GLOBALS['notification']->push(sprintf(_("Error saving timeslice: %s"), $e->getMessage()), 'horde.error');
return false;
}
$GLOBALS['notification']->push(_("Successfully saved timeslice."), 'horde.success');
return true;
}
/**
* Check reply status of any resources and report back. Used as a check
* before saving an event to give the user feedback.
*
* The following arguments are expected:
* - r: A comma separated string of resource identifiers.
* - s: The event start time to check.
* - e: The event end time to check.
* - u: The event uid, if not a new event.
* - c: The event's calendar.
*/
public function checkResources()
{
if (empty($GLOBALS['conf']['resource']['driver'])) {
return array();
}
if ($this->vars->i) {
$event = $this->_getDriver($this->vars->c)->getEvent($this->vars->i);
} else {
$event = Kronolith::getDriver()->getEvent();
}
// Overrite start/end times since we may be checking before we edit
// an existing event with new times.
$event->start = new Horde_Date($this->vars->s);
$event->end = new Horde_Date($this->vars->e);
$event->start->setTimezone(date_default_timezone_get());
$event->end->setTimezone(date_default_timezone_get());
$results = array();
foreach (explode(',', $this->vars->r) as $id) {
$resource = Kronolith::getDriver('Resource')->getResource($id);
$results[$id] = $resource->getResponse($event);
}
return $results;
}
/**
* Returns the driver object for a calendar.
*
* @param string $cal A calendar string in the format "type|name".
*
* @return Kronolith_Driver|boolean A driver instance or false on failure.
*/
protected function _getDriver($cal)
{
list($driver, $calendar) = explode('|', $cal);
if ($driver == 'internal' &&
!Kronolith::hasPermission($calendar, Horde_Perms::SHOW)) {
$GLOBALS['notification']->push(_("Permission Denied"), 'horde.error');
return false;
}
try {
$kronolith_driver = Kronolith::getDriver($driver, $calendar);
} catch (Exception $e) {
$GLOBALS['notification']->push($e, 'horde.error');
return false;
}
if ($driver == 'remote') {
$kronolith_driver->setParam('timeout', 15);
}
return $kronolith_driver;
}
/**
* Saves an event and returns a signed result object including the saved
* event.
*
* @param Kronolith_Event $event An event object.
* @param Kronolith_Event $original If $event is an exception, this should
* be set to the original event.
* @param object $attributes The attributes sent by the client.
* Expected to contain cstart and cend.
* @param boolean $saveOriginal Commit any changes in $original to
* storage also.
*
* @return object The result object.
*/
protected function _saveEvent(Kronolith_Event $event,
Kronolith_Event $original = null,
$attributes = null,
$saveOriginal = false)
{
if ($this->vars->targetcalendar) {
$cal = $this->vars->targetcalendar;
} elseif ($this->vars->cal) {
$cal = $this->vars->cal;
} else {
$cal = $event->calendarType . '|' . $event->calendar;
}
$result = $this->_signedResponse($cal);
$events = array();
try {
$event->save();
if (!$this->vars->view_start || !$this->vars->view_end) {
$result->events = array();
return $result;
}
$end = new Horde_Date($this->vars->view_end);
$end->hour = 23;
$end->min = $end->sec = 59;
Kronolith::addEvents(
$events, $event,
new Horde_Date($this->vars->view_start),
$end, true, true);
// If this is an exception, we re-add the original event also;
// cstart and cend are the cacheStart and cacheEnd dates from the
// client.
if (!empty($original)) {
Kronolith::addEvents(
$events, $original,
new Horde_Date($attributes->cstart),
new Horde_Date($attributes->cend),
true, true);
if ($saveOriginal) {
$original->save();
}
}
// If this event recurs, we must add any bound exceptions to the
// results
if ($event->recurs()) {
$bound = $event->boundExceptions(false);
foreach ($bound as $day => &$exceptions) {
foreach ($exceptions as &$exception) {
$exception = $exception->toJson();
}
}
Kronolith::mergeEvents($events, $bound);
}
$result->events = count($events) ? $events : array();
} catch (Exception $e) {
$GLOBALS['notification']->push($e, 'horde.error');
}
return $result;
}
/**
* Creates a result object with the signature of the current request.
*
* @param string $calendar A calendar id.
*
* @return object The result object.
*/
protected function _signedResponse($calendar)
{
$result = new stdClass;
$result->cal = $calendar;
$result->view = $this->vars->view;
$result->sig = $this->vars->sig;
return $result;
}
/**
* Add an exception to the original event.
*
* @param Kronolith_Event $event The recurring event.
* @param object $attributes The attributes passed from the client.
* Expected to contain either rstart or rday.
*
* @return Kronolith_Event The event representing the exception, with
* the start/end times set the same as the original
* occurence.
*/
protected function _addException(Kronolith_Event $event, $attributes)
{
if ($attributes->rstart) {
$rstart = new Horde_Date($attributes->rstart);
$rstart->setTimezone($event->start->timezone);
} else {
$rstart = new Horde_Date($attributes->rday);
$rstart->setTimezone($event->start->timezone);
$rstart->hour = $event->start->hour;
$rstart->min = $event->start->min;
}
$event->recurrence->addException($rstart->year, $rstart->month, $rstart->mday);
$event->save();
}
/**
* Creates a new event that represents an exception to a recurring event.
*
* @param Kronolith_Event $event The original recurring event.
* @param Kronolith_Event $copy If present, contains a copy of $event, but
* with changes from edited event form.
* @param stdClass $attributes The attributes passed from the client.
* Expected to contain rstart and rend or
* rday that represents the original
* starting/ending date of the instance.
*
* @return Kronolith_Event The event representing the exception
*/
protected function _copyEvent(Kronolith_Event $event, Kronolith_Event $copy = null, $attributes = null)
{
if (empty($copy)) {
$copy = clone($event);
}
if ($attributes->rstart) {
$rstart = new Horde_Date($attributes->rstart);
$rstart->setTimezone($event->start->timezone);
$rend = new Horde_Date($attributes->rend);
$rend->setTimezone($event->end->timezone);
} else {
$rstart = new Horde_Date($attributes->rday);
$rstart->setTimezone($event->start->timezone);
$rstart->hour = $event->start->hour;
$rstart->min = $event->start->min;
$rend = $rstart->add($event->getDuration);
$rend->setTimezone($event->end->timezone);
$rend->hour = $event->end->hour;
$rend->min = $event->end->min;
}
$uid = $event->uid;
$otime = $event->start->strftime('%T');
// Create new event for the exception
$nevent = $event->getDriver()->getEvent();
$nevent->baseid = $uid;
$nevent->exceptionoriginaldate = new Horde_Date($rstart->strftime('%Y-%m-%d') . 'T' . $otime);
$nevent->exceptionoriginaldate->setTimezone($event->start->timezone);
$nevent->creator = $event->creator;
$nevent->title = $copy->title;
$nevent->description = $copy->description;
$nevent->location = $copy->location;
$nevent->private = $copy->private;
$nevent->url = $copy->url;
$nevent->status = $copy->status;
$nevent->attendees = $copy->attendees;
$nevent->setResources($copy->getResources());
$nevent->start = $rstart;
$nevent->end = $rend;
$nevent->initialized = true;
return $nevent;
}
}
kronolith-4.2.13/lib/Ajax/Imple/ContactAutoCompleter.php 0000664 0000765 0000024 00000002432 12654566222 020054 0 ustar
* @category Horde
* @license http://www.horde.org/licenses/gpl GPL
* @package Kronolith
*/
class Kronolith_Ajax_Imple_ContactAutoCompleter extends Horde_Core_Ajax_Imple_ContactAutoCompleter
{
/**
*/
protected function _getAutoCompleter()
{
$opts = array();
foreach (array('box', 'onAdd', 'onRemove', 'triggerContainer', 'beforeUpdate') as $val) {
if (isset($this->_params[$val])) {
$opts[$val] = $this->_params[$val];
}
}
return empty($this->_params['pretty'])
? new Horde_Core_Ajax_Imple_AutoCompleter_Ajax($opts)
: new Horde_Core_Ajax_Imple_AutoCompleter_Pretty($opts);
}
/**
*/
protected function _getAddressbookSearchParams()
{
$params = Kronolith::getAddressbookSearchParams();
$ob = new stdClass;
$ob->fields = $params['fields'];
$ob->sources = $params['sources'];
return $ob;
}
}
kronolith-4.2.13/lib/Ajax/Imple/ResourceAutoCompleter.php 0000664 0000765 0000024 00000003505 12654566222 020252 0 ustar
* @category Horde
* @license http://www.horde.org/licenses/gpl GPL
* @package Kronolith
*/
class Kronolith_Ajax_Imple_ResourceAutoCompleter extends Horde_Core_Ajax_Imple_AutoCompleter
{
/**
*/
protected function _getAutoCompleter()
{
$opts = array();
foreach (array('box', 'onAdd', 'onRemove', 'triggerContainer') as $val) {
if (isset($this->_params[$val])) {
$opts[$val] = $this->_params[$val];
}
}
if (empty($this->_params['pretty'])) {
return new Horde_Core_Ajax_Imple_AutoCompleter_Ajax($opts);
}
$opts['filterCallback'] = <<listResources(Horde_Perms::READ, array(), 'name');
foreach ($resources as $r) {
if (strpos(Horde_String::lower($r->get('name')), Horde_String::lower($input)) !== false) {
$ret[] = array(
'name' => $r->get('name'),
'code' => $r->getId());
}
}
return $ret;
}
}
kronolith-4.2.13/lib/Ajax/Imple/TagAutoCompleter.php 0000664 0000765 0000024 00000001744 12654566222 017201 0 ustar
* @package Kronolith
*/
class Kronolith_Ajax_Imple_TagAutoCompleter extends Horde_Core_Ajax_Imple_AutoCompleter
{
/**
*/
protected function _getAutoCompleter()
{
$opts = array();
foreach (array('box', 'triggerContainer') as $val) {
if (isset($this->_params[$val])) {
$opts[$val] = $this->_params[$val];
}
}
return empty($this->_params['pretty'])
? new Horde_Core_Ajax_Imple_AutoCompleter_Ajax($opts)
: new Horde_Core_Ajax_Imple_AutoCompleter_Pretty($opts);
}
/**
*/
protected function _handleAutoCompleter($input)
{
return array_values(Kronolith::getTagger()->listTags($input));
}
}
kronolith-4.2.13/lib/Ajax/Application.php 0000664 0000765 0000024 00000002332 12654566222 015151 0 ustar
* @author Jan Schneider
* @author Gonçalo Queirós
* @category Horde
* @license http://www.horde.org/licenses/gpl GPL
* @package Kronolith
*/
class Kronolith_Ajax_Application extends Horde_Core_Ajax_Application
{
/**
*/
protected function _init()
{
$this->addHandler('Kronolith_Ajax_Application_Handler');
$this->addHandler('Horde_Core_Ajax_Application_Handler_Chunk');
$this->addHandler('Horde_Core_Ajax_Application_Handler_Groups');
$this->addHandler('Horde_Core_Ajax_Application_Handler_Imple');
$this->addHandler('Horde_Core_Ajax_Application_Handler_Prefs');
$email = $this->addHandler('Horde_Core_Ajax_Application_Handler_Email');
$email->defaultDomain = empty($GLOBALS['conf']['storage']['default_domain'])
? null
: $GLOBALS['conf']['storage']['default_domain'];
}
}
kronolith-4.2.13/lib/Block/Month.php 0000664 0000765 0000024 00000016521 12654566222 014147 0 ustar _name = _("This Month");
}
/**
*/
protected function _params()
{
$params = array(
'calendar' => array(
'name' => _("Calendar"),
'type' => 'enum',
'default' => '__all'
)
);
$params['calendar']['values']['__all'] = _("All Visible");
foreach (Kronolith::listCalendars(Horde_Perms::SHOW, true) as $id => $cal) {
$params['calendar']['values'][$id] = $cal->name();
}
return $params;
}
/**
*/
protected function _title()
{
$title = _("All Calendars");
$url = Horde::url($GLOBALS['registry']->getInitialPage(), true);
if (isset($this->_params['calendar']) &&
$this->_params['calendar'] != '__all') {
$calendars = Kronolith::listCalendars();
if (isset($calendars[$this->_params['calendar']])) {
$title = htmlspecialchars($calendars[$this->_params['calendar']]->name());
} else {
$title = _("Calendar not found");
}
$url->add('display_cal', $this->_params['calendar']);
}
$date = new Horde_Date(time());
return $title . ', ' . $url->link() . $date->strftime('%B, %Y') . '';
}
/**
*/
protected function _content()
{
global $prefs;
if (isset($this->_params['calendar']) &&
$this->_params['calendar'] != '__all') {
$calendars = Kronolith::listCalendars();
if (!isset($calendars[$this->_params['calendar']])) {
return _("Calendar not found");
}
if (!$calendars[$this->_params['calendar']]->hasPermission(Horde_Perms::READ)) {
return _("Permission Denied");
}
}
$year = date('Y');
$month = date('m');
$startday = new Horde_Date(array('mday' => 1,
'month' => $month,
'year' => $year));
$startday = $startday->dayOfWeek();
$daysInView = Date_Calc::weeksInMonth($month, $year) * 7;
if (!$prefs->getValue('week_start_monday')) {
$startOfView = 1 - $startday;
// We may need to adjust the number of days in the view if
// we're starting weeks on Sunday.
if ($startday == Horde_Date::DATE_SUNDAY) {
$daysInView -= 7;
}
$endday = new Horde_Date(array('mday' => Horde_Date_Utils::daysInMonth($month, $year),
'month' => $month,
'year' => $year));
$endday = $endday->dayOfWeek();
if ($endday == Horde_Date::DATE_SUNDAY) {
$daysInView += 7;
}
} else {
if ($startday == Horde_Date::DATE_SUNDAY) {
$startOfView = -5;
} else {
$startOfView = 2 - $startday;
}
}
$startDate = new Horde_Date(array('year' => $year, 'month' => $month, 'mday' => $startOfView));
$endDate = new Horde_Date(array('year' => $year, 'month' => $month, 'mday' => $startOfView + $daysInView,
'hour' => 23, 'min' => 59, 'sec' => 59));
/* Table start. and current month indicator. */
$html = '';
/* Set up the weekdays. */
$weekdays = array(_("Mo"), _("Tu"), _("We"), _("Th"), _("Fr"), _("Sa"));
if (!$prefs->getValue('week_start_monday')) {
array_unshift($weekdays, _("Su"));
} else {
$weekdays[] = _("Su");
}
foreach ($weekdays as $weekday) {
$html .= '' . $weekday . ' | ';
}
try {
if (isset($this->_params['calendar']) &&
$this->_params['calendar'] != '__all') {
list($type, $calendar) = explode('_', $this->_params['calendar'], 2);
$driver = Kronolith::getDriver($type, $calendar);
$all_events = $driver->listEvents($startDate, $endDate, array(
'show_recurrence' => true));
} else {
$all_events = Kronolith::listEvents($startDate, $endDate, $GLOBALS['calendar_manager']->get(Kronolith::DISPLAY_CALENDARS));
}
} catch (Exception $e) {
return '' . $e->getMessage() . '';
}
$weekday = 0;
$week = -1;
for ($day = $startOfView; $day < $startOfView + $daysInView; ++$day) {
if ($weekday == 7) {
$weekday = 0;
}
if ($weekday == 0) {
++$week;
$html .= ' ';
}
$date_ob = new Kronolith_Day($month, $day, $year);
if ($date_ob->isToday()) {
$td_class = 'kronolith-today';
} elseif ($date_ob->month != $month) {
$td_class = 'kronolith-othermonth';
} elseif ($date_ob->dayOfWeek() == 0 || $date_ob->dayOfWeek() == 6) {
$td_class = 'kronolith-weekend';
} else {
$td_class = '';
}
$html .= '';
/* Set up the link to the day view. */
$url = Horde::url('day.php', true)
->add('date', $date_ob->dateString());
if (isset($this->_params['calendar']) &&
$this->_params['calendar'] != '__all') {
$url->add('display_cal', $this->_params['calendar']);
}
$date_stamp = $date_ob->dateString();
if (empty($all_events[$date_stamp])) {
/* No events, plain link to the day. */
$cell = Horde::linkTooltip($url, _("View Day")) . $date_ob->mday . '';
} else {
/* There are events; create a cell with tooltip to
* list them. */
$day_events = '';
foreach ($all_events[$date_stamp] as $event) {
if ($event->isAllDay()) {
$day_events .= _("All day");
} else {
$day_events .= $event->start->strftime($prefs->getValue('twentyFour') ? '%R' : '%I:%M%p') . '-' . $event->end->strftime($prefs->getValue('twentyFour') ? '%R' : '%I:%M%p');
}
$location = $event->getLocation();
$day_events .= ':'
. ($location ? ' (' . htmlspecialchars($location) . ')' : '')
. ' ' . $event->getTitle() . "\n";
}
$cell = Horde::linkTooltip($url, _("View Day"), '', '', '', $day_events) . $date_ob->mday . '';
}
/* Bold the cell if there are events. */
if (!empty($all_events[$date_stamp])) {
$cell = '' . $cell . '';
}
$html .= $cell . ' | ';
++$weekday;
}
return $html . ' ';
}
}
kronolith-4.2.13/lib/Block/Monthlist.php 0000664 0000765 0000024 00000017002 12654566222 015036 0 ustar _name = _("Upcoming Events");
}
/**
*/
protected function _params()
{
$params = array(
'calendar' => array(
'name' => _("Calendar"),
'type' => 'enum',
'default' => '__all'),
'months' => array(
'name' => _("Months Ahead"),
'type' => 'int',
'default' => 2),
'maxevents' => array(
'name' => _("Maximum number of events to display (0 = no limit)"),
'type' => 'int',
'default' => 0),
'alarms' => array(
'name' => _("Show only events that have an alarm set?"),
'type' => 'checkbox',
'default' => 0
)
);
$params['calendar']['values']['__all'] = _("All Visible");
foreach (Kronolith::listCalendars(Horde_Perms::SHOW, true) as $id => $cal) {
$params['calendar']['values'][$id] = $cal->name();
}
return $params;
}
/**
*/
protected function _title()
{
$url = Horde::url($GLOBALS['registry']->getInitialPage(), true);
if (isset($this->_params['calendar']) &&
$this->_params['calendar'] != '__all') {
$url->add('display_cal', $this->_params['calendar']);
}
return $url->link() . _("Upcoming Events") . '';
}
/**
*/
protected function _content()
{
global $page_output;
$page_output->addScriptFile('tooltips.js', 'horde');
$now = new Horde_Date($_SERVER['REQUEST_TIME']);
$today = date('j');
$current_month = '';
$startDate = new Horde_Date(array(
'year' => date('Y'),
'month' => date('n'),
'mday' => date('j')));
$endDate = new Horde_Date(array(
'year' => date('Y'),
'month' => date('n') + $this->_params['months'],
'mday' => date('j') - 1));
try {
if (isset($this->_params['calendar']) &&
$this->_params['calendar'] != '__all') {
$calendars = Kronolith::listCalendars();
if (!isset($calendars[$this->_params['calendar']])) {
return _("Calendar not found");
}
if (!$calendars[$this->_params['calendar']]->hasPermission(Horde_Perms::READ)) {
return _("Permission Denied");
}
list($type, $calendar) = explode('_', $this->_params['calendar'], 2);
$driver = Kronolith::getDriver($type, $calendar);
$all_events = $driver->listEvents(
$startDate,
$endDate,
array('show_recurrence' => true,
'has_alarm' => !empty($this->_params['alarms']),
'cover_dates' => false)
);
} else {
$all_events = Kronolith::listEvents(
$startDate,
$endDate,
$GLOBALS['calendar_manager']->get(Kronolith::DISPLAY_CALENDARS),
array(
'has_alarm' => !empty($this->_params['alarms']),
'cover_dates' => false
)
);
}
} catch (Exception $e) {
return '' . $e->getMessage() . '';
}
/* How many days do we need to check. */
$days = Date_Calc::dateDiff(
$startDate->mday, $startDate->month, $startDate->year,
$endDate->mday, $endDate->month, $endDate->year);
/* Loop through the days. */
$totalevents = 0;
$html = '';
for ($i = 0; $i < $days; ++$i) {
$day = new Kronolith_Day($startDate->month, $today + $i);
$date_stamp = $day->dateString();
if (empty($all_events[$date_stamp])) {
continue;
}
if (!empty($this->_params['maxevents']) &&
$totalevents >= $this->_params['maxevents']) {
break;
}
/* Output month header. */
if ($current_month != $day->month) {
$html .= '' . $day->strftime('%B') . ' | ';
}
$firstevent = true;
$tomorrow = $day->getTomorrow();
foreach ($all_events[$date_stamp] as $event) {
$isMultiDay = false;
if ($event->start->compareDate($day) < 0) {
$event->start = new Horde_Date($day);
}
if ($event->end->compareDate($tomorrow) >= 1) {
$isMultiDay = true;
}
if (($event->end->compareDate($now) < 0 && !$event->isAllDay()) ||
(!empty($this->_params['alarms']) && !$event->alarm)) {
continue;
}
if ($firstevent || $isMultiDay) {
$html .= 'month) {
$html .= ' class="upcomingday"';
}
$html .= '>';
if ($day->isToday()) {
$html .= _("Today");
} elseif ($day->isTomorrow()) {
$html .= _("Tomorrow");
} else {
$html .= $day->mday;
}
if ($isMultiDay) {
$endDay = new Kronolith_Day($event->end->month, $event->end->mday);
$html .= ' - ';
if ($endDay->isTomorrow()) {
$html .= _("Tomorrow");
} else {
$html .= $event->end->mday;
}
}
$html .= ' | ';
$firstevent = $isMultiDay;
} else {
$html .= ' | ';
}
$html .= '';
if ($event->start->compareDate($now) < 0 &&
$event->end->compareDate($now) > 0) {
$html .= '' . htmlspecialchars($event->getLocation()) . '';
} else {
$html .= htmlspecialchars($event->getLocation());
}
if ($event->start->compareDate($now) < 0 &&
$event->end->compareDate($now) > 0) {
$html .= '';
}
$html .= $event->getLink(null, true, null, true);
if ($event->start->compareDate($now) < 0 &&
$event->end->compareDate($now) > 0) {
$html .= '';
}
$html .= ' | ';
$totalevents++;
}
$current_month = $day->strftime('%m');
}
if (empty($html)) {
return '' . _("No events to display") . '';
}
return '';
}
}
kronolith-4.2.13/lib/Block/Prevmonthlist.php 0000664 0000765 0000024 00000014111 12654566222 015731 0 ustar _name = _("Prior Events");
}
/**
*/
protected function _params()
{
$params = array(
'calendar' => array(
'name' => _("Calendar"),
'type' => 'enum',
'default' => '__all'
),
'months' => array(
'name' => _("Months Before"),
'type' => 'int',
'default' => 2
),
'alarms' => array(
'name' => _("Show only events that have an alarm set?"),
'type' => 'checkbox',
'default' => 0
)
);
$params['calendar']['values']['__all'] = _("All Visible");
foreach (Kronolith::listCalendars(Horde_Perms::SHOW, true) as $id => $cal) {
$params['calendar']['values'][$id] = $cal->name();
}
return $params;
}
/**
*/
protected function _title()
{
$url = Horde::url($GLOBALS['registry']->getInitialPage(), true);
if (isset($this->_params['calendar']) &&
$this->_params['calendar'] != '__all') {
$url->add('display_cal', $this->_params['calendar']);
}
return $url->link() . $this->getName() . '';
}
/**
*/
protected function _content()
{
global $page_output, $registry, $prefs;
$GLOBALS['from_block'] = true;
$page_output->addScriptFile('tooltips.js', 'horde');
$startDate = new Horde_Date(array('year' => date('Y'), 'month' => date('n') - $this->_params['months'], 'mday' => date('j')));
$endDate = new Horde_Date(array('year' => date('Y'), 'month' => date('n'), 'mday' => date('j') - 1));
$current_month = '';
try {
if (isset($this->_params['calendar']) &&
$this->_params['calendar'] != '__all') {
$calendars = Kronolith::listCalendars();
if (!isset($calendars[$this->_params['calendar']])) {
return _("Calendar not found");
}
if (!$calendars[$this->_params['calendar']]->hasPermission(Horde_Perms::READ)) {
return _("Permission Denied");
}
list($type, $calendar) = explode('_', $this->_params['calendar']);
$driver = Kronolith::getDriver($type, $calendar);
$all_events = $driver->listEvents(
$startDate, $endDate, array('show_recurrence' => true));
} else {
$all_events = Kronolith::listEvents($startDate, $endDate, $GLOBALS['calendar_manager']->get(Kronolith::DISPLAY_CALENDARS));
}
} catch (Exception $e) {
return '' . $e->getMessage() . '';
}
$html = '';
/* How many days do we need to check. */
$days = Date_Calc::dateDiff($startDate->mday, $startDate->month, $startDate->year,
$endDate->mday, $endDate->month, $endDate->year);
/* Loop through the days. */
for ($i = 0; $i < $days; ++$i) {
$day = new Kronolith_Day($startDate->month, $startDate->mday + $i, $startDate->year);
if (empty($all_events[$day->dateString()])) {
continue;
}
/* Output month header. */
if ($current_month != $day->month) {
$current_month = $day->strftime('%m');
$html .= '' . $day->strftime('%B') . ' | ';
}
$firstevent = true;
$tomorrow = $day->getTomorrow();
foreach ($all_events[$day->dateString()] as $event) {
if ($event->start->compareDate($day) < 0) {
$event->start = new Horde_Date($day);
}
if ($event->end->compareDate($tomorrow) >= 0) {
$event->end = $tomorrow;
}
if ($event->end->compareDate($startDate) < 0) {
continue;
}
if ($this->_params['alarms'] && !$event->alarm) {
continue;
}
if ($firstevent) {
$html .= '';
if ($day->isToday()) {
$html .= _("Today");
} elseif ($day->isTomorrow()) {
$html .= _("Tomorrow");
} else {
$html .= $day->mday;
}
$html .= ' | ';
$firstevent = false;
} else {
$html .= ' | ';
}
$html .= '';
if ($event->start->compareDate($startDate) < 0 &&
$event->end->compareDate($startDate) > 0) {
$html .= '' . htmlspecialchars($event->getLocation()) . '';
} else {
$html .= htmlspecialchars($event->getLocation());
}
if ($event->start->compareDate($startDate) < 0 &&
$event->end->compareDate($startDate) > 0) {
$html .= '';
}
$html .= $event->getLink(null, true, null, true);
if ($event->start->compareDate($startDate) < 0 &&
$event->end->compareDate($startDate) > 0) {
$html .= '';
}
$html .= ' | ';
}
}
if (empty($html)) {
return '' . _("No events to display") . '';
}
return '';
}
}
kronolith-4.2.13/lib/Block/Summary.php 0000664 0000765 0000024 00000017143 12654566222 014520 0 ustar _params['days'])) {
$this->_params['days'] = 7;
}
$this->_name = _("Calendar Summary");
}
/**
*/
protected function _params()
{
$params = array(
'calendar' => array(
'name' => _("Calendar"),
'type' => 'enum',
'default' => '__all'
),
'days' => array(
'name' => _("The time span to show"),
'type' => 'enum',
'default' => 7,
'values' => array(
1 => '1 ' . _("day"),
2 => '2 ' . _("days"),
3 => '3 ' . _("days"),
4 => '4 ' . _("days"),
5 => '5 ' . _("days"),
6 => '6 ' . _("days"),
7 => '1 ' . _("week"),
14 => '2 ' . _("weeks"),
21 => '3 ' . _("weeks"),
28 => '4 ' . _("weeks")
)
),
'maxevents' => array(
'name' => _("Maximum number of events to display (0 = no limit)"),
'type' => 'int',
'default' => 0
),
'alarms' => array(
'name' => _("Show only events that have an alarm set?"),
'type' => 'checkbox',
'default' => 0
)
);
$params['calendar']['values']['__all'] = _("All Visible");
foreach (Kronolith::listCalendars(Horde_Perms::SHOW, true) as $id => $cal) {
$params['calendar']['values'][$id] = $cal->name();
}
return $params;
}
/**
*/
protected function _title()
{
$url = Horde::url($GLOBALS['registry']->getInitialPage(), true);
if (isset($this->_params['calendar']) &&
$this->_params['calendar'] != '__all') {
$url->add('display_cal', $this->_params['calendar']);
}
return $url->link()
. htmlspecialchars($GLOBALS['registry']->get('name')) . '';
}
/**
*/
protected function _content()
{
$GLOBALS['page_output']->addScriptFile('tooltips.js', 'horde');
$now = new Horde_Date($_SERVER['REQUEST_TIME']);
$today = date('j');
$startDate = new Horde_Date(array('year' => date('Y'), 'month' => date('n'), 'mday' => date('j')));
$endDate = new Horde_Date(array('year' => date('Y'), 'month' => date('n'), 'mday' => date('j') + $this->_params['days']));
try {
if (isset($this->_params['calendar']) &&
$this->_params['calendar'] != '__all') {
$calendars = Kronolith::listCalendars();
if (!isset($calendars[$this->_params['calendar']])) {
return _("Calendar not found");
}
if (!$calendars[$this->_params['calendar']]->hasPermission(Horde_Perms::READ)) {
return _("Permission Denied");
}
list($type, $calendar) = explode('_', $this->_params['calendar'], 2);
$driver = Kronolith::getDriver($type, $calendar);
$all_events = Kronolith::sortEvents(
$driver->listEvents(
$startDate, $endDate, array('show_recurrence' => true))
);
} else {
$all_events = Kronolith::listEvents(
$startDate, $endDate, $GLOBALS['calendar_manager']->get(Kronolith::DISPLAY_CALENDARS));
}
} catch (Exception $e) {
return '' . $e->getMessage() . '';
}
$html = '';
$iMax = $today + $this->_params['days'];
$firstday = true;
$totalevents = 0;
for ($i = $today; $i < $iMax; ++$i) {
$day = new Kronolith_Day(date('n'), $i);
$date_stamp = $day->dateString();
if (empty($all_events[$date_stamp])) {
continue;
}
$firstevent = true;
$tomorrow = $day->getTomorrow();
foreach ($all_events[$date_stamp] as $event) {
if (!empty($this->_params['maxevents']) &&
$totalevents >= $this->_params['maxevents']) {
break 2;
}
if ($event->start->compareDate($day) < 0) {
$event->start = $day;
}
if ($event->end->compareDate($tomorrow) >= 0) {
$event->end = $tomorrow;
}
if ($event->end->compareDateTime($now) < 0) {
continue;
}
if (!empty($this->_params['alarms']) && !$event->alarm) {
continue;
}
$event_active = $event->start->compareDateTime($now) < 0 &&
$event->end->compareDateTime($now) > 0;
if ($firstevent) {
$html .= '';
if ($day->isToday()) {
$dayname = _("Today");
} elseif ($day->isTomorrow()) {
$dayname = _("Tomorrow");
} elseif ($day->diff() < 7) {
$dayname = $day->strftime('%A');
} else {
$dayname = $day->strftime($GLOBALS['prefs']->getValue('date_format'));
}
$url = Horde::url('day.php', true)
->setRaw(false)
->add('date', $day->dateString());
if (isset($this->_params['calendar']) &&
$this->_params['calendar'] != '__all') {
$url->add('display_cal', $this->_params['calendar']);
}
$html .= $url->link(array('title' => sprintf(_("Goto %s"), $dayname)))
. $dayname . ' | ';
$firstevent = false;
$firstday = false;
}
$html .= '';
if ($event_active) {
$html .= '';
}
if ($event->isAllDay()) {
$time = _("All day");
} else {
$time = $event->start->format($GLOBALS['prefs']->getValue('twentyFour') ? 'H:i' : 'h:ia')
. '-' . $event->end->format($GLOBALS['prefs']->getValue('twentyFour') ? 'H:i' : 'h:ia');
}
$html .= $time;
if ($event_active) {
$html .= '';
}
$html .= ' | ';
$html .= 'getCSSColors() . '>';
if ($event_active) {
$html .= '';
}
$html .= ' ' . $event->getLink(null, true, null, true, true);
if ($event_active) {
$html .= '';
}
$html .= ' | ';
$totalevents++;
}
}
if (empty($html)) {
return '' . _("No events to display") . '';
}
return '';
}
}
kronolith-4.2.13/lib/Calendar/External/Tasks.php 0000664 0000765 0000024 00000006361 12654566222 016411 0 ustar
* @package Kronolith
*/
class Kronolith_Calendar_External_Tasks extends Kronolith_Calendar_External
{
/**
* The share of this task list.
*
* @var Horde_Share_Object
*/
protected $_share;
/**
* Constructor.
*
* @param array $params A hash with any parameters that this calendar
* might need.
* Required parameters:
* - share: The share of this calendar.
*/
public function __construct($params = array())
{
if (!isset($params['share'])) {
throw new BadMethodCallException('share parameter is missing');
}
Kronolith_Calendar::__construct($params);
}
/**
* Returns a hash representing this calendar.
*
* @return array A simple hash.
*/
public function toHash()
{
global $calendar_manager, $conf, $injector, $registry;
$owner = $registry->getAuth() &&
$this->_share->get('owner') == $registry->getAuth();
$hash = parent::toHash();
$hash['name'] = Kronolith::getLabel($this->_share);
$hash['desc'] = (string)$this->_share->get('desc');
$hash['owner'] = $owner;
$hash['users'] = Kronolith::listShareUsers($this->_share);
$hash['fg'] = Kronolith::foregroundColor($this->_share);
$hash['bg'] = Kronolith::backgroundColor($this->_share);
$hash['show'] = in_array(
'tasks/' . $this->_share->getName(),
$calendar_manager->get(Kronolith::DISPLAY_EXTERNAL_CALENDARS)
);
$hash['edit'] = $this->_share->hasPermission(
$registry->getAuth(),
Horde_Perms::EDIT
);
try {
$hash['caldav'] = Horde::url(
$registry->get('webroot', 'horde')
. ($conf['urls']['pretty'] == 'rewrite'
? '/rpc/calendars/'
: '/rpc.php/calendars/'),
true,
-1
)
. $registry->convertUsername($registry->getAuth(), false) . '/'
. $injector->getInstance('Horde_Dav_Storage')
->getExternalCollectionId($this->_share->getName(), 'tasks')
. '/';
} catch (Horde_Exception $e) {
}
$hash['sub'] = Horde::url(
$registry->get('webroot', 'horde')
. ($conf['urls']['pretty'] == 'rewrite'
? '/rpc/nag/'
: '/rpc.php/nag/'),
true,
-1
)
. ($this->_share->get('owner')
? $registry->convertUsername($this->_share->get('owner'), false)
: '-system-')
. '/'
. $this->_share->getName() . '.ics';
if ($owner) {
$hash['perms'] = Kronolith::permissionToJson($this->_share->getPermission());
}
return $hash;
}
}
kronolith-4.2.13/lib/Calendar/External.php 0000664 0000765 0000024 00000005503 12654566222 015321 0 ustar
* @package Kronolith
*/
class Kronolith_Calendar_External extends Kronolith_Calendar
{
/**
* The application of this timeobject source.
*
* @var string
*/
protected $_api;
/**
* The ID of this timeobject source.
*
* @var string
*/
protected $_id;
/**
* The name of this timeobject source.
*
* @var string
*/
protected $_name;
/**
* The type of timeobject.
* I.e., a single or share type.
*
* @var string
*/
protected $_type = 'share';
/**
* Constructor.
*
* @param array $params A hash with any parameters that this calendar
* might need.
*/
public function __construct($params = array())
{
if (!isset($params['name'])) {
throw new BadMethodCallException('name parameter is missing');
}
if (!isset($params['id'])) {
throw new BadMethodCallException('id parameter is missing');
}
if (!isset($params['api'])) {
throw new BadMethodCallException('api parameter is missing');
}
if (!empty($params['type'])) {
$this->_type = $params['type'];
}
parent::__construct($params);
}
/**
* Returns the name of this calendar.
*
* @return string This calendar's name.
*/
public function name()
{
return $this->_name;
}
/**
* Whether this calendar is supposed to be displayed in lists.
*
* @return boolean True if this calendar should be displayed.
*/
public function display()
{
return empty($GLOBALS['conf']['share']['hidden']) ||
$this->_type != 'share' ||
in_array($this->_api . '/' . $this->_id, $GLOBALS['calendar_manager']->get(Kronolith::DISPLAY_EXTERNAL_CALENDARS));
}
/**
* Returns the application of this calendar.
*
* @return string This calendar's timeobject application.
*/
public function api()
{
return $this->_api;
}
/**
* Returns a hash representing this calendar.
*
* @return array A simple hash.
*/
public function toHash()
{
$hash = parent::toHash();
$hash['api'] = $GLOBALS['registry']->get('name', $GLOBALS['registry']->hasInterface($this->api()));
$hash['show'] = in_array($this->_api . '/' . $this->_id, $GLOBALS['calendar_manager']->get(Kronolith::DISPLAY_EXTERNAL_CALENDARS));
return $hash;
}
}
kronolith-4.2.13/lib/Calendar/Holiday.php 0000664 0000765 0000024 00000003427 12654566222 015133 0 ustar
* @package Kronolith
*/
class Kronolith_Calendar_Holiday extends Kronolith_Calendar
{
/**
* The Date_Holidays driver information.
*
* @var array
*/
protected $_driver;
/**
* Constructor.
*
* @param array $params A hash with any parameters that this calendar
* might need.
* Required parameters:
* - share: The share of this calendar.
*/
public function __construct($params = array())
{
if (!isset($params['driver'])) {
throw new BadMethodCallException('driver parameter is missing');
}
parent::__construct($params);
}
/**
* Returns the name of this calendar.
*
* @return string This calendar's name.
*/
public function name()
{
return Horde_Nls_Translation::t($this->_driver['title']);
}
/**
* Whether this calendar is supposed to be displayed in lists.
*
* @return boolean True if this calendar should be displayed.
*/
public function display()
{
return in_array($this->_driver['id'], $GLOBALS['calendar_manager']->get(Kronolith::DISPLAY_HOLIDAYS));
}
/**
* Returns a hash representing this calendar.
*
* @return array A simple hash.
*/
public function toHash()
{
$hash = parent::toHash();
$hash['show'] = $this->display();
return $hash;
}
}
kronolith-4.2.13/lib/Calendar/Internal.php 0000664 0000765 0000024 00000012757 12654566222 015324 0 ustar
* @package Kronolith
*/
class Kronolith_Calendar_Internal extends Kronolith_Calendar
{
/**
* The share of this calendar.
*
* @var Horde_Share_Object
*/
protected $_share;
/**
* Constructor.
*
* @param array $params A hash with any parameters that this calendar
* might need.
* Required parameters:
* - share: The share of this calendar.
*/
public function __construct($params = array())
{
if (!isset($params['share'])) {
throw new BadMethodCallException('share parameter is missing');
}
if (!($params['share'] instanceof Horde_Share_Object)) {
throw new InvalidArgumentException('share parameter is not a Horde_Share_Object');
}
parent::__construct($params);
}
/**
* Returns the owner of this calendar.
*
* @return string This calendar's owner.
*/
public function owner()
{
return $this->_share->get('owner');
}
/**
* Returns the name of this calendar.
*
* @return string This calendar's name.
*/
public function name()
{
return Kronolith::getLabel($this->_share);
}
/**
* Returns the description of this calendar.
*
* @return string This calendar's description.
*/
public function description()
{
return $this->_share->get('desc');
}
/**
* Returns the background color for this calendar.
*
* @return string A HTML color code.
*/
public function background()
{
$color = $this->_share->get('color');
return empty($color) ? parent::background() : $color;
}
/**
* Encapsulates permissions checking.
*
* @param integer $permission The permission to check for.
* @param string $user The user to check permissions for. Defaults
* to the current user.
* @param string $creator An event creator, to check for creator
* permissions.
*
* @return boolean Whether the user has the permission on this calendar.
*/
public function hasPermission($permission, $user = null, $creator = null)
{
if ($user === null) {
$user = $GLOBALS['registry']->getAuth();
}
return $this->_share->hasPermission($user, $permission, $creator);
}
/**
* Whether this calendar is supposed to be displayed in lists.
*
* @return boolean True if this calendar should be displayed.
*/
public function display()
{
return $this->owner() == $GLOBALS['registry']->getAuth() ||
empty($GLOBALS['conf']['share']['hidden']) ||
in_array($this->_share->getName(), $GLOBALS['calendar_manager']->get(Kronolith::DISPLAY_CALENDARS));
}
/**
* Returns the share of this calendar.
*
* @return Horde_Share_Object This calendar's share.
*/
public function share()
{
return $this->_share;
}
/**
* Returns a hash representing this calendar.
*
* @return array A simple hash.
*/
public function toHash()
{
global $calendar_manager, $conf, $injector, $registry;
$id = $this->_share->getName();
$owner = $registry->getAuth() &&
$this->owner() == $registry->getAuth();
$hash = parent::toHash();
$hash['name'] = $this->name();
$hash['owner'] = $owner;
$hash['users'] = Kronolith::listShareUsers($this->_share);
$hash['show'] = in_array(
$id,
$calendar_manager->get(Kronolith::DISPLAY_CALENDARS)
);
$hash['edit'] = $this->hasPermission(Horde_Perms::EDIT);
$hash['delete'] = $this->hasPermission(Horde_Perms::DELETE);
try {
$hash['caldav'] = Horde::url(
$registry->get('webroot', 'horde')
. ($conf['urls']['pretty'] == 'rewrite'
? '/rpc/calendars/'
: '/rpc.php/calendars/'),
true,
-1
)
. $registry->convertUsername($registry->getAuth(), false) . '/'
. $injector->getInstance('Horde_Dav_Storage')
->getExternalCollectionId($id, 'calendar')
. '/';
} catch (Horde_Exception $e) {
}
$hash['sub'] = Horde::url(
$registry->get('webroot', 'horde')
. ($conf['urls']['pretty'] == 'rewrite'
? '/rpc/kronolith/'
: '/rpc.php/kronolith/'),
true,
-1
)
. ($this->owner() ? $registry->convertUsername($this->owner(), false) : '-system-') . '/'
. $id . '.ics';
$hash['feed'] = (string)Kronolith::feedUrl($id);
$hash['embed'] = Kronolith::embedCode($id);
$hash['tg'] = array_values(Kronolith::getTagger()->getTags($id, Kronolith_Tagger::TYPE_CALENDAR));
if ($owner) {
$hash['perms'] = Kronolith::permissionToJson($this->_share->getPermission());
}
return $hash;
}
}
kronolith-4.2.13/lib/Calendar/Remote.php 0000664 0000765 0000024 00000011157 12654566222 014774 0 ustar
* @package Kronolith
*/
class Kronolith_Calendar_Remote extends Kronolith_Calendar
{
/**
* The URL of this calendar.
*
* @var string
*/
protected $_url;
/**
* The name of this calendar.
*
* @var string
*/
protected $_name;
/**
* The description of this calendar.
*
* @var string
*/
protected $_desc = '';
/**
* The HTTP user name for this calendar.
*
* @var string
*/
protected $_user;
/**
* The HTTP password for this calendar.
*
* @var string
*/
protected $_password;
/**
* The color of this calendar.
*
* @var string
*/
protected $_color;
/**
* Constructor.
*
* @param array $params A hash with any parameters that this calendar
* might need.
* Required parameters:
* - share: The share of this calendar.
*/
public function __construct($params = array())
{
if (!isset($params['url'])) {
throw new BadMethodCallException('url parameter is missing');
}
if (!isset($params['name'])) {
throw new BadMethodCallException('name parameter is missing');
}
$key = $GLOBALS['registry']->getAuthCredential('password');
if ($key) {
$secret = $GLOBALS['injector']->getInstance('Horde_Secret');
if (!empty($params['user'])) {
$params['user'] = $secret->read($key, base64_decode($params['user']));
}
if (!empty($params['password'])) {
$params['password'] = $secret->read($key, base64_decode($params['password']));
}
}
parent::__construct($params);
}
/**
* Returns the name of this calendar.
*
* @return string This calendar's name.
*/
public function name()
{
return $this->_name;
}
/**
* Returns the description of this calendar.
*
* @return string This calendar's description.
*/
public function description()
{
return $this->_desc;
}
/**
* Returns the background color for this calendar.
*
* @return string A HTML color code.
*/
public function background()
{
return empty($this->_color) ? parent::background() : $this->_color;
}
/**
* Encapsulates permissions checking.
*
* @param integer $permission The permission to check for.
* @param string $user The user to check permissions for. Defaults
* to the current user.
* @param string $creator An event creator, to check for creator
* permissions.
*
* @return boolean Whether the user has the permission on this calendar.
*/
public function hasPermission($permission, $user = null, $creator = null)
{
return (boolean)(Kronolith::getDriver('Ical', $this->_url)->getPermission() & $permission);
}
/**
* Whether this calendar is supposed to be displayed in lists.
*
* @return boolean True if this calendar should be displayed.
*/
public function display()
{
return in_array($this->_url, $GLOBALS['calendar_manager']->get(Kronolith::DISPLAY_REMOTE_CALENDARS));
}
/**
* Returns the URL of this calendar.
*
* @return string This calendar's URL.
*/
public function url()
{
return $this->_url;
}
/**
* Returns the authentication credentials for this calendar.
*
* @return array This calendar's credentials.
*/
public function credentials()
{
if (!empty($this->_user)) {
return array('user' => $this->_user, 'password' => $this->_password);
}
return array();
}
/**
* Returns a hash representing this calendar.
*
* @return array A simple hash.
*/
public function toHash()
{
return array_merge(
parent::toHash(),
array('show' => in_array($this->_url, $GLOBALS['calendar_manager']->get(Kronolith::DISPLAY_REMOTE_CALENDARS)),
'edit' => $this->hasPermission(Horde_Perms::EDIT)),
$this->credentials()
);
}
}
kronolith-4.2.13/lib/Calendar/Resource.php 0000664 0000765 0000024 00000007525 12654566222 015334 0 ustar
* @package Kronolith
*/
class Kronolith_Calendar_Resource extends Kronolith_Calendar
{
/**
* The share of this calendar.
*
* @var Kronolith_Resource_Single
*/
protected $_resource;
/**
* Constructor.
*
* @param array $params A hash with any parameters that this calendar
* might need.
* Required parameters:
* - share: The share of this calendar.
*/
public function __construct($params = array())
{
if (!isset($params['resource'])) {
throw new BadMethodCallException('resource parameter is missing.');
}
if (!($params['resource'] instanceof Kronolith_Resource_Single)) {
throw new InvalidArgumentException('resource parameter is not a Kronolith_Resource_Single object.');
}
parent::__construct($params);
}
/**
* Returns the owner of this calendar.
*
* @return string This calendar's owner.
*/
public function owner()
{
// @TODO: what to return here? Resources do not currently have owners.
return '';
}
/**
* Returns the name of this calendar.
*
* @return string This calendar's name.
*/
public function name()
{
return $this->_resource->get('name');
}
/**
* Returns the description of this calendar.
*
* @return string This calendar's description.
*/
public function description()
{
return $this->_resource->get('description');
}
/**
* Encapsulates permissions checking.
*
* @param integer $permission The permission to check for.
* @param string $user The user to check permissions for. Defaults
* to the current user.
* @param string $creator An event creator, to check for creator
* permissions.
*
* @return boolean Whether the user has the permission on this calendar.
*/
public function hasPermission($permission, $user = null, $creator = null)
{
return $this->_resource->hasPermission($user, $permission, $creator);
}
/**
* Whether this calendar is supposed to be displayed in lists.
*
* @return boolean True if this calendar should be displayed.
*/
public function display()
{
return in_array($this->_resource->get('calendar'), $GLOBALS['calendar_manager']->get(Kronolith::DISPLAY_RESOURCE_CALENDARS));
}
/**
* Returns a hash representing this calendar.
*
* @return array A simple hash.
*/
public function toHash()
{
global $registry, $injector;
$owner = $registry->isAdmin() ||
$injector->getInstance('Horde_Core_Perms')
->hasAppPermission('resource_management');
$hash = parent::toHash();
$hash['id'] = $this->_resource->getId();
$hash['name'] = $this->name();
$hash['owner'] = $owner;
$hash['show'] = $this->display();
$hash['edit'] = $this->hasPermission(Horde_Perms::EDIT);
$hash['sub'] = null;
$hash['feed'] = null;
$hash['embed'] = null;
$hash['response_type'] = $this->_resource->get('response_type');
if ($owner) {
$hash['perms'] = array(
'type' => 'matrix',
'default' => 0,
'guest' => 0,
'creator' => 0);
}
return $hash;
}
}
kronolith-4.2.13/lib/Calendar/ResourceGroup.php 0000664 0000765 0000024 00000007350 12654566222 016345 0 ustar
* @author Michael J Rubinsky
* @package Kronolith
*/
class Kronolith_Calendar_ResourceGroup extends Kronolith_Calendar
{
/**
* The share of this calendar.
*
* @var Kronolith_Resource_Group
*/
protected $_resource;
/**
* Constructor.
*
* @param array $params A hash with any parameters that this calendar
* might need.
* Required parameters:
* - share: The share of this calendar.
*/
public function __construct($params = array())
{
if (!isset($params['resource'])) {
throw new BadMethodCallException('resource parameter is missing.');
}
if (!($params['resource'] instanceof Kronolith_Resource_Group)) {
throw new InvalidArgumentException('resource parameter is not a Kronolith_Resource_Single object.');
}
parent::__construct($params);
}
/**
* Returns the owner of this calendar.
*
* @return string This calendar's owner.
*/
public function owner()
{
// @TODO: what to return here? Resources do not currently have owners.
return '';
}
/**
* Returns the name of this calendar.
*
* @return string This calendar's name.
*/
public function name()
{
return $this->_resource->get('name');
}
/**
* Returns the description of this calendar.
*
* @return string This calendar's description.
*/
public function description()
{
return $this->_resource->get('description');
}
/**
* Encapsulates permissions checking.
*
* @param integer $permission The permission to check for.
* @param string $user The user to check permissions for. Defaults
* to the current user.
* @param string $creator An event creator, to check for creator
* permissions.
*
* @return boolean Whether the user has the permission on this calendar.
*/
public function hasPermission($permission, $user = null, $creator = null)
{
return $this->_resource->hasPermission($user, $permission, $creator);
}
/**
* Whether this calendar is supposed to be displayed in lists.
*
* @return boolean True if this calendar should be displayed.
*/
public function display()
{
return in_array($this->_resource->get('calendar'), $GLOBALS['calendar_manager']->get(Kronolith::DISPLAY_CALENDARS));
}
/**
* Returns a hash representing this calendar.
*
* @return array A simple hash.
*/
public function toHash()
{
$owner = $GLOBALS['registry']->isAdmin();
$hash = parent::toHash();
$hash['id'] = $this->_resource->getId();
$hash['name'] = $this->name();
$hash['owner'] = $owner;
$hash['show'] = $this->display();
$hash['edit'] = $this->hasPermission(Horde_Perms::EDIT);
$hash['sub'] = null;
$hash['feed'] = null;
$hash['embed'] = null;
$hash['members'] = $this->_resource->get('members');
if ($owner) {
$hash['perms'] = array(
'type' => 'matrix',
'default' => 0,
'guest' => 0,
'creator' => 0);
}
return $hash;
}
}
kronolith-4.2.13/lib/Calendars/Base.php 0000664 0000765 0000024 00000005120 12654566222 014567 0 ustar
* @package Kronolith
*/
abstract class Kronolith_Calendars_Base
{
/**
* The share backend.
*
* @var Horde_Share_Base
*/
protected $_shares;
/**
* The current user.
*
* @var string
*/
protected $_user;
/**
* Additional parameters for the tasklist handling.
*
* @var array
*/
protected $_params;
/**
* Constructor.
*
* @param Horde_Share_Base $shares The share backend.
* @param string $user The current user.
* @param array $params Additional parameters.
*/
public function __construct($shares, $user, $params)
{
$this->_shares = $shares;
$this->_user = $user;
$this->_params = $params;
}
/**
* Create the default calendar share for the current user.
*
* @return Horde_Share_Object The new default share.
*/
public function createDefaultShare()
{
$share = $this->_shares->newShare(
$this->_user,
strval(new Horde_Support_Randomid()),
$this->_getDefaultShareName()
);
$share->set('color', Kronolith::randomColor());
$this->_prepareDefaultShare($share);
$this->_shares->addShare($share);
return $share;
}
/**
* Returns the default share's ID, if it can be determined from the share
* backend.
*
* @return string The default share ID.
*/
public function getDefaultShare()
{
$shares = $this->_shares->listShares(
$this->_user,
array('attributes' => $this->_user)
);
foreach ($shares as $id => $share) {
if ($share->get('default')) {
return $id;
}
}
}
/**
* Runs any actions after setting a new default tasklist.
*
* @param string $share The default share ID.
*/
public function setDefaultShare($share)
{
}
/**
* Return the name of the default share.
*
* @return string The name of a default share.
*/
abstract protected function _getDefaultShareName();
/**
* Add any modifiers required to the share in order to mark it as default
*
* @param Horde_Share_Object $share The new default share.
*/
protected function _prepareDefaultShare($share)
{
}
} kronolith-4.2.13/lib/Calendars/Default.php 0000664 0000765 0000024 00000002425 12654566222 015306 0 ustar
* @package Kronolith
*/
class Kronolith_Calendars_Default extends Kronolith_Calendars_Base
{
/**
* The current identity.
*
* @var Horde_Prefs_Identity
*/
private $_identity;
/**
* Constructor.
*
* @param Horde_Share_Base $shares The share backend.
* @param string $user The current user.
* @param array $params Additional parameters.
*/
public function __construct($shares, $user, $params)
{
if (!isset($params['identity'])) {
throw new BadMethodCallException('This calendars handler needs an "identity" parameter!');
} else {
$this->_identity = $params['identity'];
unset($params['identity']);
}
parent::__construct($shares, $user, $params);
}
/**
* Return the name of the default share.
*
* @return string The name of a default share.
*/
protected function _getDefaultShareName()
{
return sprintf(_("Calendar of %s"), $this->_identity->getName());
}
} kronolith-4.2.13/lib/Calendars/Kolab.php 0000664 0000765 0000024 00000002653 12654566222 014755 0 ustar
* @package Kronolith
*/
class Kronolith_Calendars_Kolab extends Kronolith_Calendars_Base
{
/**
* Runs any actions after setting a new default calendar.
*
* @param string $share The default share ID.
*/
public function setDefaultShare($share)
{
$calendars = $this->_shares
->listShares(
$this->_user,
array('perm' => Horde_Perms::SHOW,
'attributes' => $this->_user));
foreach ($calendars as $id => $calendar) {
if ($id == $share) {
$calendar->set('default', true);
$calendar->save();
break;
}
}
}
/**
* Return the name of the default share.
*
* @return string The name of a default share.
*/
protected function _getDefaultShareName()
{
return _("Calendar");
}
/**
* Add any modifiers required to the share in order to mark it as default
*
* @param Horde_Share_Object $share The new default share.
*/
protected function _prepareDefaultShare($share)
{
$share->set('default', true);
}
} kronolith-4.2.13/lib/Driver/Resource/Sql.php 0000664 0000765 0000024 00000046063 12654566222 015615 0 ustar
* @author Chuck Hagenbuch
* @author Jan Schneider
* @author Michael J Rubinsky
* @package Kronolith
*/
class Kronolith_Driver_Resource_Sql extends Kronolith_Driver
{
/**
* The main event storage driver.
*
* @var Kronolith_Driver
*/
protected $_driver;
/**
* Column information as Horde_Db_Adapter_Base_Column objects.
*
* @var array
*/
protected $_columns = array();
/**
* The class name of the event object to instantiate.
*
* @var string
*/
protected $_eventClass = 'Kronolith_Event_Resource_Sql';
/**
* Attempts to open a connection to the SQL server.
*
* @throws Kronolith_Exception
*/
public function initialize()
{
if (empty($this->_params['db'])) {
throw new InvalidArgumentException('Missing required Horde_Db_Adapter instance');
}
try {
$this->_db = $this->_params['db'];
} catch (Horde_Exception $e) {
throw new Kronolith_Exception($e);
}
$this->_params = array_merge(array(
'table' => 'kronolith_resources'
), $this->_params);
$this->_driver = Kronolith::getDriver();
$this->_columns = $this->_db->columns($this->_params['table']);
}
/**
* Selects a calendar as the currently opened calendar.
*
* @param string $calendar A calendar identifier.
*/
public function open($calendar)
{
$this->calendar = $calendar;
$this->_driver->open($calendar);
}
/**
* Lists all events in the time range, optionally restricting results to
* only events with alarms.
*
* @param Horde_Date $startDate The start of range date.
* @param Horde_Date $endDate The end of date range.
* @param array $options Additional options:
* - show_recurrence: (boolean) Return every instance of a recurring
* event?
* DEFAULT: false (Only return recurring events once
* inside $startDate - $endDate range)
* - has_alarm: (boolean) Only return events with alarms.
* DEFAULT: false (Return all events)
* - json: (boolean) Store the results of the event's toJson()
* method?
* DEFAULT: false
* - cover_dates: (boolean) Add the events to all days that they
* cover?
* DEFAULT: true
* - hide_exceptions: (boolean) Hide events that represent exceptions to
* a recurring event.
* DEFAULT: false (Do not hide exception events)
* - fetch_tags: (boolean) Fetch tags for all events.
* DEFAULT: false (Do not fetch event tags)
*
* @throws Kronolith_Exception
*/
public function listEvents(Horde_Date $startDate = null,
Horde_Date $endDate = null,
array $options = array())
{
$json = !empty($options['json']);
$options['json'] = false;
$events = $this->_driver->listEvents($startDate, $endDate, $options);
$results = array();
foreach ($events as $period_key => $period) {
foreach ($period as $event_id => $event) {
$resource_event = $this->_buildResourceEvent($event);
$results[$period_key][$event_id] = $json
? $resource_event->toJson()
: $resource_event;
}
}
return $results;
}
protected function _buildResourceEvent($driver_event)
{
$resource_event = new $this->_eventClass($this);
$resource_event->fromDriver($driver_event->toProperties(true));
$resource_event->calendar = $this->calendar;
return $resource_event;
}
/**
* Get an event or events with the given UID value.
*
* @param string $uid The UID to match
* @param array $calendars A restricted array of calendar ids to search
* @param boolean $getAll Return all matching events?
*
* @return Kronolith_Event
* @throws Kronolith_Exception
* @throws Horde_Exception_NotFound
*/
public function getByUID($uid, $calendars = null, $getAll = false)
{
$event = new $this->_eventClass($this);
$driver_event = $this->_driver->getByUID($uid, $calendars, $getAll);
$event->fromDriver($driver_event->toProperties(true));
$event->calendar = $this->calendar;
return $event;
}
/**
* @throws Kronolith_Exception
* @throws Horde_Exception_NotFound
*/
public function getEvent($eventId = null)
{
if (!strlen($eventId)) {
$event = new $this->_eventClass($this);
$event->calendar = $this->calendar;
return $event;
}
$driver_event = $this->_driver->getEvent($eventId);
$event = $this->_buildResourceEvent($driver_event);
return $event;
}
/**
* Saves an event in the backend.
*
* If it is a new event, it is added, otherwise the event is updated.
*
* @param Kronolith_Event $event The event to save.
*
* @return string The event id.
* @throws Horde_Mime_Exception
* @throws Kronolith_Exception
*/
public function saveEvent(Kronolith_Event $event)
{
return $this->_driver->saveEvent($event);
}
/**
* Delete an event.
*
* Since this is the Kronolith_Resource's version of the event, if we
* delete it, we must also make sure to remove it from the event that
* it is attached to. Not sure if there is a better way to do this...
*
* @param string|Kronolith_Event_Resource_Sql $eventId The ID of the event
* to delete.
* @param boolean $silent Don't send notifications, used when deleting
* events in bulk from maintenance tasks.
* @param boolean $keep_bound If true, does not remove the resource from
* the bound event. @since 4.2.2
*
* @throws Kronolith_Exception
* @throws Horde_Exception_NotFound
*/
public function deleteEvent($eventId, $silent = false, $keep_bound = false)
{
if ($eventId instanceof Kronolith_Event_Resource_Sql) {
$delete_event = $eventId;
$eventId = $delete_event->id;
} else {
$delete_event = $this->getEvent($eventId);
}
if ($keep_bound) {
return;
}
$uid = $delete_event->uid;
$events = $this->_driver->getByUID($uid, null, true);
foreach ($events as $e) {
$resources = $e->getResources();
if (count($resources)) {
$r = $this->getResource($this->getResourceIdByCalendar($delete_event->calendar));
$e->removeResource($r);
$e->save();
}
}
$this->_driver->open($this->calendar);
$this->_driver->deleteEvent($delete_event, $silent);
}
/**
* Save or update a Kronolith_Resource
*
* @param Kronolith_Resource_Base $resource
*
* @return Kronolith_Resource object
* @throws Kronolith_Exception, Horde_Exception_PermissionDenied
*/
public function save(Kronolith_Resource_Base $resource)
{
if (!$GLOBALS['registry']->isAdmin() &&
!$GLOBALS['injector']->getInstance('Horde_Core_Perms')->hasAppPermission('resource_management')) {
throw new Horde_Exception_PermissionDenied();
}
if ($resource->getId()) {
$query = 'UPDATE ' . $this->_params['table'] . ' SET resource_name = ?, '
. 'resource_calendar = ? , resource_description = ?, '
. 'resource_response_type = ?, resource_type = ?, '
. 'resource_members = ?, resource_email = ? WHERE resource_id = ?';
$values = array($this->convertToDriver($resource->get('name')),
$resource->get('calendar'),
$this->convertToDriver($resource->get('description')),
$resource->get('response_type'),
$resource->get('type'),
serialize($resource->get('members')),
$resource->get('email'),
$resource->getId());
try {
$this->_db->update($query, $values);
} catch (Horde_Db_Exception $e) {
throw new Kronolith_Exception($e);
}
} else {
$query = 'INSERT INTO ' . $this->_params['table']
. ' (resource_name, resource_calendar, '
. 'resource_description, resource_response_type, '
. ' resource_type, resource_members, resource_email)'
. ' VALUES (?, ?, ?, ?, ?, ?, ?)';
$values = array($this->convertToDriver($resource->get('name')),
$resource->get('calendar'),
$this->convertToDriver($resource->get('description')),
$resource->get('response_type'),
$resource->get('type'),
serialize($resource->get('members')),
$resource->get('email'));
try {
$id = $this->_db->insert($query, $values);
} catch (Horde_Db_Exception $e) {
throw new Kronolith_Exception($e);
}
$resource->setId($id);
}
return $resource;
}
/**
* Removes a resource from storage, along with any events in the resource's
* calendar.
*
* @param Kronolith_Resource_Base $resource The kronolith resource to remove
*
* @throws Kronolith_Exception, Horde_Exception_PermissionDenied
*/
public function delete($resource)
{
if (!$GLOBALS['registry']->isAdmin() &&
!$GLOBALS['injector']->getInstance('Horde_Core_Perms')->hasAppPermission('resource_management')) {
throw new Horde_Exception_PermissionDenied();
}
if (!$resource->getId()) {
throw new Kronolith_Exception(_("Resource not valid."));
}
// Get group memberships and remove from group.
$groups = $this->getGroupMemberships($resource->getId());
foreach ($groups as $id) {
$rg = $this->getResource($id);
$members = $rg->get('members');
unset($members[array_search($resource->getId(), $members)]);
$rg->set('members', $members);
$rg->save();
}
$this->_deleteResourceCalendar($resource->get('calendar'));
try {
$query = 'DELETE FROM ' . $this->_params['table'] . ' WHERE resource_id = ?';
$this->_db->delete($query, array($resource->getId()));
} catch (Horde_Db_Exception $e) {
throw new Kronolith_Exception($e);
}
}
/**
* Obtain a Kronolith_Resource by the resource's id
*
* @param integer $id The key for the Kronolith_Resource
*
* @return Kronolith_Resource_Base
* @throws Kronolith_Exception
*/
public function getResource($id)
{
$query = 'SELECT resource_id, resource_name, resource_calendar, '
. 'resource_description, resource_response_type, resource_type, '
. 'resource_members, resource_email FROM ' . $this->_params['table']
. ' WHERE resource_id = ?';
try {
$results = $this->_db->selectOne($query, array($id));
} catch (Horde_Db_Exception $e) {
throw new Kronolith_Exception($e);
}
if (!count($results)) {
throw new Horde_Exception_NotFound('Resource not found');
}
$class = 'Kronolith_Resource_' . $results['resource_type'];
if (!class_exists($class)) {
throw new Kronolith_Exception('Could not load the class definition for ' . $class);
}
return new $class($this->_fromDriver($results));
}
/**
* Obtain the resource id associated with the given calendar uid.
*
* @param string $calendar The calendar's uid.
*
* @return integer The Kronolith_Resource id.
* @throws Kronolith_Exception
*/
public function getResourceIdByCalendar($calendar)
{
$query = 'SELECT resource_id FROM ' . $this->_params['table']
. ' WHERE resource_calendar = ?';
try {
$result = $this->_db->selectValue($query, array($calendar));
} catch (Horde_Db_Exception $e) {
throw new Kronolith_Exception($e);
}
if (empty($result)) {
throw new Horde_Exception_NotFound('Resource not found');
}
return $result;
}
/**
* Determine if the provided calendar id represents a resource's calendar.
*
* @param string $calendar The calendar identifier to check.
*
* @return boolean
*/
public function isResourceCalendar($calendar)
{
$query = 'SELECT count(*) FROM ' . $this->_params['table']
. ' WHERE resource_calendar = ?';
try {
return $this->_db->selectValue($query, array($calendar)) > 0;
} catch (Horde_Db_Exception $e) {
throw new Kronolith_Exception($e);
}
}
/**
* Return a list of Kronolith_Resources
*
* Right now, all users have Horde_Perms::READ, but only system admins have
* Horde_Perms::EDIT | Horde_Perms::DELETE
*
* @param integer $perms A Horde_Perms::* constant.
* @param array $filter A hash of field/values to filter on.
* @param string $orderby Field to order results by. Null for no ordering.
*
* @return an array of Kronolith_Resource objects.
* @throws Kronolith_Exception
*/
public function listResources($perms = Horde_Perms::READ, array $filter = array(), $orderby = null)
{
if (($perms & (Horde_Perms::EDIT | Horde_Perms::DELETE)) &&
!$GLOBALS['registry']->isAdmin()) {
return array();
}
$query = 'SELECT resource_id, resource_name, resource_calendar, resource_description,'
. ' resource_response_type, resource_type, resource_members, resource_email FROM '
. $this->_params['table'];
if (count($filter)) {
$clause = ' WHERE ';
$i = 0;
$c = count($filter);
foreach (array_keys($filter) as $field) {
$clause .= 'resource_' . $field . ' = ?' . (($i++ < ($c - 1)) ? ' AND ' : '');
}
$query .= $clause;
}
if (!empty($orderby)) {
$query .= ' ORDER BY resource_' . $orderby;
}
try {
$results = $this->_db->selectAll($query, $filter);
} catch (Horde_Db_Exception $e) {
throw new Kronolith_Exception($e);
}
$return = array();
foreach ($results as $row) {
$class = 'Kronolith_Resource_' . $row['resource_type'];
$return[$row['resource_id']] = new $class($this->_fromDriver(array_merge(array('resource_id' => $row['resource_id']), $row)));
}
return $return;
}
/**
* Obtain the group id for each group the specified resource is a member of.
*
* @param integer $resource_id The resource id to check for.
*
* @return array An array of group ids.
* @throws Kronolith_Exception
*/
public function getGroupMemberships($resource_id)
{
$groups = $this->listResources(Horde_Perms::READ, array('type' => Kronolith_Resource::TYPE_GROUP));
$in = array();
foreach ($groups as $group) {
$members = $group->get('members');
if (array_search($resource_id, $members) !== false) {
$in[] = $group->getId();
}
}
return $in;
}
/**
* Converts a value from the driver's charset to the default
* charset.
*
* @param mixed $value A value to convert.
*
* @return mixed The converted value.
*/
public function convertFromDriver($value)
{
return Horde_String::convertCharset($value, $this->_params['charset'], 'UTF-8');
}
/**
* Converts a value from the default charset to the driver's
* charset.
*
* @param mixed $value A value to convert.
*
* @return mixed The converted value.
*/
public function convertToDriver($value)
{
return Horde_String::convertCharset($value, 'UTF-8', $this->_params['charset']);
}
/**
* Delete the resource calendar
*
* @param string $calendar The calendar id.
*/
public function _deleteResourceCalendar($calendar)
{
$this->open($calendar);
$events = $this->listEvents(null, null, array('cover_dates' => false));
foreach ($events as $dayevents) {
foreach ($dayevents as $event) {
$this->deleteEvent($event, true);
}
}
}
/**
* Convert from driver keys and charset to Kronolith keys and charset.
*
* @param array $params The key/values to convert.
*
* @return array An array of converted values.
*/
protected function _fromDriver(array $params)
{
$return = array();
foreach ($params as $field => $value) {
switch ($field) {
case 'resource_description':
$value = $this->_columns['resource_description']
->binaryToString($value);
// Fall through.
case 'resource_name':
$value = $this->convertFromDriver($value);
break;
case 'resource_members':
$value = $this->_columns['resource_members']
->binaryToString($value);
$value = @unserialize($value);
break;
}
$return[str_replace('resource_', '', $field)] = $value;
}
return $return;
}
/**
* Helper function to update an existing event's tags to tagger storage.
*
* @param Kronolith_Event $event The event to update
*/
protected function _updateTags(Kronolith_Event $event)
{
// noop
}
/**
* Helper function to add tags from a newly creted event to the tagger.
*
* @param Kronolith_Event $event The event to save tags to storage for.
*/
protected function _addTags(Kronolith_Event $event)
{
// noop
}
protected function _handleNotifications(Kronolith_Event $event, $action)
{
// noop
}
}
kronolith-4.2.13/lib/Driver/Holidays.php 0000664 0000765 0000024 00000013553 12654566222 015041 0 ustar
* @package Kronolith
*/
class Kronolith_Driver_Holidays extends Kronolith_Driver
{
public function listAlarms($date, $fullevent = false)
{
return array();
}
/**
* Lists all events in the time range, optionally restricting results to
* only events with alarms.
*
* @param Horde_Date $startDate The start of range date.
* @param Horde_Date $endDate The end of date range.
* @param array $options Additional options:
* - show_recurrence: (boolean) Return every instance of a recurring
* event?
* DEFAULT: false (Only return recurring events once
* inside $startDate - $endDate range)
* - has_alarm: (boolean) Only return events with alarms.
* DEFAULT: false (Return all events)
* - json: (boolean) Store the results of the event's toJson()
* method?
* DEFAULT: false
* - cover_dates: (boolean) Add the events to all days that they
* cover?
* DEFAULT: true
* - hide_exceptions: (boolean) Hide events that represent exceptions to
* a recurring event.
* DEFAULT: false (Do not hide exception events)
* - fetch_tags: (boolean) Fetch tags for all events.
* DEFAULT: false (Do not fetch event tags)
*
* @throws Kronolith_Exception
*/
protected function _listEvents(Horde_Date $startDate = null,
Horde_Date $endDate = null,
array $options = array())
{
if (!class_exists('Date_Holidays')) {
Horde::log('Support for Date_Holidays has been enabled but the package seems to be missing.', 'ERR');
return array();
}
if (is_null($startDate) && !is_null($endDate)) {
$startDate = clone $endDate;
$startDate->year--;
}
if (is_null($endDate) && !is_null($startDate)) {
$endDate = clone $startDate;
$endDate->year++;
}
if ($options['has_alarm'] || is_null($startDate) || is_null($endDate)) {
return array();
}
$startDate = clone $startDate;
$startDate->hour = $startDate->min = $startDate->sec = 0;
$endDate = clone $endDate;
$endDate->hour = 23;
$endDate->min = $endDate->sec = 59;
Date_Holidays::staticSetProperty('DIE_ON_MISSING_LOCALE', false);
$results = array();
for ($year = $startDate->year; $year <= $endDate->year; $year++) {
$dh = Date_Holidays::factory($this->calendar, $year, $this->_params['language']);
if (Date_Holidays::isError($dh)) {
Horde::log(sprintf('Factory was unable to produce driver object for driver %s in year %s with locale %s',
$this->calendar, $year, $this->_params['language']), 'ERR');
continue;
}
$dh->addTranslation($this->_params['language']);
$events = $this->_getEvents($dh, $startDate, $endDate);
foreach ($events as $event) {
Kronolith::addEvents($results, $event, $startDate, $endDate,
$options['show_recurrence'],
$options['json'],
$options['cover_dates']);
}
}
return $results;
}
/**
* @throws Kronolith_Exception
* @throws Horde_Exception_NotFound
*/
public function getEvent($eventId = null)
{
if (!$eventId) {
$date = new Date();
return new Kronolith_Event_Holidays($this, new Date_Holidays_Holiday(null, null, $date, null));
}
list($id, $date) = explode('-', $eventId, 2);
$year = substr($date, 0, 4);
$dh = Date_Holidays::factory($this->calendar, $year, $this->_params['language']);
if (Date_Holidays::isError($dh)) {
Horde::log(sprintf('Factory was unable to produce driver object for driver %s in year %s with locale %s',
$this->calendar, $year, $this->_params['language']), 'ERR');
return false;
}
$dh->addTranslation($this->_params['language']);
$event = $dh->getHoliday($id);
if ($event instanceof PEAR_Error) {
throw new Horde_Exception_NotFound($event);
}
return new Kronolith_Event_Holidays($this, $event);
}
private function _getEvents($dh, $startDate, $endDate)
{
$events = array();
for ($date = new Horde_Date($startDate);
$date->compareDate($endDate) <= 0;
$date->mday++) {
$holidays = $dh->getHolidayForDate($date->format('Y-m-d'), null, true);
if (Date_Holidays::isError($holidays)) {
Horde::log(sprintf('Unable to retrieve list of holidays from %s to %s',
(string)$startDate, (string)$endDate), __FILE__, __LINE__);
continue;
}
if (is_null($holidays)) {
continue;
}
foreach ($holidays as $holiday) {
$event = new Kronolith_Event_Holidays($this, $holiday);
$events[] = $event;
}
}
return $events;
}
}
kronolith-4.2.13/lib/Driver/Horde.php 0000664 0000765 0000024 00000014227 12654566222 014325 0 ustar
* @package Kronolith
*/
class Kronolith_Driver_Horde extends Kronolith_Driver
{
/**
* The API (application) of the current calendar.
*
* @var string
*/
public $api;
public function open($calendar)
{
parent::open($calendar);
list($this->api,) = explode('/', $this->calendar, 2);
}
public function listAlarms($date, $fullevent = false)
{
return array();
}
/**
* Lists all events in the time range, optionally restricting results to
* only events with alarms.
*
* @param Horde_Date $startDate The start of range date.
* @param Horde_Date $endDate The end of date range.
* @param array $options Additional options:
* - show_recurrence: (boolean) Return every instance of a recurring
* event?
* DEFAULT: false (Only return recurring events once
* inside $startDate - $endDate range)
* - has_alarm: (boolean) Only return events with alarms.
* DEFAULT: false (Return all events)
* - json: (boolean) Store the results of the event's toJson()
* method?
* DEFAULT: false
* - cover_dates: (boolean) Add the events to all days that they
* cover?
* DEFAULT: true
* - hide_exceptions: (boolean) Hide events that represent exceptions to
* a recurring event.
* DEFAULT: false (Do not hide exception events)
* - fetch_tags: (boolean) Fetch tags for all events.
* DEFAULT: false (Do not fetch event tags)
*
* @throws Kronolith_Exception
*/
protected function _listEvents(Horde_Date $startDate = null,
Horde_Date $endDate = null,
array $options = array())
{
list($this->api, $category) = explode('/', $this->calendar, 2);
if (!$this->_params['registry']->hasMethod($this->api . '/listTimeObjects')) {
return array();
}
if (is_null($startDate)) {
$startDate = new Horde_Date(
array('mday' => 1, 'month' => 1, 'year' => 0000));
}
if (is_null($endDate)) {
$endDate = new Horde_Date(
array('mday' => 31, 'month' => 12, 'year' => 9999));
}
$startDate = clone $startDate;
$startDate->hour = $startDate->min = $startDate->sec = 0;
$endDate = clone $endDate;
$endDate->hour = 23;
$endDate->min = $endDate->sec = 59;
try {
$eventsList = $this->_params['registry']->call(
$this->api . '/listTimeObjects',
array(array($category), $startDate, $endDate));
} catch (Horde_Exception $e) {
throw new Kronolith_Exception($e);
}
$results = array();
foreach ($eventsList as $eventsListItem) {
try {
$event = new Kronolith_Event_Horde($this, $eventsListItem);
} catch (Kronolith_Exception $e) {
Horde::log($e, 'NOTICE');
continue;
}
// Ignore events out of the period.
$recurs = $event->recurs();
if (
// Starts after the period.
$event->start->compareDateTime($endDate) > 0 ||
// End before the period and doesn't recur.
(!$recurs &&
$event->end->compareDateTime($startDate) < 0)) {
continue;
}
if ($recurs) {
// Fixed end date? Check if end is before start period.
if ($event->recurrence->hasRecurEnd() &&
$event->recurrence->recurEnd->compareDateTime($startDate) < 0) {
continue;
} else {
$next = $event->recurrence->nextRecurrence($startDate);
if ($next == false || $next->compareDateTime($endDate) > 0) {
continue;
}
}
}
Kronolith::addEvents(
$results, $event, $startDate, $endDate,
$options['show_recurrence'], $options['json'], $options['cover_dates']);
}
return $results;
}
/**
* Updates an existing event in the backend.
*
* @param Kronolith_Event_Horde $event The event to save.
*
* @return string The event id.
* @throws Kronolith_Exception
*/
protected function _updateEvent(Kronolith_Event $event)
{
if (!isset($this->api)) {
list($this->api,) = explode('/', $this->calendar, 2);
}
try {
$this->_params['registry']->call($this->api . '/saveTimeObject', array($event->toTimeobject()));
} catch (Horde_Exception $e) {
throw new Kronolith_Exception($e);
}
return $event->timeobject['id'];
}
/**
* @todo: implement getTimeObject in timeobjects API.
* @throws Kronolith_Exception
* @throws Horde_Exception_NotFound
*/
public function getEvent($eventId = null, $start = null)
{
$end = null;
if ($start) {
$start = new Horde_Date($start);
$end = clone $start;
$end->mday++;
}
$events = $this->listEvents(
$start,
$end,
array('show_recurrence' => (bool)$start));
foreach ($events as $day) {
if (isset($day[$eventId])) {
return $day[$eventId];
}
}
throw new Horde_Exception_NotFound(_("Event not found"));
}
}
kronolith-4.2.13/lib/Driver/Ical.php 0000664 0000765 0000024 00000073063 12654566222 014137 0 ustar
* @author Jan Schneider
* @package Kronolith
*/
class Kronolith_Driver_Ical extends Kronolith_Driver
{
/**
* Cache events as we fetch them to avoid fetching or parsing the same
* event twice.
*
* @var array
*/
protected $_cache = array();
/**
* HTTP client object.
*
* @var Horde_Http_Client
*/
protected $_client;
/**
* A list of DAV support levels.
*
* @var array
*/
protected $_davSupport;
/**
* The Horde_Perms permissions mask matching the CalDAV ACL.
*
* @var integer
*/
protected $_permission;
/**
* Selects a calendar as the currently opened calendar.
*
* @param string $calendar A calendar identifier.
*/
public function open($calendar)
{
parent::open($calendar);
$this->_client = null;
$this->_permission = 0;
unset($this->_davSupport);
}
/**
* Returns the background color of the current calendar.
*
* @return string The calendar color.
*/
public function backgroundColor()
{
return $GLOBALS['calendar_manager']->getEntry(Kronolith::ALL_REMOTE_CALENDARS, $this->calendar)
? $GLOBALS['calendar_manager']->getEntry(Kronolith::ALL_REMOTE_CALENDARS, $this->calendar)->background()
: '#dddddd';
}
public function listAlarms($date, $fullevent = false)
{
return array();
}
/**
* Lists all events in the time range, optionally restricting results to
* only events with alarms.
*
* @param Horde_Date $startDate The start of range date.
* @param Horde_Date $endDate The end of date range.
* @param array $options Additional options:
* - show_recurrence: (boolean) Return every instance of a recurring
* event?
* DEFAULT: false (Only return recurring events once
* inside $startDate - $endDate range)
* - has_alarm: (boolean) Only return events with alarms.
* DEFAULT: false (Return all events)
* - json: (boolean) Store the results of the event's toJson()
* method?
* DEFAULT: false
* - cover_dates: (boolean) Add the events to all days that they
* cover?
* DEFAULT: true
* - hide_exceptions: (boolean) Hide events that represent exceptions to
* a recurring event.
* DEFAULT: false (Do not hide exception events)
* - fetch_tags: (boolean) Fetch tags for all events.
* DEFAULT: false (Do not fetch event tags)
*
* @throws Kronolith_Exception
*/
protected function _listEvents(Horde_Date $startDate = null,
Horde_Date $endDate = null,
array $options = array())
{
if ($this->isCalDAV()) {
return $this->_listCalDAVEvents(
$startDate, $endDate, $options['show_recurrence'],
$options['has_alarm'], $options['json'],
$options['cover_dates'], $options['hide_exceptions']);
}
return $this->_listWebDAVEvents(
$startDate, $endDate, $options['show_recurrence'],
$options['has_alarm'], $options['json'],
$options['cover_dates'], $options['hide_exceptions']);
}
/**
* Lists all events in the time range, optionally restricting results to
* only events with alarms.
*
* @param Horde_Date $startInterval Start of range date object.
* @param Horde_Date $endInterval End of range data object.
* @param boolean $showRecurrence Return every instance of a recurring
* event? If false, will only return
* recurring events once inside the
* $startDate - $endDate range.
* @param boolean $hasAlarm Only return events with alarms?
* @param boolean $json Store the results of the events'
* toJson() method?
* @param boolean $coverDates Whether to add the events to all days
* that they cover.
* $param boolean $hideExceptions Hide events that represent exceptions
* to a recurring event.
*
* @return array Events in the given time range.
* @throws Kronolith_Exception
*/
protected function _listWebDAVEvents(
$startDate = null, $endDate = null, $showRecurrence = false,
$hasAlarm = false, $json = false, $coverDates = true,
$hideExceptions = false
)
{
$ical = $this->getRemoteCalendar();
if (is_null($startDate)) {
$startDate = new Horde_Date(array('mday' => 1,
'month' => 1,
'year' => 0000));
}
if (is_null($endDate)) {
$endDate = new Horde_Date(array('mday' => 31,
'month' => 12,
'year' => 9999));
}
$startDate = clone $startDate;
$startDate->hour = $startDate->min = $startDate->sec = 0;
$endDate = clone $endDate;
$endDate->hour = 23;
$endDate->min = $endDate->sec = 59;
$results = array();
$this->_processComponents(
$results, $ical, $startDate, $endDate, $showRecurrence, $json,
$coverDates, $hideExceptions
);
return $results;
}
/**
* Lists all events in the time range, optionally restricting results to
* only events with alarms.
*
* @param Horde_Date $startInterval Start of range date object.
* @param Horde_Date $endInterval End of range data object.
* @param boolean $showRecurrence Return every instance of a recurring
* event? If false, will only return
* recurring events once inside the
* $startDate - $endDate range.
* @param boolean $hasAlarm Only return events with alarms?
* @param boolean $json Store the results of the events'
* toJson() method?
* @param boolean $coverDates Whether to add the events to all days
* that they cover.
* $param boolean $hideExceptions Hide events that represent exceptions
* to a recurring event.
*
* @return array Events in the given time range.
* @throws Kronolith_Exception
*/
protected function _listCalDAVEvents(
$startDate = null, $endDate = null, $showRecurrence = false,
$hasAlarm = false, $json = false, $coverDates = true,
$hideExceptions = false
)
{
if (!is_null($startDate)) {
$startDate = clone $startDate;
$startDate->hour = $startDate->min = $startDate->sec = 0;
}
if (!is_null($endDate)) {
$endDate = clone $endDate;
$endDate->hour = 23;
$endDate->min = $endDate->sec = 59;
}
/* Build report query. */
$xml = new XMLWriter();
$xml->openMemory();
$xml->setIndent(true);
$xml->startDocument();
$xml->startElementNS('C', 'calendar-query', 'urn:ietf:params:xml:ns:caldav');
$xml->writeAttribute('xmlns:D', 'DAV:');
$xml->startElement('D:prop');
$xml->writeElement('D:getetag');
$xml->startElement('C:calendar-data');
$xml->startElement('C:comp');
$xml->writeAttribute('name', 'VCALENDAR');
$xml->startElement('C:comp');
$xml->writeAttribute('name', 'VEVENT');
$xml->endElement();
$xml->endElement();
$xml->endElement();
$xml->endElement();
$xml->startElement('C:filter');
$xml->startElement('C:comp-filter');
$xml->writeAttribute('name', 'VCALENDAR');
$xml->startElement('C:comp-filter');
$xml->writeAttribute('name', 'VEVENT');
if (!is_null($startDate) ||
!is_null($endDate)) {
$xml->startElement('C:time-range');
if (!is_null($startDate)) {
$xml->writeAttribute('start', $startDate->toiCalendar());
}
if (!is_null($endDate)) {
$xml->writeAttribute('end', $endDate->toiCalendar());
}
}
$xml->endDocument();
$url = $this->_getUrl();
list($response, $events) = $this->_request('REPORT', $url, $xml,
array('Depth' => 1));
if (!$events->children('DAV:')->response) {
return array();
}
if (isset($response['headers']['content-location'])) {
$path = $response['headers']['content-location'];
} else {
$parsedUrl = parse_url($url);
$path = $parsedUrl['path'];
}
$results = array();
foreach ($events->children('DAV:')->response as $response) {
if (!$response->children('DAV:')->propstat) {
continue;
}
$ical = new Horde_Icalendar();
try {
$ical->parsevCalendar($response->children('DAV:')->propstat->prop->children('urn:ietf:params:xml:ns:caldav')->{'calendar-data'});
} catch (Horde_Icalendar_Exception $e) {
throw new Kronolith_Exception($e);
}
$this->_processComponents(
$results, $ical, $startDate, $endDate, $showRecurrence, $json,
$coverDates, $hideExceptions,
trim(str_replace($path, '', $response->href), '/')
);
}
return $results;
}
/**
* Processes the components of a Horde_Icalendar container into an event
* list.
*
* @param array $results Gets filled with the events in the
* given time range.
* @param Horde_Icalendar $ical An Horde_Icalendar container.
* @param Horde_Date $startInterval Start of range date.
* @param Horde_Date $endInterval End of range date.
* @param boolean $showRecurrence Return every instance of a recurring
* event? If false, will only return
* recurring events once inside the
* $startDate - $endDate range.
* @param boolean $json Store the results of the events'
* toJson() method?
* @param boolean $coverDates Whether to add the events to all days
* that they cover.
* $param boolean $hideExceptions Hide events that represent exceptions
* to a recurring event.
* @param string $id Enforce a certain event id (not UID).
*
* @throws Kronolith_Exception
*/
protected function _processComponents(
&$results, $ical, $startDate, $endDate, $showRecurrence, $json,
$coverDates, $hideExceptions, $id = null
)
{
$components = $ical->getComponents();
$events = array();
$count = count($components);
$exceptions = array();
for ($i = 0; $i < $count; $i++) {
$component = $components[$i];
if ($component->getType() == 'vEvent') {
try {
$event = new Kronolith_Event_Ical($this, $component);
} catch (Kronolith_Exception $e) {
Horde::log(
sprintf(
'Failed parse event from remote calendar: url = "%s"',
$this->calendar
),
'INFO'
);
continue;
}
$event->permission = $this->getPermission();
// Force string so JSON encoding is consistent across drivers.
$event->id = $id ? $id : 'ical' . $i;
/* Catch RECURRENCE-ID attributes which mark single recurrence
* instances. */
try {
$recurrence_id = $component->getAttribute('RECURRENCE-ID');
if (is_int($recurrence_id) &&
is_string($uid = $component->getAttribute('UID')) &&
is_int($seq = $component->getAttribute('SEQUENCE'))) {
$exceptions[$uid][$seq] = $recurrence_id;
if ($hideExceptions) {
continue;
}
$event->id .= '/' . $recurrence_id;
}
} catch (Horde_Icalendar_Exception $e) {}
/* Ignore events out of the period. */
$recurs = $event->recurs();
if (
/* Starts after the period. */
($endDate && $event->start->compareDateTime($endDate) > 0) ||
/* End before the period and doesn't recur. */
($startDate && !$recurs &&
$event->end->compareDateTime($startDate) < 0)) {
continue;
}
if ($recurs && $startDate) {
// Fixed end date? Check if end is before start period.
if ($event->recurrence->hasRecurEnd() &&
$event->recurrence->recurEnd->compareDateTime($startDate) < 0) {
continue;
} elseif ($endDate) {
$next = $event->recurrence->nextRecurrence($startDate);
if ($next == false || $next->compareDateTime($endDate) > 0) {
continue;
}
}
}
$events[] = $event;
}
}
/* Loop through all explicitly defined recurrence intances and create
* exceptions for those in the event with the matching recurrence. */
foreach ($events as $key => $event) {
if ($event->recurs() &&
isset($exceptions[$event->uid][$event->sequence])) {
$timestamp = $exceptions[$event->uid][$event->sequence];
$events[$key]->recurrence->addException(date('Y', $timestamp), date('m', $timestamp), date('d', $timestamp));
}
Kronolith::addEvents($results, $event, $startDate, $endDate,
$showRecurrence, $json, $coverDates);
}
}
/**
* @throws Kronolith_Exception
* @throws Horde_Exception_NotFound
*/
public function getEvent($eventId = null)
{
if (!$eventId) {
$event = new Kronolith_Event_Ical($this);
$event->permission = $this->getPermission();
return $event;
}
if ($this->isCalDAV()) {
if (preg_match('/(.*)-(\d+)$/', $eventId, $matches)) {
$eventId = $matches[1];
//$recurrenceId = $matches[2];
}
$url = trim($this->_getUrl(), '/') . '/' . $eventId;
try {
$response = $this->_getClient($url)->request('GET');
} catch (Horde_Dav_Exception $e) {
throw new Kronolith_Exception($e);
}
if ($response['statusCode'] == 200) {
$ical = new Horde_Icalendar();
try {
$ical->parsevCalendar($response['body']);
} catch (Horde_Icalendar_Exception $e) {
throw new Kronolith_Exception($e);
}
$results = array();
$this->_processComponents($results, $ical, null, null, false,
false, false, $eventId);
$event = reset(reset($results));
if (!$event) {
throw new Horde_Exception_NotFound(_("Event not found"));
}
return $event;
}
}
$eventId = str_replace('ical', '', $eventId);
$ical = $this->getRemoteCalendar();
$components = $ical->getComponents();
if (isset($components[$eventId]) &&
$components[$eventId]->getType() == 'vEvent') {
$event = new Kronolith_Event_Ical($this, $components[$eventId]);
$event->permission = $this->getPermission();
$event->id = 'ical' . $eventId;
return $event;
}
throw new Horde_Exception_NotFound(_("Event not found"));
}
/**
* Updates an existing event in the backend.
*
* @param Kronolith_Event $event The event to save.
*
* @return string The event id.
* @throws Horde_Mime_Exception
* @throws Kronolith_Exception
*/
protected function _updateEvent(Kronolith_Event $event)
{
$response = $this->_saveEvent($event);
if (!in_array($response['statusCode'], array(200, 204))) {
Horde::log(sprintf('Failed to update event on remote calendar: url = "%s", status = %s',
$response['url'], $response['statusCode']), 'INFO');
throw new Kronolith_Exception(_("The event could not be updated on the remote server."));
}
return $event->id;
}
/**
* Adds an event to the backend.
*
* @param Kronolith_Event $event The event to save.
*
* @return string The event id.
* @throws Horde_Mime_Exception
* @throws Kronolith_Exception
*/
protected function _addEvent(Kronolith_Event $event)
{
if (!$event->uid) {
$event->uid = (string)new Horde_Support_Uuid;
}
if (!$event->id) {
$event->id = $event->uid . '.ics';
}
$response = $this->_saveEvent($event);
if (!in_array($response['statusCode'], array(200, 201, 204))) {
Horde::log(sprintf('Failed to create event on remote calendar: status = %s',
$response['statusCode']), 'INFO');
throw new Kronolith_Exception(_("The event could not be added to the remote server."));
}
return $event->id;
}
/**
* Updates an existing event in the backend.
*
* @param Kronolith_Event $event The event to save.
*
* @return string The event id.
* @throws Horde_Mime_Exception
* @throws Kronolith_Exception
*/
protected function _saveEvent($event)
{
$ical = new Horde_Icalendar();
$ical->addComponent($event->toiCalendar($ical));
$url = trim($this->_getUrl(), '/') . '/' . $event->id;
try {
return $this->_getClient($url)
->request(
'PUT',
'',
$ical->exportvCalendar(),
array('Content-Type' => 'text/calendar')
);
} catch (Horde_Dav_Exception $e) {
Horde::log($e, 'INFO');
throw new Kronolith_Exception($e);
}
}
/**
* Deletes an event.
*
* @param string $eventId The ID of the event to delete.
* @param boolean $silent Don't send notifications, used when deleting
* events in bulk from maintenance tasks.
*
* @throws Kronolith_Exception
* @throws Horde_Exception_NotFound
* @throws Horde_Mime_Exception
*/
protected function _deleteEvent($eventId, $silent = false)
{
/* Fetch the event for later use. */
if ($eventId instanceof Kronolith_Event) {
$event = $eventId;
$eventId = $event->id;
} else {
$event = $this->getEvent($eventId);
}
if (!$this->isCalDAV()) {
throw new Kronolith_Exception(_("Deleting events is not supported with this remote calendar."));
}
if (preg_match('/(.*)-(\d+)$/', $eventId)) {
throw new Kronolith_Exception(_("Cannot delete exceptions (yet)."));
}
$url = trim($this->_getUrl(), '/') . '/' . $eventId;
try {
$response = $this->_getClient($url)->request('DELETE');
} catch (Horde_Dav_Exception $e) {
Horde::log($e, 'INFO');
throw new Kronolith_Exception($e);
}
if (!in_array($response['statusCode'], array(200, 202, 204))) {
Horde::log(sprintf('Failed to delete event from remote calendar: url = "%s", status = %s',
$url, $response['statusCode']), 'INFO');
throw new Kronolith_Exception(_("The event could not be deleted from the remote server."));
}
return $event;
}
/**
* Fetches a remote calendar into the cache and return the data.
*
* @param boolean $cache Whether to return data from the cache.
*
* @return Horde_Icalendar The calendar data.
* @throws Kronolith_Exception
*/
public function getRemoteCalendar($cache = true)
{
$url = $this->_getUrl();
$cacheOb = $GLOBALS['injector']->getInstance('Horde_Cache');
$cacheVersion = 2;
$signature = 'kronolith_remote_' . $cacheVersion . '_' . $url . '_' . serialize($this->_params);
if ($cache) {
$calendar = $cacheOb->get($signature, 3600);
if ($calendar) {
$calendar = unserialize($calendar);
if (!is_object($calendar)) {
throw new Kronolith_Exception($calendar);
}
return $calendar;
}
}
try {
$response = $this->_getClient($url)->request('GET');
if ($response['statusCode'] != 200) {
throw new Horde_Dav_Exception('Request Failed', $response['statusCode']);
}
} catch (Horde_Dav_Exception $e) {
Horde::log(
sprintf('Failed to retrieve remote calendar: url = "%s", status = %s',
$url, $e->getCode()),
'INFO'
);
$error = sprintf(
_("Could not open %s: %s"),
$url, $e->getMessage()
);
if ($cache) {
$cacheOb->set($signature, serialize($error));
}
throw new Kronolith_Exception($error, $e->getCode());
}
/* Log fetch at DEBUG level. */
Horde::log(
sprintf('Retrieved remote calendar for %s: url = "%s"',
$GLOBALS['registry']->getAuth(), $url),
'DEBUG'
);
$ical = new Horde_Icalendar();
try {
$ical->parsevCalendar($response['body']);
} catch (Horde_Icalendar_Exception $e) {
if ($cache) {
$cacheOb->set($signature, serialize($e->getMessage()));
}
throw new Kronolith_Exception($e);
}
if ($cache) {
$cacheOb->set($signature, serialize($ical));
}
return $ical;
}
/**
* Returns whether the remote calendar is a CalDAV server, and propagates
* the $_davSupport propery with the server's DAV capabilities.
*
* @return boolean True if the remote calendar is a CalDAV server.
* @throws Kronolith_Exception
*/
public function isCalDAV()
{
if (isset($this->_davSupport)) {
return $this->_davSupport
? in_array('calendar-access', $this->_davSupport)
: false;
}
$client = $this->_getClient($this->_getUrl());
try {
$this->_davSupport = $client->options();
} catch (Horde_Dav_Exception $e) {
if ($e->getCode() != 405) {
Horde::log($e, 'INFO');
}
$this->_davSupport = false;
return false;
}
if (!$this->_davSupport) {
$this->_davSupport = false;
return false;
}
if (!in_array('calendar-access', $this->_davSupport)) {
return false;
}
/* Check if this URL is a collection. */
try {
$properties = $client->propfind(
'',
array('{DAV:}resourcetype', '{DAV:}current-user-privilege-set')
);
} catch (\Sabre\DAV\Exception $e) {
Horde::log($e, 'INFO');
return false;
} catch (Horde_Dav_Exception $e) {
Horde::log($e, 'INFO');
return false;
}
if (!$properties['{DAV:}resourcetype']->is('{DAV:}collection')) {
throw new Kronolith_Exception(_("The remote server URL does not point to a CalDAV directory."));
}
/* Read ACLs. */
if (!empty($properties['{DAV:}current-user-privilege-set'])) {
$privileges = $properties['{DAV:}current-user-privilege-set'];
if ($privileges->has('{DAV:}read')) {
/* GET access. */
$this->_permission |= Horde_Perms::SHOW;
$this->_permission |= Horde_Perms::READ;
}
if ($privileges->has('{DAV:}write') ||
$privileges->has('{DAV:}write-content')) {
/* PUT access. */
$this->_permission |= Horde_Perms::EDIT;
}
if ($privileges->has('{DAV:}unbind')) {
/* DELETE access. */
$this->_permission |= Horde_Perms::DELETE;
}
}
return true;
}
/**
* Returns the permissions for the current calendar.
*
* @return integer A Horde_Perms permission bit mask.
*/
public function getPermission()
{
if ($this->isCalDAV()) {
return $this->_permission;
}
return Horde_Perms::SHOW | Horde_Perms::READ;
}
/**
* Sends a CalDAV request.
*
* @param string $method A request method.
* @param string $url A request URL.
* @param XMLWriter $xml An XMLWriter object with the body content.
* @param array $headers A hash with additional request headers.
*
* @return array The Horde_Http_Response object and the parsed
* SimpleXMLElement results.
* @throws Kronolith_Exception
*/
protected function _request($method, $url, XMLWriter $xml = null,
array $headers = array())
{
try {
$response = $this->_getClient($url)
->request($method,
'',
$xml ? $xml->outputMemory() : null,
array_merge(array('Cache-Control' => 'no-cache',
'Pragma' => 'no-cache',
'Content-Type' => 'application/xml'),
$headers));
} catch (Horde_Dav_Exception $e) {
Horde::log($e, 'INFO');
throw new Kronolith_Exception($e);
}
if ($response['statusCode'] != 207) {
throw new Kronolith_Exception(_("Unexpected response from remote server."));
}
libxml_use_internal_errors(true);
try {
$xml = new SimpleXMLElement($response['body']);
} catch (Exception $e) {
throw new Kronolith_Exception($e);
}
return array($response, $xml);
}
/**
* Returns the URL of this calendar.
*
* Does any necessary trimming and URL scheme fixes on the user-provided
* calendar URL.
*
* @return string The URL of this calendar.
*/
protected function _getUrl()
{
$url = trim($this->calendar);
if (strpos($url, 'http') !== 0) {
$url = str_replace(array('webcal://', 'webdav://', 'webdavs://'),
array('http://', 'http://', 'https://'),
$url);
}
return $url;
}
/**
* Returns a configured, cached DAV client.
*
* @param string $uri The base URI for any requests.
*
* @return Horde_Dav_Client A DAV client.
*/
protected function _getClient($uri)
{
$hordeOptions = array(
'request.timeout' => isset($this->_params['timeout'])
? $this->_params['timeout']
: 5
);
$sabreOptions = array('baseUri' => $uri);
if (!empty($this->_params['user'])) {
$hordeOptions['request.username'] = $sabreOptions['userName'] = $this->_params['user'];
$hordeOptions['request.password'] = $sabreOptions['password'] = $this->_params['password'];
}
$sabreOptions['client'] = $GLOBALS['injector']
->getInstance('Horde_Core_Factory_HttpClient')
->create($hordeOptions);
$this->_client = new Horde_Dav_Client($sabreOptions);
return $this->_client;
}
}
kronolith-4.2.13/lib/Driver/Kolab.php 0000664 0000765 0000024 00000040401 12654566222 014305 0 ustar
* @author Gunnar Wrobel
* @author Stuart Binge
* @package Kronolith
*/
class Kronolith_Driver_Kolab extends Kronolith_Driver
{
/**
* Our Kolab server connection.
*
* @var Kolab
*/
private $_kolab = null;
/**
* Internal cache of Kronolith_Event_Kolab. eventID is key
*
* @var array
*/
private $_events_cache;
/**
* Indicates if we have synchronized this folder
*
* @var boolean
*/
private $_synchronized;
/**
* The current calendar.
*
* @var Horde_Kolab_Storage_Data
*/
private $_data;
/**
* Attempts to open a Kolab Groupware folder.
*/
public function initialize()
{
if (empty($this->_params['storage'])) {
throw new InvalidArgumentException('Missing required Horde_Kolab_Storage instance');
}
$this->_kolab = $this->_params['storage'];
$this->reset();
}
/**
* Selects a calendar as the currently opened calendar.
*
* @param string $calendar A calendar identifier.
*/
public function open($calendar)
{
if ($this->calendar == $calendar) {
return;
}
$this->calendar = $calendar;
$this->reset();
}
/**
* Returns the background color of the current calendar.
*
* @return string The calendar color.
*/
public function backgroundColor()
{
if ($GLOBALS['calendar_manager']->getEntry(Kronolith::ALL_CALENDARS, $this->calendar) !== false) {
return $GLOBALS['calendar_manager']->getEntry(Kronolith::ALL_CALENDARS, $this->calendar)->background();
}
return '#dddddd';
}
/**
* Reset internal variable on share change
*/
public function reset()
{
$this->_events_cache = array();
$this->_synchronized = false;
}
// We delay initial synchronization to the first use
// so multiple calendars don't add to the total latency.
// This function must be called before all internal driver functions
public function synchronize($force = false)
{
if ($this->_synchronized && !$force) {
return;
}
// Connect to the Kolab backend
try {
$this->_data = $this->_kolab->getData(
$GLOBALS['calendar_manager']->getEntry(Kronolith::ALL_CALENDARS, $this->calendar)->share()->get('folder'),
'event'
);
} catch (Kolab_Storage_Exception $e) {
throw new Kronolith_Exception($e);
}
// build internal event cache
$this->_events_cache = $uids = array();
$events = $this->_data->getObjects();
foreach ($events as $event) {
$this->_events_cache[Horde_Url::uriB64Encode($event['uid'])] = new Kronolith_Event_Kolab($this, $event);
$uids[] = $event['uid'];
}
$tags = Kronolith::getTagger()->getTags(array_unique($uids));
foreach ($this->_events_cache as &$event) {
if (isset($tags[$event->uid])) {
$event->synchronizeTags($tags[$event->uid]);
}
}
$this->_synchronized = true;
}
/**
* @throws Kronolith_Exception
*/
public function listAlarms($date, $fullevent = false)
{
$allevents = $this->listEvents($date, null, array('has_alarm' => true));
$events = array();
foreach (array_keys($allevents) as $eventId) {
$event = $this->getEvent($eventId);
if (!$event->recurs()) {
$start = new Horde_Date($event->start);
$start->min -= $event->alarm;
if ($start->compareDateTime($date) <= 0 &&
$date->compareDateTime($event->end) <= -1) {
$events[] = $fullevent ? $event : $eventId;
}
} else {
if ($next = $event->recurrence->nextRecurrence($date)) {
if ($event->recurrence->hasException($next->year, $next->month, $next->mday)) {
continue;
}
$start = new Horde_Date($next);
$start->min -= $event->alarm;
$end = new Horde_Date(array('year' => $next->year,
'month' => $next->month,
'mday' => $next->mday,
'hour' => $event->end->hour,
'min' => $event->end->min,
'sec' => $event->end->sec));
if ($start->compareDateTime($date) <= 0 &&
$date->compareDateTime($end) <= -1) {
if ($fullevent) {
$event->start = $start;
$event->end = $end;
$events[] = $event;
} else {
$events[] = $eventId;
}
}
}
}
}
return is_array($events) ? $events : array();
}
/**
* Checks if the event's UID already exists and returns all event
* ids with that UID.
*
* @param string $uid The event's uid.
* @param string $calendar_id Calendar to search in.
*
* @return string|boolean Returns a string with event_id or false if
* not found.
* @throws Kronolith_Exception
*/
public function exists($uid, $calendar_id = null)
{
// Log error if someone uses this function in an unsupported way
if ($calendar_id != $this->calendar) {
throw new BadMethodCallException(sprintf('Kolab::exists called for calendar %s. Currently active is %s.', $calendar_id, $this->calendar));
}
$this->synchronize();
if ($this->_data->objectIdExists($uid)) {
return $uid;
}
return false;
}
/**
* Lists all events in the time range, optionally restricting results to
* only events with alarms.
*
* @param Horde_Date $startDate The start of range date.
* @param Horde_Date $endDate The end of date range.
* @param array $options Additional options:
* - show_recurrence: (boolean) Return every instance of a recurring
* event?
* DEFAULT: false (Only return recurring events once
* inside $startDate - $endDate range)
* - has_alarm: (boolean) Only return events with alarms.
* DEFAULT: false (Return all events)
* - json: (boolean) Store the results of the event's toJson()
* method?
* DEFAULT: false
* - cover_dates: (boolean) Add the events to all days that they
* cover?
* DEFAULT: true
* - hide_exceptions: (boolean) Hide events that represent exceptions to
* a recurring event.
* DEFAULT: false (Do not hide exception events)
* - fetch_tags: (boolean) Fetch tags for all events.
* DEFAULT: false (Do not fetch event tags)
*
* @throws Kronolith_Exception
*/
protected function _listEvents(Horde_Date $startDate = null,
Horde_Date $endDate = null,
array $options = array())
{
$this->synchronize();
if (empty($startDate)) {
$startDate = new Horde_Date(
array('mday' => 1, 'month' => 1, 'year' => 0000));
}
if (empty($endDate)) {
$endDate = new Horde_Date(
array('mday' => 31, 'month' => 12, 'year' => 9999));
}
if (!($startDate instanceOf Horde_Date)) {
$startDate = new Horde_Date($startDate);
}
if (!($endDate instanceOf Horde_Date)) {
$endDate = new Horde_Date($endDate);
}
$startDate = clone $startDate;
$startDate->hour = $startDate->min = $startDate->sec = 0;
$endDate = clone $endDate;
$endDate->hour = 23;
$endDate->min = $endDate->sec = 59;
$events = array();
foreach ($this->_events_cache as $event) {
if ($options['has_alarm'] && !$event->alarm) {
continue;
}
if ($options['hide_exceptions'] && !empty($event->baseid)) {
continue;
}
/* Ignore events out of the period. */
$recurs = $event->recurs();
if (
/* Starts after the period. */
$event->start->compareDateTime($endDate) > 0 ||
/* End before the period and doesn't recur. */
(!$recurs &&
$event->end->compareDateTime($startDate) < 0)) {
continue;
}
if ($recurs) {
// Fixed end date? Check if end is before start period.
if ($event->recurrence->hasRecurEnd() &&
$event->recurrence->recurEnd->compareDateTime($startDate) < 0) {
continue;
} else {
$next = $event->recurrence->nextRecurrence($startDate);
if ($next == false || $next->compareDateTime($endDate) > 0) {
continue;
}
}
}
Kronolith::addEvents(
$events, $event, $startDate, $endDate,
$options['show_recurrence'],
$options['json'],
$options['cover_dates']);
}
return $events;
}
/**
* @throws Kronolith_Exception
* @throws Horde_Exception_NotFound
*/
public function getEvent($eventId = null)
{
if (!strlen($eventId)) {
return new Kronolith_Event_Kolab($this);
}
$this->synchronize();
if (isset($this->_events_cache[$eventId])) {
return $this->_events_cache[$eventId];
}
throw new Horde_Exception_NotFound(sprintf(_("Event not found: %s"), $eventId));
}
/**
* Get an event or events with the given UID value.
*
* @param string $uid The UID to match
* @param array $calendars A restricted array of calendar ids to search
* @param boolean $getAll Return all matching events? If this is false,
* an error will be returned if more than one event is found.
*
* @return Kronolith_Event
* @throws Kronolith_Exception
* @throws Horde_Exception_NotFound
*/
public function getByUID($uid, $calendars = null, $getAll = false)
{
if (!is_array($calendars)) {
$calendars = array_keys(Kronolith::listInternalCalendars(false, Horde_Perms::READ));
}
$id = Horde_Url::uriB64Encode($uid);
foreach ($calendars as $calendar) {
$this->open($calendar);
$this->synchronize();
if (!isset($this->_events_cache[$id])) {
continue;
}
// Ok, found event
$event = $this->_events_cache[$id];
if ($getAll) {
return array($event);
}
return $event;
}
throw new Horde_Exception_NotFound(sprintf(_("Event not found: %s"), $uid));
}
/**
* Updates an existing event in the backend.
*
* @param Kronolith_Event $event The event to save.
*
* @return string The event id.
* @throws Horde_Mime_Exception
*/
protected function _updateEvent(Kronolith_Event $event)
{
return $this->_saveEvent($event, true);
}
/**
* Adds an event to the backend.
*
* @param Kronolith_Event $event The event to save.
*
* @return string The event id.
* @throws Horde_Mime_Exception
*/
protected function _addEvent(Kronolith_Event $event)
{
return $this->_saveEvent($event, false);
}
/**
* Saves an event in the backend.
*
* @param Kronolith_Event $event The event to save.
*
* @return string The event id.
* @throws Horde_Mime_Exception
*/
protected function _saveEvent($event, $edit)
{
$this->synchronize();
$action = $edit
? array('action' => 'modify')
: array('action' => 'add');
if (!$event->uid) {
$event->uid = $this->_data->generateUID();
$event->id = Horde_Url::uriB64Encode($event->uid);
}
$object = $event->toKolab();
if ($edit) {
$this->_data->modify($object);
} else {
$this->_data->create($object);
}
/* Deal with tags */
if ($edit) {
$this->_updateTags($event);
} else {
$this->_addTags($event);
}
/* Notify about the changed event. */
Kronolith::sendNotification($event, $edit ? 'edit' : 'add');
/* Log the creation/modification of this item in the history log. */
try {
$GLOBALS['injector']->getInstance('Horde_History')->log('kronolith:' . $event->calendar . ':' . $event->uid, $action, true);
} catch (Exception $e) {
Horde::log($e, 'ERR');
}
// refresh IMAP cache
$this->synchronize(true);
if (is_callable('Kolab', 'triggerFreeBusyUpdate')) {
//Kolab::triggerFreeBusyUpdate($this->_data->parseFolder($event->calendar));
}
return $event->id;
}
/**
* Moves an event to a new calendar.
*
* @param string $eventId The event to move.
* @param string $newCalendar The new calendar.
*
* @return Kronolith_Event The old event.
* @throws Kronolith_Exception
* @throws Horde_Exception_NotFound
*/
protected function _move($eventId, $newCalendar)
{
$event = $this->getEvent($eventId);
$this->synchronize();
$target = $GLOBALS['injector']
->getInstance('Kronolith_Shares')
->getShare($newCalendar)
->get('folder');
$this->_data->move($event->uid, $target);
unset($this->_events_cache[$eventId]);
try {
$this->_kolab->getData($target, 'event')->synchronize();
} catch (Kolab_Storage_Exception $e) {
throw new Kronolith_Exception($e);
}
if (is_callable('Kolab', 'triggerFreeBusyUpdate')) {
//Kolab::triggerFreeBusyUpdate($this->_data->parseFolder($this->calendar));
//Kolab::triggerFreeBusyUpdate($this->_data->parseFolder($newCalendar));
}
return $event;
}
/**
* Delete all of a calendar's events.
*
* @param string $calendar The name of the calendar to delete.
*
* @throws Kronolith_Exception
*/
public function delete($calendar)
{
$this->open($calendar);
$result = $this->synchronize();
$result = $this->_data->deleteAll($calendar);
if (is_callable('Kolab', 'triggerFreeBusyUpdate')) {
//Kolab::triggerFreeBusyUpdate($this->_data->parseFolder($calendar));
}
}
/**
* Deletes an event.
*
* @param string $eventId The ID of the event to delete.
*
* @throws Kronolith_Exception
* @throws Horde_Exception_NotFound
* @throws Horde_Mime_Exception
*/
protected function _deleteEvent($eventId, $silent = false)
{
if ($eventId instanceof Kronolith_Event) {
$event = $eventId;
$this->synchronize();
} else {
$event = $this->getEvent($eventId);
}
$this->_data->delete($event->uid);
unset($this->_events_cache[$event->id]);
/* Notify about the deleted event. */
if (!$silent) {
$this->_handleNotifications($event, 'delete');
}
return $event;
}
}
kronolith-4.2.13/lib/Driver/Mock.php 0000664 0000765 0000024 00000004547 12654566222 014161 0 ustar
* @package Kronolith
*/
class Kronolith_Driver_Mock extends Kronolith_Driver
{
/**
* List all alarms.
*
* @param Horde_Date $date The date to list alarms for
* @param boolean $fullevent Return the full event objects?
*
* @return array An array of event ids, or Kronolith_Event objects
* @throws Kronolith_Exception
*/
public function listAlarms($date, $fullevent = false)
{
return array();
}
/**
* Lists all events in the time range, optionally restricting results to
* only events with alarms.
*
* @param Horde_Date $startDate The start of range date.
* @param Horde_Date $endDate The end of date range.
* @param array $options Additional options:
* - show_recurrence: (boolean) Return every instance of a recurring
* event?
* DEFAULT: false (Only return recurring events once
* inside $startDate - $endDate range)
* - has_alarm: (boolean) Only return events with alarms.
* DEFAULT: false (Return all events)
* - json: (boolean) Store the results of the event's toJson()
* method?
* DEFAULT: false
* - cover_dates: (boolean) Add the events to all days that they
* cover?
* DEFAULT: true
* - hide_exceptions: (boolean) Hide events that represent exceptions to
* a recurring event.
* DEFAULT: false (Do not hide exception events)
* - fetch_tags: (boolean) Fetch tags for all events.
* DEFAULT: false (Do not fetch event tags)
*
* @throws Kronolith_Exception
*/
protected function _listEvents(Horde_Date $startDate = null,
Horde_Date $endDate = null,
array $options = array())
{
return array();
}
}
kronolith-4.2.13/lib/Driver/Sql.php 0000664 0000765 0000024 00000100401 12654566222 014011 0 ustar
* @author Chuck Hagenbuch
* @author Jan Schneider
* @package Kronolith
*/
class Kronolith_Driver_Sql extends Kronolith_Driver
{
/**
* The object handle for the current database connection.
*
* @var Horde_Db_Adapter
*/
protected $_db;
/**
* Column information as Horde_Db_Adapter_Base_Column objects.
*
* @var array
*/
protected $_columns = array();
/**
* Cache events as we fetch them to avoid fetching the same event from the
* DB twice.
*
* @var array
*/
protected $_cache = array();
/**
* The class name of the event object to instantiate.
*
* Can be overwritten by sub-classes.
*
* @var string
*/
protected $_eventClass = 'Kronolith_Event_Sql';
/**
* Returns the background color of the current calendar.
*
* @return string The calendar color.
*/
public function backgroundColor()
{
if ($GLOBALS['calendar_manager']->getEntry(Kronolith::ALL_CALENDARS, $this->calendar) !== false) {
return $GLOBALS['calendar_manager']->getEntry(Kronolith::ALL_CALENDARS, $this->calendar)->background();
}
return '#dddddd';
}
/**
* Returns whether this driver supports per-event timezones.
*
* @return boolean Whether this drivers suppports per-event timezones.
*/
public function supportsTimezones()
{
return $this->getParam('utc');
}
/**
*
* @param Horde_Date $date The date to list alarms for
* @param boolean $fullevent Return the full event objects?
*
* @return array An array of event ids, or Kronolith_Event objects
* @throws Kronolith_Exception
*/
public function listAlarms($date, $fullevent = false)
{
$allevents = $this->listEvents($date, null, array('has_alarm' => true));
$events = array();
foreach ($allevents as $dayevents) {
foreach ($dayevents as $event) {
if (!$event->recurs()) {
$start = new Horde_Date($event->start);
$start->min -= $event->alarm;
if ($start->compareDateTime($date) <= 0 &&
$date->compareDateTime($event->end) <= -1) {
$events[] = $fullevent ? $event : $event->id;
}
} else {
// Need to start at the beginning of the day to catch the
// case where we might be within the event's timespan
// when we call this, hence nextRecurrence() would miss the
// current event.
$start = clone $date;
$start->min = 0;
$start->hour = 0;
$start->sec = 0;
if ($next = $event->recurrence->nextRecurrence($start)) {
if ($event->recurrence->hasException($next->year, $next->month, $next->mday)) {
continue;
}
$start = new Horde_Date($next);
$start->min -= $event->alarm;
$diff = Date_Calc::dateDiff(
$event->start->mday,
$event->start->month,
$event->start->year,
$event->end->mday,
$event->end->month,
$event->end->year
);
if ($diff == -1) {
$diff = 0;
}
$end = new Horde_Date(array(
'year' => $next->year,
'month' => $next->month,
'mday' => $next->mday + $diff,
'hour' => $event->end->hour,
'min' => $event->end->min,
'sec' => $event->end->sec)
);
if ($start->compareDateTime($date) <= 0 &&
$date->compareDateTime($end) <= -1) {
if ($fullevent) {
$event->start = $next;
$event->end = $end;
$events[] = $event;
} else {
$events[] = $event->id;
}
}
}
}
}
}
return $events;
}
/**
* Searches a calendar.
*
* @param object $query An object with the criteria to search for.
* @param boolean $json Store the results of the events' toJson() method?
*
* @return mixed An array of Kronolith_Events.
* @throws Kronolith_Exception
*/
public function search($query, $json = false)
{
/* Build SQL conditions based on the query string. */
$cond = '((';
$values = array();
foreach (array('title', 'location', 'url', 'description') as $field) {
if (!empty($query->$field)) {
$binds = $this->_db->buildClause('event_' . $field, 'LIKE', $this->convertToDriver($query->$field), true);
if (is_array($binds)) {
$cond .= $binds[0] . ' AND ';
$values = array_merge($values, $binds[1]);
} else {
$cond .= $binds;
}
}
}
if (!empty($query->baseid)) {
$binds = $this->_db->buildClause('event_baseid', '=', $query->baseid, true);
if (is_array($binds)) {
$cond .= $binds[0] . ' AND ';
$values = array_merge($values, $binds[1]);
} else {
$cond .= $binds;
}
}
if (isset($query->status)) {
$binds = $this->_db->buildClause('event_status', '=', $query->status, true);
if (is_array($binds)) {
$cond .= $binds[0] . ' AND ';
$values = array_merge($values, $binds[1]);
} else {
$cond .= $binds;
}
}
if (!empty($query->creator)) {
$binds = $this->_db->buildClause('event_creator_id', '=', $query->creator, true);
if (is_array($binds)) {
$cond .= $binds[0] . ' AND ';
$values = array_merge($values, $binds[1]);
} else {
$cond .= $binds;
}
}
if ($cond == '((') {
$cond = '';
} else {
$cond = substr($cond, 0, strlen($cond) - 5) . '))';
}
$eventIds = $this->_listEventsConditional(empty($query->start) ? null : $query->start,
empty($query->end) ? null : $query->end,
$cond,
$values);
$events = array();
foreach ($eventIds as $eventId) {
Kronolith::addSearchEvents($events, $this->getEvent($eventId), $query, $json);
}
return $events;
}
/**
* Checks if the event's UID already exists and returns all event
* ids with that UID.
*
* @param string $uid The event's uid.
* @param string $calendar_id Calendar to search in.
*
* @return string|boolean Returns a string with event_id or false if
* not found.
* @throws Kronolith_Exception
*/
public function exists($uid, $calendar_id = null)
{
$query = 'SELECT event_id FROM ' . $this->_params['table'] . ' WHERE event_uid = ?';
$values = array($uid);
if (!is_null($calendar_id)) {
$query .= ' AND calendar_id = ?';
$values[] = $calendar_id;
}
try {
$event = $this->_db->selectValue($query, $values);
} catch (Horde_Db_Exception $e) {
throw new Kronolith_Exception($e);
}
return !empty($event) ? $event : false;
}
/**
* Lists all events in the time range, optionally restricting results to
* only events with alarms.
*
* @param Horde_Date $startDate The start of range date.
* @param Horde_Date $endDate The end of date range.
* @param array $options Additional options:
* - show_recurrence: (boolean) Return every instance of a recurring
* event?
* DEFAULT: false (Only return recurring events once
* inside $startDate - $endDate range)
* - has_alarm: (boolean) Only return events with alarms.
* DEFAULT: false (Return all events)
* - json: (boolean) Store the results of the event's toJson()
* method?
* DEFAULT: false
* - cover_dates: (boolean) Add the events to all days that they
* cover?
* DEFAULT: true
* - hide_exceptions: (boolean) Hide events that represent exceptions to
* a recurring event.
* DEFAULT: false (Do not hide exception events)
* - fetch_tags: (boolean) Fetch tags for all events.
* DEFAULT: false (Do not fetch event tags)
*
* @throws Kronolith_Exception
*/
protected function _listEvents(Horde_Date $startDate = null,
Horde_Date $endDate = null,
array $options = array())
{
if (!is_null($startDate)) {
$startDate = clone $startDate;
$startDate->hour = $startDate->min = $startDate->sec = 0;
}
if (!is_null($endDate)) {
$endDate = clone $endDate;
$endDate->hour = 23;
$endDate->min = $endDate->sec = 59;
}
$conditions = $options['has_alarm'] ? 'event_alarm > ?' : '';
$values = $options['has_alarm'] ? array(0) : array();
if ($options['hide_exceptions']) {
if (!empty($conditions)) {
$conditions .= ' AND ';
}
$conditions .= "event_baseid = ''";
}
$events = $this->_listEventsConditional($startDate, $endDate, $conditions, $values);
$results = array();
$tags = null;
if ($options['fetch_tags'] && count($events)) {
$tags = Kronolith::getTagger()->getTags(array_keys($events));
}
foreach ($events as $id) {
$event = $this->getEvent($id);
if (isset($tags) && !empty($tags[$event->uid])) {
$event->tags = $tags[$event->uid];
}
Kronolith::addEvents(
$results, $event, $startDate, $endDate, $options['show_recurrence'],
$options['json'], $options['cover_dates']);
}
return $results;
}
/**
* Lists all events that satisfy the given conditions.
*
* @param Horde_Date $startInterval Start of range date object.
* @param Horde_Date $endInterval End of range data object.
* @param string $conditions Conditions, given as SQL clauses.
* @param array $vals SQL bind variables for use with
* $conditions clauses.
*
* @return array Events in the given time range satisfying the given
* conditions.
* @throws Kronolith_Exception
*/
private function _listEventsConditional(Horde_Date $startInterval = null,
Horde_Date $endInterval = null,
$conditions = '', array $vals = array())
{
if ($this->getParam('utc')) {
if (!is_null($startInterval)) {
$startInterval = clone $startInterval;
$startInterval->setTimezone('UTC');
}
if (!is_null($endInterval)) {
$endInterval = clone $endInterval;
$endInterval->setTimezone('UTC');
}
}
$q = 'SELECT event_id, event_uid, event_description, event_location,' .
' event_private, event_status, event_attendees,' .
' event_title, event_recurcount, event_url, event_timezone,' .
' event_recurtype, event_recurenddate, event_recurinterval,' .
' event_recurdays, event_start, event_end, event_allday,' .
' event_alarm, event_alarm_methods, event_modified,' .
' event_exceptions, event_creator_id, event_resources, event_baseid,' .
' event_exceptionoriginaldate FROM ' . $this->_params['table'] .
' WHERE calendar_id = ?';
$values = array($this->calendar);
if ($conditions) {
$q .= ' AND ' . $conditions;
$values = array_merge($values, $vals);
}
if (!is_null($startInterval) && !is_null($endInterval)) {
$etime = $endInterval->format('Y-m-d H:i:s');
$stime = $startInterval->format('Y-m-d H:i:s');
$q .= ' AND ((event_end >= ? AND event_start <= ?) OR (event_recurenddate >= ? AND event_start <= ? AND event_recurtype <> ?))';
array_push($values, $stime, $etime, $stime, $etime, Horde_Date_Recurrence::RECUR_NONE);
} elseif (!is_null($startInterval)) {
$stime = $startInterval->format('Y-m-d H:i:s');
$q .= ' AND ((event_end >= ?) OR (event_recurenddate >= ? AND event_recurtype <> ?))';
array_push($values, $stime, $stime, Horde_Date_Recurrence::RECUR_NONE);
} elseif (!is_null($endInterval)) {
$q .= ' AND (event_start <= ?)';
$values[] = $endInterval->format('Y-m-d H:i:s');
}
/* Run the query. */
try {
$qr = $this->_db->selectAll($q, $values);
} catch (Horde_Db_Exception $e) {
throw new Kronolith_Exception($e);
}
$events = array();
foreach ($qr as $row) {
/* If the event did not have a UID before, we need to give it
* one. */
if (empty($row['event_uid'])) {
$row['event_uid'] = (string)new Horde_Support_Guid;
/* Save the new UID for data integrity. */
$query = 'UPDATE ' . $this->_params['table'] . ' SET event_uid = ? WHERE event_id = ?';
$values = array($row['event_uid'], $row['event_id']);
try {
$this->_db->update($query, $values);
} catch (Horde_Db_Exception $e) {
throw new Kronolith_Exception($e);
}
}
/* Convert TEXT/CLOB fields. */
$row = $this->convertBlobs($row);
/* We have all the information we need to create an event object
* for this event, so go ahead and cache it. */
$this->_cache[$this->calendar][$row['event_id']] = new $this->_eventClass($this, $row);
if ($row['event_recurtype'] == Horde_Date_Recurrence::RECUR_NONE) {
$events[$row['event_uid']] = $row['event_id'];
} else {
$next = $this->nextRecurrence($row['event_id'], $startInterval);
if ($next &&
(is_null($endInterval) ||
$next->compareDateTime($endInterval) < 0)) {
$events[$row['event_uid']] = $row['event_id'];
}
}
}
return $events;
}
/**
* Returns the number of events in the current calendar.
*
* @return integer The number of events.
* @throws Kronolith_Exception
*/
public function countEvents()
{
$query = sprintf('SELECT count(*) FROM %s WHERE calendar_id = ?',
$this->_params['table']);
/* Run the query. */
try {
$result = $this->_db->selectValue($query, array($this->calendar));
} catch (Horde_Db_Exception $e) {
throw new Kronolith_Exception($e);
}
return $result;
}
/**
* @throws Kronolith_Exception
* @throws Horde_Exception_NotFound
*/
public function getEvent($eventId = null)
{
if (!strlen($eventId)) {
return new $this->_eventClass($this);
}
if (isset($this->_cache[$this->calendar][$eventId])) {
return $this->_cache[$this->calendar][$eventId];
}
$query = 'SELECT event_id, event_uid, event_description,' .
' event_location, event_private, event_status, event_attendees,' .
' event_title, event_recurcount, event_url, event_timezone,' .
' event_recurtype, event_recurenddate, event_recurinterval,' .
' event_recurdays, event_start, event_end, event_allday,' .
' event_alarm, event_alarm_methods, event_modified,' .
' event_exceptions, event_creator_id, event_resources,' .
' event_baseid, event_exceptionoriginaldate FROM ' .
$this->_params['table'] . ' WHERE event_id = ? AND calendar_id = ?';
$values = array($eventId, $this->calendar);
try {
$event = $this->_db->selectOne($query, $values);
} catch (Horde_Db_Exception $e) {
throw new Kronolith_Exception($e);
}
if ($event) {
/* Convert TEXT/CLOB fields. */
$event = $this->convertBlobs($event);
$this->_cache[$this->calendar][$eventId] = new $this->_eventClass($this, $event);
return $this->_cache[$this->calendar][$eventId];
}
throw new Horde_Exception_NotFound(_("Event not found"));
}
/**
* Get an event or events with the given UID value.
*
* @param string $uid The UID to match
* @param array $calendars A restricted array of calendar ids to search
* @param boolean $getAll Return all matching events?
*
* @return Kronolith_Event
* @throws Kronolith_Exception
* @throws Horde_Exception_NotFound
*/
public function getByUID($uid, $calendars = null, $getAll = false)
{
$query = 'SELECT event_id, event_uid, calendar_id, event_description,' .
' event_location, event_private, event_status, event_attendees,' .
' event_title, event_recurcount, event_url, event_timezone,' .
' event_recurtype, event_recurenddate, event_recurinterval,' .
' event_recurdays, event_start, event_end, event_allday,' .
' event_alarm, event_alarm_methods, event_modified,' .
' event_exceptions, event_creator_id, event_resources, event_baseid,' .
' event_exceptionoriginaldate FROM ' . $this->_params['table'] .
' WHERE event_uid = ?';
$values = array((string)$uid);
/* Optionally filter by calendar */
if (!empty($calendars)) {
if (!count($calendars)) {
throw new Kronolith_Exception(_("No calendars to search"));
}
$query .= ' AND calendar_id IN (?' . str_repeat(', ?', count($calendars) - 1) . ')';
$values = array_merge($values, $calendars);
}
try {
$events = $this->_db->selectAll($query, $values);
} catch (Horde_Db_Exception $e) {
throw new Kronolith_Exception($e);
}
if (!count($events)) {
throw new Horde_Exception_NotFound(sprintf(_("%s not found"), $uid));
}
$eventArray = array();
foreach ($events as $event) {
/* Convert TEXT/CLOB fields. */
$event = $this->convertBlobs($event);
$this->open($event['calendar_id']);
$this->_cache[$this->calendar][$event['event_id']] = new $this->_eventClass($this, $event);
$eventArray[] = $this->_cache[$this->calendar][$event['event_id']];
}
if ($getAll) {
return $eventArray;
}
/* First try the user's own calendars. */
$ownerCalendars = Kronolith::listInternalCalendars(true, Horde_Perms::READ);
$event = null;
foreach ($eventArray as $ev) {
if (isset($ownerCalendars[$ev->calendar])) {
$event = $ev;
break;
}
}
/* If not successful, try all calendars the user has access too. */
if (empty($event)) {
$readableCalendars = Kronolith::listInternalCalendars(false, Horde_Perms::READ);
foreach ($eventArray as $ev) {
if (isset($readableCalendars[$ev->calendar])) {
$event = $ev;
break;
}
}
}
if (empty($event)) {
$event = $eventArray[0];
}
return $event;
}
/**
* Builds a history hash for a modified event.
*
* We don't write it in here because we don't want to commit history before
* the actual changes are made.
*
* @param Kronolith_Event $event The event to log.
*
* @return array The change log.
* @throws Horde_Mime_Exception
* @throws Kronolith_Exception
*/
protected function _buildEventHistory(Kronolith_Event $event)
{
$changes = array('action' => 'modify');
/* We cannot use getEvent() because of caching. */
$oldProperties = $this->getbyUID(
$event->uid,
array($event->calendar))->toProperties();
$newProperties = $event->toProperties();
if (empty($oldProperties)) {
return $changes;
}
foreach (array_keys($newProperties) as $property) {
if (!isset($oldProperties[$property]) ||
($oldProperties[$property] != $newProperties[$property])) {
$changes['new'][$property] = $newProperties[$property];
$changes['old'][$property] = !isset($oldProperties[$property]) ? $oldProperties[$property] : null;
}
}
return $changes;
}
/**
* Updates an existing event in the backend.
*
* @param Kronolith_Event $event The event to save.
*
* @return string The event id.
* @throws Horde_Mime_Exception
* @throws Kronolith_Exception
*/
protected function _updateEvent(Kronolith_Event $event)
{
$values = array();
$query = 'UPDATE ' . $this->_params['table'] . ' SET ';
foreach ($event->toProperties() as $key => $val) {
$query .= " $key = ?,";
$values[] = $val;
}
$query = substr($query, 0, -1);
$query .= ' WHERE event_id = ?';
$values[] = $event->id;
$history = $this->_buildEventHistory($event);
try {
$this->_db->update($query, $values);
} catch (Horde_Db_Exception $e) {
throw new Kronolith_Exception($e);
}
/* Log the modification of this item in the history log. */
if ($event->uid) {
try {
$GLOBALS['injector']->getInstance('Horde_History')->log('kronolith:' . $this->calendar . ':' . $event->uid, $history, true);
} catch (Exception $e) {
Horde::log($e, 'ERR');
}
}
/* If this event is an exception, we need to modify the base event's
* history log also, or some sync clients will never pick up the
* change. */
if ($event->baseid) {
try {
$GLOBALS['injector']->getInstance('Horde_History')->log('kronolith:' . $this->calendar . ':' . $event->baseid, $history, true);
} catch (Exception $e) {
Horde::log($e, 'ERR');
}
}
$this->_updateTags($event);
/* Update Geolocation */
try {
$GLOBALS['injector']->getInstance('Kronolith_Geo')->setLocation($event->id, $event->geoLocation);
} catch (Kronolith_Exception $e) {
}
/* Notify users about the changed event. */
$this->_handleNotifications($event, 'edit');
return $event->id;
}
/**
* Adds an event to the backend.
*
* @param Kronolith_Event $event The event to save.
*
* @return string The event id.
* @throws Horde_Mime_Exception
* @throws Kronolith_Exception
*/
protected function _addEvent(Kronolith_Event $event)
{
if (!$event->id) {
$event->id = (string)new Horde_Support_Randomid;
}
if (!$event->uid) {
$event->uid = (string)new Horde_Support_Guid;
}
$query = 'INSERT INTO ' . $this->_params['table'];
$cols_name = ' (event_id, event_uid,';
$cols_values = ' VALUES (?, ?,';
$values = array($event->id, $event->uid);
foreach ($event->toProperties() as $key => $val) {
$cols_name .= " $key,";
$cols_values .= ' ?,';
$values[] = $val;
}
$cols_name .= ' calendar_id)';
$cols_values .= ' ?)';
$values[] = $this->calendar;
$query .= $cols_name . $cols_values;
try {
$this->_db->insert($query, $values);
} catch (Horde_Db_Exception $e) {
throw new Kronolith_Exception($e);
}
/* Log the creation of this item in the history log. */
try {
$GLOBALS['injector']->getInstance('Horde_History')->log('kronolith:' . $this->calendar . ':' . $event->uid, array('action' => 'add'), true);
} catch (Exception $e) {
Horde::log($e, 'ERR');
}
$this->_addTags($event);
/* Update Geolocation */
if ($event->geoLocation) {
try {
$GLOBALS['injector']->getInstance('Kronolith_Geo')->setLocation($event->id, $event->geoLocation);
} catch (Kronolith_Exception $e) {
}
}
/* Notify users about the new event. */
$this->_handleNotifications($event, 'add');
return $event->id;
}
/**
* Moves an event to a new calendar.
*
* @param string $eventId The event to move.
* @param string $newCalendar The new calendar.
*
* @return Kronolith_Event The old event.
* @throws Kronolith_Exception
* @throws Horde_Exception_NotFound
*/
protected function _move($eventId, $newCalendar)
{
/* Fetch the event for later use. */
$event = $this->getEvent($eventId);
$query = 'UPDATE ' . $this->_params['table'] . ' SET calendar_id = ? WHERE calendar_id = ? AND event_id = ?';
$values = array($newCalendar, $this->calendar, $eventId);
/* Attempt the move query. */
try {
$this->_db->update($query, $values);
} catch (Horde_Db_Exception $e) {
throw new Kronolith_Exception($e);
}
return $event;
}
/**
* Delete all of a calendar's events.
*
* @param string $calendar The name of the calendar to delete.
*
* @throws Kronolith_Exception
*/
public function delete($calendar)
{
$oldCalendar = $this->calendar;
$this->open($calendar);
$events = $this->listEvents(null, null, array('cover_dates' => false, 'hide_exceptions' => true));
$uids = array();
foreach ($events as $dayevents) {
foreach ($dayevents as $event) {
$uids[] = $event->uid;
}
}
foreach ($uids as $uid) {
$event = $this->getByUID($uid, array($calendar));
$this->deleteEvent($event->id);
}
$this->open($oldCalendar);
}
/**
* Deletes an event.
*
* @param string $eventId The ID of the event to delete.
* @param boolean $silent Don't send notifications, used when deleting
* events in bulk from maintenance tasks.
*
* @throws Kronolith_Exception
* @throws Horde_Exception_NotFound
* @throws Horde_Mime_Exception
*/
protected function _deleteEvent($eventId, $silent = false)
{
/* Fetch the event for later use. */
if ($eventId instanceof Kronolith_Event) {
$event = $eventId;
$eventId = $event->id;
} else {
$event = $this->getEvent($eventId);
}
$original_uid = $event->uid;
$isRecurring = $event->recurs();
$query = 'DELETE FROM ' . $this->_params['table'] . ' WHERE event_id = ? AND calendar_id = ?';
try {
$this->_db->delete($query, array($eventId, $this->calendar));
} catch (Horde_Db_Exception $e) {
throw new Kronolith_Exception($e);
}
/* Notify about the deleted event. */
if (!$silent) {
$this->_handleNotifications($event, 'delete');
}
/* Now check for any exceptions that THIS event may have */
if ($isRecurring) {
$query = 'SELECT event_id FROM ' . $this->_params['table'] . ' WHERE event_baseid = ? AND calendar_id = ?';
$values = array($original_uid, $this->calendar);
try {
$result = $this->_db->selectValues($query, $values);
} catch (Horde_Db_Exception $e) {
throw new Kronolith_Exception($e);
}
foreach ($result as $id) {
$this->deleteEvent($id, true);
}
}
return $event;
}
/**
* Filters a list of events to return only those that belong to certain
* calendars.
*
* @param array $uids A list of event UIDs.
* @param array $calendar A list of calendar IDs.
*
* @return array Event UIDs filtered by calendar IDs.
* @throws Kronolith_Exception
*/
public function filterEventsByCalendar($uids, $calendar)
{
$sql = 'SELECT event_uid FROM kronolith_events WHERE calendar_id IN (' . str_repeat('?, ', count($calendar) - 1) . '?) '
. 'AND event_uid IN (' . str_repeat('?,', count($uids) - 1) . '?)';
try {
$result = $this->_db->selectValues($sql, array_merge($calendar, $uids));
} catch (Horde_Db_Exception $e) {
throw new Kronolith_Exception($e);
}
return $result;
}
/**
* Attempts to open a connection to the SQL server.
*
* @throws Kronolith_Exception
*/
public function initialize()
{
if (empty($this->_params['db'])) {
throw new InvalidArgumentException('Missing required Horde_Db_Adapter instance');
}
try {
$this->_db = $this->_params['db'];
} catch (Horde_Exception $e) {
throw new Kronolith_Exception($e);
}
$this->_params = array_merge(array(
'table' => 'kronolith_events'
), $this->_params);
$this->_columns = $this->_db->columns($this->_params['table']);
}
/**
* Converts a value from the driver's charset to the default
* charset.
*
* @param mixed $value A value to convert.
*
* @return mixed The converted value.
*/
public function convertFromDriver($value)
{
return Horde_String::convertCharset($value, $this->_params['charset'], 'UTF-8');
}
/**
* Converts a value from the default charset to the driver's
* charset.
*
* @param mixed $value A value to convert.
*
* @return mixed The converted value.
*/
public function convertToDriver($value)
{
return Horde_String::convertCharset($value, 'UTF-8', $this->_params['charset']);
}
/**
* Converts TEXT/CLOB fields in an event.
*
* @param array $event An event hash with TEXT/CLOB columns.
*
* @return array The event with TEXT/CLOB columns converted to strings.
*/
public function convertBlobs($event)
{
$clobs = array(
'alarm_methods', 'attendees', 'description', 'exceptions',
'location', 'resources'
);
foreach ($clobs as $clob) {
$event['event_' . $clob] = $this->_columns['event_' . $clob]
->binaryToString($event['event_' . $clob]);
}
return $event;
}
}
kronolith-4.2.13/lib/Event/Resource/Sql.php 0000664 0000765 0000024 00000005765 12654566222 015447 0 ustar
* @author Chuck Hagenbuch
* @author Jan Schneider
* @author Michael J. Rubinsky
*
* @package Kronolith
*/
class Kronolith_Event_Resource_Sql extends Kronolith_Event_Sql
{
/**
* The type of the calender this event exists on.
*
* @var string
*/
public $calendarType = 'resource';
/**
* Returns a reference to a driver that's valid for this event.
*
* @return Kronolith_Driver A driver that this event can use to save
* itself, etc.
*/
public function getDriver()
{
return Kronolith::getDriver('Resource', $this->calendar);
}
/**
* Encapsulates permissions checking. For now, admins, and ONLY admins have
* any permissions to a resource's events.
*
* @param integer $permission The permission to check for.
* @param string $user The user to check permissions for.
*
* @return boolean
*/
public function hasPermission($permission, $user = null)
{
return $GLOBALS['registry']->isAdmin();
}
/**
* Saves changes to this event.
*
* @return integer The event id.
* @throws Kronolith_Exception
*/
public function save()
{
if (!$this->initialized) {
throw new Kronolith_Exception('Event not yet initialized');
}
/* Save */
return $this->getDriver()->saveEvent($this);
}
/**
* Returns the title of this event, considering private flags.
*
* @param string $user The current user.
*
* @return string The title of this event.
*/
public function getTitle($user = null)
{
if (!$this->initialized) {
return '';
}
$reservee = sprintf(_("Reserved by: %s"), $this->getResourceReservee());
$perms = $GLOBALS['injector']->getInstance('Horde_Core_Perms');
return $this->isPrivate($user)
? ($perms->hasAppPermission('resource_management') ? $reservee : _("busy"))
: (strlen($this->title) ? sprintf('%s %s', $this->title, $reservee) : sprintf(_("[Unnamed event] %s"), $reservee));
}
/**
* Return the name/email address or username of the reservee for this event.
*
* @return string The email or username.
*/
public function getResourceReservee()
{
$identity = $GLOBALS['injector']
->getInstance('Horde_Core_Factory_Identity')
->create($this->creator);
$fullname = $identity->getDefaultFromAddress(true);
if (empty($fullname)) {
$fullname = $this->creator;
} else {
$fullname = $fullname->writeAddress();
}
return $fullname;
}
}
kronolith-4.2.13/lib/Event/Holidays.php 0000664 0000765 0000024 00000004354 12654566222 014666 0 ustar
* @package Kronolith
*/
class Kronolith_Event_Holidays extends Kronolith_Event
{
/**
* The type of the calender this event exists on.
*
* @var string
*/
public $calendarType = 'holiday';
/**
* The status of this event.
*
* @var integer
*/
public $status = Kronolith::STATUS_FREE;
/**
* Whether this is an all-day event.
*
* @var boolean
*/
public $allday = true;
/**
* Parse in an event from the driver.
*
* @param Date_Holidays_Holiday $dhEvent A holiday returned
* from the driver
*/
public function fromDriver($dhEvent)
{
$this->stored = true;
$this->initialized = true;
$this->title = $dhEvent->getTitle();
$this->start = new Horde_Date($dhEvent->getDate()->getDate());
$this->end = new Horde_Date($this->start);
$this->end->mday++;
$this->id = $dhEvent->getInternalName() . '-' . $this->start->dateString();
}
/**
* Encapsulates permissions checking.
*
* @param integer $permission The permission to check for.
* @param string $user The user to check permissions for.
*
* @return boolean
*/
public function hasPermission($permission, $user = null)
{
switch ($permission) {
case Horde_Perms::SHOW:
case Horde_Perms::READ:
return true;
default:
return false;
}
}
/**
* Return this events title.
*
* @return string The title of this event
*/
public function getTitle()
{
return $this->title;
}
/**
* Is this event an all-day event?
*
* Since there are no holidays lasting only a few hours, this is always
* true.
*
* @return boolean true
*/
public function isAllDay()
{
return true;
}
}
kronolith-4.2.13/lib/Event/Horde.php 0000664 0000765 0000024 00000025513 12654566222 014153 0 ustar
* @package Kronolith
*/
class Kronolith_Event_Horde extends Kronolith_Event
{
/**
* The type of the calender this event exists on.
*
* @var string
*/
public $calendarType = 'external';
/**
* The API (application) of this event.
*
* @var string
*/
protected $_api;
/**
* The link to this event.
*
* @var string
*/
protected $_link;
/**
* The link to edit this event.
*
* @var string
*/
protected $_editLink;
/**
* The link to delete this event.
*
* @var string
*/
protected $_deleteLink;
/**
* The link to this event in the ajax interface.
*
* @var string
*/
protected $_ajaxLink;
/**
* Any parameters to identify the object in the other Horde application.
*
* @var array
*/
protected $_params;
/**
* The event's owner.
*
* @var string
*/
protected $_owner;
/**
* A bitmask of permissions the current user has on this object.
*
* @var integer
*/
protected $_permissions;
/**
* Whether this event has a variable length.
*
* @boolean
*/
protected $_variableLength;
/**
* Constructor.
*
* @param Kronolith_Driver_Horde $driver The backend driver that this
* event is stored in.
* @param mixed $eventObject Backend specific event object
* that this will represent.
*/
public function __construct(Kronolith_Driver_Horde $driver, $eventObject = null)
{
$this->_api = $driver->api;
parent::__construct($driver, $eventObject);
}
/**
* Imports a backend specific event object.
*
* @param mixed $event Backend specific event object that this object
* will represent.
*/
public function fromDriver($event)
{
$this->id = '_' . $this->_api . $event['id'];
$this->icon = !empty($event['icon']) ? $event['icon'] : null;
$this->title = $event['title'];
$this->description = isset($event['description']) ? $event['description'] : '';
if (isset($event['location'])) {
$this->location = $event['location'];
}
try {
$this->start = new Horde_Date($event['start']);
$this->end = new Horde_Date($event['end']);
} catch (Horde_Date_Exception $e) {
throw new Kronolith_Exception($e);
}
if (isset($event['status'])) {
switch ($event['status']) {
case 'confirmed':
$this->status = Kronolith::STATUS_CONFIRMED;
break;
case 'tentative':
$this->status = Kronolith::STATUS_TENTATIVE;
break;
default:
$this->status = Kronolith::STATUS_FREE;
}
} else {
$this->status = Kronolith::STATUS_FREE;
}
if (isset($event['private'])) {
$this->private = $event['private'];
}
$this->_params = $event['params'];
$this->_link = !empty($event['link']) ? $event['link'] : null;
$this->url = !empty($event['url']) ? (string)$event['url'] : null;
$this->_editLink = !empty($event['edit_link']) ? $event['edit_link'] : null;
$this->_deleteLink = !empty($event['delete_link']) ? $event['delete_link'] : null;
$this->_ajaxLink = !empty($event['ajax_link']) ? $event['ajax_link'] : null;
$this->_backgroundColor = Kronolith::backgroundColor($event);
$this->_foregroundColor = Kronolith::foregroundColor($event);
if (isset($event['recurrence'])) {
$recurrence = new Horde_Date_Recurrence($this->start);
$recurrence->setRecurType($event['recurrence']['type']);
if (isset($event['recurrence']['end'])) {
$recurrence->setRecurEnd(new Horde_Date($event['recurrence']['end']));
}
if (isset($event['recurrence']['interval'])) {
$recurrence->setRecurInterval($event['recurrence']['interval']);
}
if (isset($event['recurrence']['count'])) {
$recurrence->setRecurCount($event['recurrence']['count']);
}
if (isset($event['recurrence']['days'])) {
$recurrence->setRecurOnDay($event['recurrence']['days']);
}
if (isset($event['recurrence']['exceptions'])) {
foreach ($event['recurrence']['exceptions'] as $exception) {
$recurrence->addException(substr($exception, 0, 4),
substr($exception, 4, 2),
substr($exception, 6, 2));
}
}
if (isset($event['recurrence']['completions'])) {
foreach ($event['recurrence']['completions'] as $completion) {
$recurrence->addCompletion(substr($completion, 0, 4),
substr($completion, 4, 2),
substr($completion, 6, 2));
}
}
$this->recurrence = $recurrence;
}
if (isset($event['owner'])) {
$this->_owner = $event['owner'];
}
if (isset($event['permissions'])) {
$this->_permissions = $event['permissions'];
}
if (isset($event['variable_length'])) {
$this->_variableLength = $event['variable_length'];
}
$this->initialized = true;
$this->stored = true;
}
/**
* Prepares this event to be saved to the backend.
*/
public function toTimeobject()
{
$timeobject = array(
'id' => substr($this->id, strlen($this->_api) + 1),
'icon' => $this->icon,
'title' => $this->title,
'description' => $this->description,
'location' => $this->location,
'start' => $this->start->format('Y-m-d\TH:i:s'),
'end' => $this->end->format('Y-m-d\TH:i:s'),
'params' => $this->_params,
'link' => $this->_link,
'ajax_link' => $this->_ajaxLink,
'permissions' => $this->_permissions,
'variable_length' => $this->_variableLength);
if ($this->recurs()) {
$timeobject['recurrence'] = array('type' => $this->recurrence->getRecurType());
if ($end = $this->recurrence->getRecurEnd()) {
$timeobject['recurrence']['end'] = $end->format('Y-m-d\TH:i:s');
}
if ($interval = $this->recurrence->getRecurInterval()) {
$timeobject['recurrence']['interval'] = $interval;
}
if ($count = $this->recurrence->getRecurCount()) {
$timeobject['recurrence']['count'] = $count;
}
if ($days = $this->recurrence->getRecurOnDays()) {
$timeobject['recurrence']['days'] = $days;
}
if ($count = $this->recurrence->getRecurCount()) {
$timeobject['recurrence']['count'] = $count;
}
if ($exceptions = $this->recurrence->getExceptions()) {
$timeobject['recurrence']['exceptions'] = $exceptions;
}
}
return $timeobject;
}
/**
* Encapsulates permissions checking.
*
* @param integer $permission The permission to check for.
* @param string $user The user to check permissions for.
*
* @return boolean
*/
public function hasPermission($permission, $user = null)
{
if ($user === null) {
$user = $GLOBALS['registry']->getAuth();
}
if (isset($this->_owner) && $this->_owner == $user) {
return true;
}
if (isset($this->_permissions)) {
return (bool)($this->_permissions & $permission);
}
switch ($permission) {
case Horde_Perms::SHOW:
case Horde_Perms::READ:
return true;
default:
return false;
}
}
/**
* Returns the title of this event.
*
* @param string $user The current user.
*
* @return string The title of this event.
*/
public function getTitle($user = null)
{
return !empty($this->title) ? $this->title : _("[Unnamed event]");
}
/**
* @param array $params
*
* @return Horde_Url
*/
public function getViewUrl($params = array(), $full = false, $encoded = true)
{
if (empty($this->_link)) {
return null;
}
$url = clone $this->_link;
return $url->setRaw(!$encoded);
}
/**
* @param array $params
*
* @return Horde_Url
*/
public function getEditUrl($params = array(), $full = false)
{
if (empty($this->_editLink)) {
return null;
}
$url = clone $this->_editLink;
if (isset($params['url'])) {
$url->add('url', $params['url']);
}
return $url->setRaw($full);
}
/**
* @param array $params
*
* @return Horde_Url
*/
public function getDeleteUrl($params = array(), $full = false)
{
if (empty($this->_deleteLink)) {
return null;
}
$url = clone $this->_deleteLink;
if (isset($params['url'])) {
$url->add('url', $params['url']);
}
return $url->setRaw($full);
}
/**
* Returns a simple object suitable for json transport representing this
* event.
*
* @param boolean $allDay If not null, overrides whether the event is
* an all-day event.
* @param boolean $full Whether to return all event details.
* @param string $time_format The date() format to use for time formatting.
*
* @return object A simple object.
*/
public function toJson($allDay = null, $full = false, $time_format = 'H:i')
{
$json = parent::toJson($allDay, $full, $time_format);
if ($this->_ajaxLink) {
$json->aj = $this->_ajaxLink;
} elseif ($link = (string)$this->getViewUrl(array(), true, false)) {
$json->ln = $link;
}
if (isset($this->_variableLength)) {
$json->vl = $this->_variableLength;
}
return $json;
}
/**
* @return string A tooltip for quick descriptions of this event.
*/
public function getTooltip()
{
return Horde_String::wrap($this->description);
}
}
kronolith-4.2.13/lib/Event/Ical.php 0000664 0000765 0000024 00000006760 12654566222 013765 0 ustar
* @author Jan Schneider
* @package Kronolith
*/
class Kronolith_Event_Ical extends Kronolith_Event
{
/**
* The status of this event.
*
* @var integer
*/
public $status = Kronolith::STATUS_FREE;
/**
* The type of the calender this event exists on.
*
* @var string
*/
public $calendarType = 'remote';
/**
* The Horde_Perms permissions mask matching the CalDAV ACL of this event's
* calendar.
*
* @var integer
*/
public $permission = 0;
/**
* Imports a backend specific event object.
*
* @param Horde_Icalendar_Vevent Backend specific event object that this
* object will represent.
*/
public function fromDriver($vEvent)
{
$this->fromiCalendar($vEvent);
$this->initialized = true;
$this->stored = true;
}
/**
* Encapsulates permissions checking.
*
* $user is being ignored.
*
* @param integer $permission The permission to check for.
* @param string $user The user to check permissions for.
*
* @return boolean
*/
public function hasPermission($permission, $user = null)
{
return $this->permission & $permission;
}
/**
* Returns the title of this event.
*
* @param string $user The current user.
*
* @return string The title of this event.
*/
public function getTitle($user = null)
{
return !empty($this->title) ? $this->title : _("[Unnamed event]");
}
/**
* @param array $params
*
* @return Horde_Url
*/
public function getViewUrl($params = array(), $full = false, $encoded = true)
{
if ($this->url) {
return new Horde_Url($this->url, !$encoded);
}
return parent::getViewUrl($params, $full, $encoded);
}
/**
* Parses the various exception related fields. Only deal with the EXDATE
* field here.
*
* @param Horde_Icalendar $vEvent The vEvent part.
*/
protected function _handlevEventRecurrence($vEvent)
{
// Recurrence.
try {
$rrule = $vEvent->getAttribute('RRULE');
if (!is_array($rrule)) {
$this->recurrence = new Horde_Date_Recurrence($this->start);
if (strpos($rrule, '=') !== false) {
$this->recurrence->fromRRule20($rrule);
} else {
$this->recurrence->fromRRule10($rrule);
}
// Exceptions. EXDATE represents deleted events, just add the
// exception, no new event is needed.
$exdates = $vEvent->getAttributeValues('EXDATE');
if (is_array($exdates)) {
foreach ($exdates as $exdate) {
if (is_array($exdate)) {
$this->recurrence->addException((int)$exdate['year'],
(int)$exdate['month'],
(int)$exdate['mday']);
}
}
}
}
} catch (Horde_Icalendar_Exception $e) {}
}
}
kronolith-4.2.13/lib/Event/Kolab.php 0000664 0000765 0000024 00000024204 12654566222 014136 0 ustar
* @author Gunnar Wrobel
* @author Stuart Binge
* @package Kronolith
*/
class Kronolith_Event_Kolab extends Kronolith_Event
{
/**
* The type of the calender this event exists on.
*
* @var string
*/
public $calendarType = 'internal';
/**
* Constructor.
*
* @param Kronolith_Driver_Kolab $driver The backend driver that this
* event is stored in.
* @param mixed $eventObject Backend specific event object
* that this will represent.
*/
public function __construct(Kronolith_Driver_Kolab $driver, $eventObject = null)
{
static $alarm;
/* Set default alarm value. */
if (!isset($alarm) && isset($GLOBALS['prefs'])) {
$alarm = $GLOBALS['prefs']->getValue('default_alarm');
}
$this->alarm = $alarm;
parent::__construct($driver, $eventObject);
}
/**
* Retrieves history information for this event from the history backend.
*/
public function loadHistory()
{
}
/**
* Imports a backend specific event object.
*
* @param array $event Backend specific event object that this object
* will represent.
*/
public function fromDriver($event)
{
$this->uid = $event['uid'];
$this->id = Horde_Url::uriB64Encode($event['uid']);
if (isset($event['summary'])) {
$this->title = $event['summary'];
}
if (isset($event['body'])) {
$this->description = $event['body'];
}
if (isset($event['location'])) {
$this->location = $event['location'];
}
if (isset($event['sensitivity']) &&
($event['sensitivity'] == 'private' || $event['sensitivity'] == 'confidential')) {
$this->private = true;
}
if (isset($event['organizer']['smtp-address'])) {
if (Kronolith::isUserEmail($GLOBALS['registry']->getAuth(), $event['organizer']['smtp-address'])) {
$this->creator = $GLOBALS['registry']->getAuth();
} else {
$this->creator = $event['organizer']['smtp-address'];
}
}
if (isset($event['alarm'])) {
$this->alarm = $event['alarm'];
}
if (isset($event['horde-alarm-methods'])) {
$this->methods = @unserialize($event['horde-alarm-methods']);
}
$tz_local = date_default_timezone_get();
$this->start = new Horde_Date($event['start-date']);
$this->start->setTimezone($tz_local);
$this->end = new Horde_Date($event['end-date']);
$this->end->setTimezone($tz_local);
$this->durMin = ($this->end->timestamp() - $this->start->timestamp()) / 60;
if (!empty($event['creation-date'])) {
$this->created = new Horde_Date($event['creation-date']);
}
if (!empty($event['last-modification-date'])) {
$this->modified = new Horde_Date($event['last-modification-date']);
}
if (isset($event['show-time-as'])) {
switch ($event['show-time-as']) {
case 'free':
$this->status = Kronolith::STATUS_FREE;
break;
case 'tentative':
$this->status = Kronolith::STATUS_TENTATIVE;
break;
case 'busy':
case 'outofoffice':
default:
$this->status = Kronolith::STATUS_CONFIRMED;
}
} else {
$this->status = Kronolith::STATUS_CONFIRMED;
}
// Recurrence
if (isset($event['recurrence'])) {
if (isset($event['recurrence']['exclusion'])) {
$exceptions = array();
foreach($event['recurrence']['exclusion'] as $exclusion) {
if (!empty($exclusion)) {
$exceptions[] = $exclusion->format('Ymd');
}
}
$event['recurrence']['exceptions'] = $exceptions;
}
if (isset($event['recurrence']['complete'])) {
$completions = array();
foreach($event['recurrence']['complete'] as $complete) {
if (!empty($complete)) {
$completions[] = $complete->format('Ymd');
}
}
$event['recurrence']['completions'] = $completions;
}
$this->recurrence = new Horde_Date_Recurrence($this->start);
$this->recurrence->fromKolab($event['recurrence']);
}
// Attendees
$attendee_count = 0;
if (!empty($event['attendee'])) {
foreach($event['attendee'] as $attendee) {
$name = $attendee['display-name'];
$email = $attendee['smtp-address'];
$role = $attendee['role'];
switch ($role) {
case 'optional':
$role = Kronolith::PART_OPTIONAL;
break;
case 'resource':
$role = Kronolith::PART_NONE;
break;
case 'required':
default:
$role = Kronolith::PART_REQUIRED;
break;
}
$status = $attendee['status'];
switch ($status) {
case 'accepted':
$status = Kronolith::RESPONSE_ACCEPTED;
break;
case 'declined':
$status = Kronolith::RESPONSE_DECLINED;
break;
case 'tentative':
$status = Kronolith::RESPONSE_TENTATIVE;
break;
case 'none':
default:
$status = Kronolith::RESPONSE_NONE;
break;
}
// Attendees without an email address get added as incremented number
if (empty($email)) {
$email = $attendee_count;
$attendee_count++;
}
$this->addAttendee($email, $role, $status, $name);
}
}
// Tags
if (isset($event['categories'])) {
$this->_internaltags = $event['categories'];
}
$this->initialized = true;
$this->stored = true;
}
/**
* Prepares this event to be saved to the backend.
*/
public function toKolab()
{
$event = array();
$event['uid'] = $this->uid;
$event['summary'] = $this->title;
$event['body'] = $this->description;
$event['location'] = $this->location;
$event['sensitivity'] = $this->private ? 'private' : 'public';
// Only set organizer if this is a new event
if ($this->_id == null) {
$organizer = array(
'display-name' => Kronolith::getUserName($this->creator),
'smtp-address' => Kronolith::getUserEmail($this->creator)
);
$event['organizer'] = $organizer;
}
if ($this->alarm != 0) {
$event['alarm'] = $this->alarm;
}
if ($this->methods !== null) {
$event['horde-alarm-methods'] = serialize($this->methods);
}
$event['start-date'] = $this->start->toDateTime();
$event['end-date'] = $this->end->toDateTime();
$event['_is_all_day'] = $this->isAllDay();
switch ($this->status) {
case Kronolith::STATUS_FREE:
case Kronolith::STATUS_CANCELLED:
$event['show-time-as'] = 'free';
break;
case Kronolith::STATUS_TENTATIVE:
$event['show-time-as'] = 'tentative';
break;
// No mapping for outofoffice
case Kronolith::STATUS_CONFIRMED:
default:
$event['show-time-as'] = 'busy';
}
// Recurrence
if ($this->recurs()) {
$event['recurrence'] = $this->recurrence->toKolab();
}
// Attendees
$event['attendee'] = array();
foreach ($this->attendees as $email => $attendee) {
$new_attendee = array();
$new_attendee['display-name'] = $attendee['name'];
// Attendee without an email address
if (is_int($email)) {
$new_attendee['smtp-address'] = '';
} else {
$new_attendee['smtp-address'] = $email;
}
switch ($attendee['attendance']) {
case Kronolith::PART_OPTIONAL:
$new_attendee['role'] = 'optional';
break;
case Kronolith::PART_NONE:
$new_attendee['role'] = 'resource';
break;
case Kronolith::PART_REQUIRED:
default:
$new_attendee['role'] = 'required';
break;
}
$new_attendee['request-response'] = 'false';
switch ($attendee['response']) {
case Kronolith::RESPONSE_ACCEPTED:
$new_attendee['status'] = 'accepted';
break;
case Kronolith::RESPONSE_DECLINED:
$new_attendee['status'] = 'declined';
break;
case Kronolith::RESPONSE_TENTATIVE:
$new_attendee['status'] = 'tentative';
break;
case Kronolith::RESPONSE_NONE:
default:
$new_attendee['status'] = 'none';
break;
}
$event['attendee'][] = $new_attendee;
}
// Tags
if (!is_array($this->tags)) {
$this->tags = Kronolith::getTagger()->split($this->tags);
}
if ($this->tags) {
$event['categories'] = $this->tags;
}
return $event;
}
}
kronolith-4.2.13/lib/Event/Mock.php 0000664 0000765 0000024 00000000717 12654566222 014002 0 ustar
* @package Kronolith
*/
/**
* Event class implementation for the mock driver.
*
* @author Jan Schneider
* @package Kronolith
*/
class Kronolith_Event_Mock extends Kronolith_Event
{
}
kronolith-4.2.13/lib/Event/Sql.php 0000664 0000765 0000024 00000025747 12654566222 013662 0 ustar
* @author Chuck Hagenbuch
* @author Jan Schneider
* @package Kronolith
*/
class Kronolith_Event_Sql extends Kronolith_Event
{
/**
* The type of the calender this event exists on.
*
* @var string
*/
public $calendarType = 'internal';
/**
* Constructor.
*
* @param Kronolith_Driver_Sql $driver The backend driver that this event
* is stored in.
* @param mixed $eventObject Backend specific event object
* that this will represent.
*/
public function __construct(Kronolith_Driver_Sql $driver, $eventObject = null)
{
/* Set default alarm value. */
if (isset($GLOBALS['prefs'])) {
$this->alarm = $GLOBALS['prefs']->getValue('default_alarm');
}
parent::__construct($driver, $eventObject);
if (!empty($this->calendar) &&
$GLOBALS['calendar_manager']->getEntry(Kronolith::ALL_CALENDARS, $this->calendar) !== false) {
$this->_backgroundColor = $GLOBALS['calendar_manager']->getEntry(Kronolith::ALL_CALENDARS, $this->calendar)->background();
$this->_foregroundColor = $GLOBALS['calendar_manager']->getEntry(Kronolith::ALL_CALENDARS, $this->calendar)->foreground();
}
}
/**
* Imports a backend specific event object.
*
* @param array $event Backend specific event object that this object
* will represent.
*/
public function fromDriver($SQLEvent)
{
$driver = $this->getDriver();
if (isset($SQLEvent['event_timezone'])) {
$this->timezone = $SQLEvent['event_timezone'];
}
$tz_local = date_default_timezone_get();
$this->allday = (bool)$SQLEvent['event_allday'];
if (!$this->allday && $driver->getParam('utc')) {
$this->start = new Horde_Date($SQLEvent['event_start'], 'UTC');
$this->start->setTimezone($tz_local);
$this->end = new Horde_Date($SQLEvent['event_end'], 'UTC');
$this->end->setTimezone($tz_local);
} else {
$this->start = new Horde_Date($SQLEvent['event_start']);
$this->end = new Horde_Date($SQLEvent['event_end']);
if ($this->end->hour == 23 && $this->end->min == 59) {
$this->end->hour = $this->end->min = $this->end->sec = 0;
$this->end->mday++;
}
}
$this->durMin = ($this->end->timestamp() - $this->start->timestamp()) / 60;
$this->title = $driver->convertFromDriver($SQLEvent['event_title']);
$this->id = $SQLEvent['event_id'];
$this->uid = $SQLEvent['event_uid'];
$this->creator = $SQLEvent['event_creator_id'];
if (!empty($SQLEvent['event_recurtype'])) {
$this->recurrence = new Horde_Date_Recurrence($this->start);
$this->recurrence->setRecurType((int)$SQLEvent['event_recurtype']);
$this->recurrence->setRecurInterval((int)$SQLEvent['event_recurinterval']);
if (isset($SQLEvent['event_recurenddate']) &&
$SQLEvent['event_recurenddate'] != '9999-12-31 23:59:59') {
if ($driver->getParam('utc')) {
$recur_end = new Horde_Date($SQLEvent['event_recurenddate'], 'UTC');
if ($recur_end->min == 0) {
/* Old recurrence end date format. */
$recur_end = new Horde_Date($SQLEvent['event_recurenddate']);
$recur_end->hour = 23;
$recur_end->min = 59;
$recur_end->sec = 59;
} else {
$recur_end->setTimezone(date_default_timezone_get());
}
} else {
$recur_end = new Horde_Date($SQLEvent['event_recurenddate']);
$recur_end->hour = 23;
$recur_end->min = 59;
$recur_end->sec = 59;
}
$this->recurrence->setRecurEnd($recur_end);
}
if (isset($SQLEvent['event_recurcount'])) {
$this->recurrence->setRecurCount((int)$SQLEvent['event_recurcount']);
}
if (isset($SQLEvent['event_recurdays'])) {
$this->recurrence->recurData = (int)$SQLEvent['event_recurdays'];
}
if (!empty($SQLEvent['event_exceptions'])) {
$this->recurrence->exceptions = explode(',', $SQLEvent['event_exceptions']);
}
}
if (isset($SQLEvent['event_location'])) {
$this->location = $driver->convertFromDriver($SQLEvent['event_location']);
}
if (isset($SQLEvent['event_url'])) {
$this->url = $SQLEvent['event_url'];
}
if (isset($SQLEvent['event_private'])) {
$this->private = (bool)($SQLEvent['event_private']);
}
if (isset($SQLEvent['event_status'])) {
$this->status = (int)$SQLEvent['event_status'];
}
if (isset($SQLEvent['event_attendees'])) {
$attendees = unserialize($SQLEvent['event_attendees']);
if ($attendees) {
$this->attendees = array_change_key_case($driver->convertFromDriver($attendees));
}
}
if (isset($SQLEvent['event_resources'])) {
$resources = unserialize($SQLEvent['event_resources']);
if ($resources) {
$this->_resources = array_change_key_case($driver->convertFromDriver($resources));
}
}
if (isset($SQLEvent['event_description'])) {
$this->description = $driver->convertFromDriver($SQLEvent['event_description']);
}
if (isset($SQLEvent['event_alarm'])) {
$this->alarm = (int)$SQLEvent['event_alarm'];
}
if (isset($SQLEvent['event_alarm_methods'])) {
$methods = unserialize($SQLEvent['event_alarm_methods']);
if ($methods) {
$this->methods = $driver->convertFromDriver($methods);
}
}
if (isset($SQLEvent['event_baseid'])) {
$this->baseid = $SQLEvent['event_baseid'];
}
if (isset($SQLEvent['event_exceptionoriginaldate'])) {
if ($driver->getParam('utc')) {
$this->exceptionoriginaldate = new Horde_Date($SQLEvent['event_exceptionoriginaldate'], 'UTC');
$this->exceptionoriginaldate->setTimezone($tz_local);
} else {
$this->exceptionoriginaldate = new Horde_Date($SQLEvent['event_exceptionoriginaldate']);
}
}
$this->initialized = true;
$this->stored = true;
}
/**
* Prepares this event to be saved to the backend.
*
* @param boolean $full Return full data, including uid and id.
*
* @return array The event properties.
*/
public function toProperties($full = false)
{
$driver = $this->getDriver();
$properties = array();
if ($full) {
$properties['event_id'] = $this->id;
$properties['event_uid'] = $this->uid;
}
/* Basic fields. */
$properties['event_creator_id'] = $driver->convertToDriver($this->creator);
$properties['event_title'] = $driver->convertToDriver($this->title);
$properties['event_description'] = $driver->convertToDriver($this->description);
$properties['event_location'] = $driver->convertToDriver($this->location);
$properties['event_timezone'] = $this->timezone;
$properties['event_url'] = (string)$this->url;
$properties['event_private'] = (int)$this->private;
$properties['event_status'] = $this->status;
$properties['event_attendees'] = serialize($driver->convertToDriver($this->attendees));
$properties['event_resources'] = serialize($driver->convertToDriver($this->getResources()));
$properties['event_modified'] = $_SERVER['REQUEST_TIME'];
if ($this->isAllDay()) {
$properties['event_start'] = $this->start->strftime('%Y-%m-%d %H:%M:%S');
$properties['event_end'] = $this->end->strftime('%Y-%m-%d %H:%M:%S');
$properties['event_allday'] = 1;
} else {
if ($driver->getParam('utc')) {
$start = clone $this->start;
$end = clone $this->end;
$start->setTimezone('UTC');
$end->setTimezone('UTC');
} else {
$start = $this->start;
$end = $this->end;
}
$properties['event_start'] = $start->strftime('%Y-%m-%d %H:%M:%S');
$properties['event_end'] = $end->strftime('%Y-%m-%d %H:%M:%S');
$properties['event_allday'] = 0;
}
/* Alarm. */
$properties['event_alarm'] = (int)$this->alarm;
/* Alarm Notification Methods. */
$properties['event_alarm_methods'] = serialize($driver->convertToDriver($this->methods));
/* Recurrence. */
if (!$this->recurs()) {
$properties['event_recurtype'] = 0;
} else {
$recur = $this->recurrence->getRecurType();
if ($this->recurrence->hasRecurEnd()) {
if ($driver->getParam('utc')) {
$recur_end = clone $this->recurrence->recurEnd;
$recur_end->setTimezone('UTC');
} else {
$recur_end = $this->recurrence->recurEnd;
}
} else {
$recur_end = new Horde_Date(array('year' => 9999, 'month' => 12, 'mday' => 31, 'hour' => 23, 'min' => 59, 'sec' => 59));
}
$properties['event_recurtype'] = $recur;
$properties['event_recurinterval'] = $this->recurrence->getRecurInterval();
$properties['event_recurenddate'] = $recur_end->format('Y-m-d H:i:s');
$properties['event_recurcount'] = $this->recurrence->getRecurCount();
switch ($recur) {
case Horde_Date_Recurrence::RECUR_WEEKLY:
$properties['event_recurdays'] = $this->recurrence->getRecurOnDays();
break;
}
$properties['event_exceptions'] = implode(',', $this->recurrence->getExceptions());
}
/* Exception information */
if (!empty($this->baseid)) {
$properties['event_baseid'] = $this->baseid;
if ($driver->getParam('utc')) {
$eod = clone $this->exceptionoriginaldate;
$eod->setTimezone('UTC');
} else {
$eod = $this->exceptionoriginaldate;
}
$properties['event_exceptionoriginaldate'] = $eod->strftime('%Y-%m-%d %H:%M:%S');
}
return $properties;
}
}
kronolith-4.2.13/lib/Factory/Calendars.php 0000664 0000765 0000024 00000003610 12654566222 015326 0 ustar
* @package Kronolith
*/
class Kronolith_Factory_Calendars
{
/**
* Calendars drivers already created.
*
* @var array
*/
private $_instances = array();
/**
* The injector.
*
* @var Horde_Injector
*/
private $_injector;
/**
* Constructor.
*
* @param Horde_Injector $injector The injector to use.
*/
public function __construct(Horde_Injector $injector)
{
$this->_injector = $injector;
}
/**
* Return a Kronolith_Calendars_Base instance.
*
* @return Kronolith_Calendars_Base
*/
public function create()
{
if (!isset($GLOBALS['conf']['calendars']['driver'])) {
$driver = 'Default';
} else {
$driver = Horde_String::ucfirst($GLOBALS['conf']['calendars']['driver']);
}
if (empty($this->_instances[$driver])) {
$class = 'Kronolith_Calendars_' . $driver;
if (class_exists($class)) {
$params = array();
switch ($driver) {
case 'Default':
$params['identity'] = $this->_injector->getInstance('Horde_Core_Factory_Identity')->create();
break;
}
$this->_instances[$driver] = new $class(
$GLOBALS['injector']->getInstance('Kronolith_Shares'),
$GLOBALS['registry']->getAuth(),
$params
);
} else {
throw new Kronolith_Exception(sprintf('Unable to load the definition of %s.', $class));
}
}
return $this->_instances[$driver];
}
}
kronolith-4.2.13/lib/Factory/Driver.php 0000664 0000765 0000024 00000007564 12654566222 014701 0 ustar _instances[$driver])) {
return $this->_instances[$driver];
}
switch ($driver) {
case 'Sql':
$params = array_merge(Horde::getDriverConfig('calendar', 'sql'), $params);
if (isset($params['driverconfig']) &&
$params['driverconfig'] != 'horde') {
$customParams = $params;
unset($customParams['driverconfig'], $customParams['table'], $customParams['utc']);
$params['db'] = $this->_injector->getInstance('Horde_Core_Factory_Db')->create('kronolith', $customParams);
} else {
$params['db'] = $this->_injector->getInstance('Horde_Db_Adapter');
}
break;
case 'Resource_Sql':
if (!isset($GLOBALS['conf']['calendar']['driver']) ||
$GLOBALS['conf']['resource']['driver'] != 'sql') {
throw new Kronolith_Exception(_("Resources are disabled"));
}
$params = array_merge(Horde::getDriverConfig('resource', 'sql'), $params);
if ($params['driverconfig'] != 'Horde') {
$customParams = $params;
unset($customParams['driverconfig'], $customParams['table'], $customParams['utc']);
$params['db'] = $this->_injector->getInstance('Horde_Core_Factory_Db')->create('kronolith', $customParams);
} else {
$params['db'] = $this->_injector->getInstance('Horde_Db_Adapter');
}
break;
case 'Kolab':
$params['storage'] = $GLOBALS['injector']->getInstance('Horde_Kolab_Storage');
break;
case 'Ical':
case 'Mock':
break;
case 'Horde':
$params['registry'] = $GLOBALS['registry'];
break;
case 'Holidays':
if (empty($GLOBALS['conf']['holidays']['enable'])) {
throw new Kronolith_Exception(_("Holidays are disabled"));
}
$params['language'] = $GLOBALS['language'];
break;
default:
throw new InvalidArgumentException('No calendar driver specified');
break;
}
$class = 'Kronolith_Driver_' . $driver;
if (class_exists($class)) {
$ob = new $class($params);
try {
$ob->initialize();
} catch (Exception $e) {
$ob = new Kronolith_Driver($params, sprintf(_("The Calendar backend is not currently available: %s"), $e->getMessage()));
}
} else {
$ob = new Kronolith_Driver($params, sprintf(_("Unable to load the definition of %s."), $class));
}
$this->_instances[$driver] = $ob;
return $ob;
}
}
kronolith-4.2.13/lib/Factory/Geo.php 0000664 0000765 0000024 00000001326 12654566222 014146 0 ustar
* @package Kronolith
*/
class Kronolith_Factory_Geo extends Horde_Core_Factory_Injector
{
/**
* Return the driver instance.
*
* @return Kronolith_Storage
* @throws Kronolith_Exception
*/
public function create(Horde_Injector $injector)
{
if (empty($GLOBALS['conf']['maps']['geodriver'])) {
throw new Kronolith_Exception('Geospatial support not configured.');
}
$class = 'Kronolith_Geo_' . $GLOBALS['conf']['maps']['geodriver'];
$db = $injector->getInstance('Horde_Db_Adapter');
return new $class($db);
}
}
kronolith-4.2.13/lib/Factory/Shares.php 0000664 0000765 0000024 00000001002 12654566222 014650 0 ustar
* @category Horde
* @package Kronolith
*/
class Kronolith_Factory_Shares extends Horde_Core_Factory_Injector
{
/**
* Return the driver instance.
*
* @return Horde_Core_Share_Driver
* @throws Horde_Exception
*/
public function create(Horde_Injector $injector)
{
return $injector->getInstance('Horde_Core_Factory_Share')->create();
}
}
kronolith-4.2.13/lib/Factory/Storage.php 0000664 0000765 0000024 00000003265 12654566222 015044 0 ustar getAuth();
} else {
$user = $params['user'];
unset($params['user']);
}
if (empty($params['driver'])) {
$driver = Horde_String::ucfirst($GLOBALS['conf']['storage']['driver']);
} else {
$driver = $params['driver'];
unset($params['driver']);
}
$driver = basename($driver);
$class = 'Kronolith_Storage_' . $driver;
$driver_params = Horde::getDriverConfig('storage', 'Sql');
if ($driver == 'Sql') {
if ($driver_params != 'horde') {
// Custom DB config
$params['db'] = $this->_injector->getInstance('Horde_Core_Factory_Db')->create('kronolith', Horde::getDriverConfig('storage', 'Sql'));
} else {
// Horde default DB config
$params['db'] = $this->_injector->getInstance('Horde_Db_Adapter');
}
$params['table'] = $driver_params['table'];
}
if (class_exists($class)) {
$driver = new $class($user, $params);
} else {
throw new Kronolith_Exception(sprintf(_("Unable to load the definition of %s."), $class));
}
try {
$driver->initialize();
} catch (Exception $e) {
$driver = new Kronolith_Storage($params);
}
return $driver;
}
}
kronolith-4.2.13/lib/Form/Type/KronolithTags.php 0000664 0000765 0000024 00000001202 12654566222 016432 0 ustar
* @license http://www.horde.org/licenses/gpl GPL
* @package Kronolith
*/
class Kronolith_Form_Type_KronolithTags extends Horde_Form_Type
{
public function getInfo(&$vars, &$var, &$info)
{
$info = $var->getValue($vars);
}
public function isValid(&$var, &$vars, $value, &$message)
{
return true;
}
public function getTypeName()
{
return 'KronolithTags';
}
} kronolith-4.2.13/lib/Form/CreateCalendar.php 0000775 0000765 0000024 00000003334 12654566222 015571 0 ustar
* @package Kronolith
*/
class Kronolith_Form_CreateCalendar extends Horde_Form
{
public function __construct($vars)
{
parent::__construct($vars, _("Create Calendar"));
$this->addVariable(_("Name"), 'name', 'text', true);
$v = $this->addVariable(_("Color"), 'color', 'colorpicker', false);
$v->setDefault(Kronolith::randomColor());
if ($GLOBALS['registry']->isAdmin()) {
$this->addVariable(_("System Calendar"), 'system', 'boolean', false, false, _("System calendars don't have an owner. Only administrators can change the calendar settings and permissions."));
}
$this->addVariable(_("Description"), 'description', 'longtext', false, false, null, array(4, 60));
$this->addVariable(_("Tags"), 'tags', 'kronolith:KronolithTags', false);
$this->setButtons(array(_("Create")));
}
/**
* @throws Kronolith_Exception
*/
public function execute()
{
$info = array();
foreach (array('name', 'color', 'description', 'tags', 'system') as $key) {
$info[$key] = $this->_vars->get($key);
}
return Kronolith::addShare($info);
}
public function renderActive()
{
return parent::renderActive(
$this->getRenderer(array('varrenderer_driver' => array('kronolith', 'kronolith'))),
$this->_vars);
}
}
kronolith-4.2.13/lib/Form/CreateResource.php 0000664 0000765 0000024 00000005630 12654566222 015645 0 ustar
* @author Michael J. Rubinsky
* @package Kronolith
*/
class Kronolith_Form_CreateResource extends Horde_Form
{
/**
* @throws Kronolith_Exception
*/
public function __construct($vars)
{
parent::__construct($vars, _("Create Resource"));
$responses = array(Kronolith_Resource::RESPONSETYPE_ALWAYS_ACCEPT => _("Always Accept"),
Kronolith_Resource::RESPONSETYPE_ALWAYS_DECLINE => _("Always Decline"),
Kronolith_Resource::RESPONSETYPE_AUTO => _("Automatically"),
Kronolith_Resource::RESPONSETYPE_MANUAL => _("Manual"),
Kronolith_Resource::RESPONSETYPE_NONE => _("None"));
/* Get a list of available resource groups */
$groups = Kronolith::getDriver('Resource')
->listResources(Horde_Perms::READ,
array('type' => Kronolith_Resource::TYPE_GROUP));
$enum = array();
foreach ($groups as $id => $group) {
$enum[$id] = $group->get('name');
}
$this->addVariable(_("Name"), 'name', 'text', true);
$this->addVariable(_("Description"), 'description', 'longtext', false, false, null, array(4, 60));
$this->addVariable(_("Email"), 'email', 'email', false);
$v = $this->addVariable(_("Response type"), 'responsetype', 'enum', true, false, null, array('enum' => $responses));
$v->setDefault(Kronolith_Resource::RESPONSETYPE_AUTO);
$this->addVariable(_("Groups"), 'category', 'multienum', false, false, null, array('enum' => $enum));
$this->setButtons(array(_("Create")));
}
/**
* @throws Kronolith_Exception
*/
public function execute()
{
$new = array('name' => $this->_vars->get('name'),
'description' => $this->_vars->get('description'),
'response_type' => $this->_vars->get('responsetype'),
'email' => $this->_vars->get('email'));
$resource = Kronolith_Resource::addResource(new Kronolith_Resource_Single($new));
/* Do we need to add this to any groups? */
$groups = $this->_vars->get('category');
if (!empty($groups)) {
foreach ($groups as $group_id) {
$group = Kronolith::getDriver('Resource')->getResource($group_id);
$members = $group->get('members');
$members[] = $resource->getId();
$group->set('members', $members);
$group->save();
}
}
}
}
kronolith-4.2.13/lib/Form/CreateResourceGroup.php 0000664 0000765 0000024 00000003137 12654566222 016662 0 ustar
* @author Michael J. Rubinsky
* @package Kronolith
*/
class Kronolith_Form_CreateResourceGroup extends Horde_Form
{
/**
* @throws Kronolith_Exception
*/
public function __construct($vars)
{
parent::__construct($vars, _("Create Resource Group"));
$resources = Kronolith::getDriver('Resource')->listResources(Horde_Perms::READ, array('type' => Kronolith_Resource::TYPE_SINGLE));
$enum = array();
foreach ($resources as $resource) {
$enum[$resource->getId()] = htmlspecialchars($resource->get('name'));
}
$this->addVariable(_("Name"), 'name', 'text', true);
$this->addVariable(_("Description"), 'description', 'longtext', false, false, null, array(4, 60));
$this->addVariable(_("Resources"), 'members', 'multienum', false, false, null, array('enum' => $enum));
$this->setButtons(array(_("Create")));
}
public function execute()
{
$new = array('name' => $this->_vars->get('name'),
'description' => $this->_vars->get('description'),
'members' => $this->_vars->get('members'));
Kronolith_Resource::addResource(new Kronolith_Resource_Group($new));
}
}
kronolith-4.2.13/lib/Form/DeleteCalendar.php 0000664 0000765 0000024 00000002747 12654566222 015574 0 ustar
* @package Kronolith
*/
class Kronolith_Form_DeleteCalendar extends Horde_Form
{
/**
* Calendar being deleted.
*/
protected $_calendar;
public function __construct($vars, $calendar)
{
$this->_calendar = $calendar;
parent::__construct($vars, sprintf(_("Delete %s"), $calendar->get('name')));
$this->addHidden('', 'c', 'text', true);
$this->addVariable(sprintf(_("Really delete the calendar \"%s\"? This cannot be undone and all data on this calendar will be permanently removed."), htmlspecialchars($this->_calendar->get('name'))), 'desc', 'description', false);
$this->setButtons(array(
array('class' => 'horde-delete', 'value' => _("Delete")),
array('class' => 'horde-cancel', 'value' => _("Cancel")),
));
}
/**
* @throws Kronolith_Exception
*/
public function execute()
{
if ($this->_vars->get('submitbutton') == _("Cancel")) {
Horde::url($GLOBALS['prefs']->getValue('defaultview') . '.php', true)
->redirect();
}
Kronolith::deleteShare($this->_calendar);
}
}
kronolith-4.2.13/lib/Form/DeleteResource.php 0000664 0000765 0000024 00000004047 12654566222 015645 0 ustar
* @author Michael J. Rubinsky
* @package Kronolith
*/
class Kronolith_Form_DeleteResource extends Horde_Form
{
/**
* Resource being deleted.
*
* @var Kronolith_Resource_Single
*/
protected $_resource;
public function __construct($vars, $resource)
{
$this->_resource = $resource;
parent::__construct($vars, sprintf(_("Delete %s"), $resource->get('name')));
$this->addHidden('', 'c', 'text', true);
$this->addVariable(sprintf(_("Really delete the resource \"%s\"? This cannot be undone and all data on this resource will be permanently removed."), htmlspecialchars($this->_resource->get('name'))), 'desc', 'description', false);
$this->setButtons(array(
array('class' => 'horde-delete', 'value' => _("Delete")),
array('class' => 'horde-cancel', 'value' => _("Cancel")),
));
}
/**
* @throws Kronolith_Exception
*/
public function execute()
{
// If cancel was clicked, return false.
if ($this->_vars->get('submitbutton') == _("Cancel")) {
Horde::url($GLOBALS['prefs']->getValue('defaultview') . '.php', true)
->redirect();
}
if (!($this->_resource->hasPermission($GLOBALS['registry']->getAuth(), Horde_Perms::DELETE))) {
throw new Kronolith_Exception(_("Permission denied"));
}
// Delete the resource.
try {
Kronolith::getDriver('Resource')->delete($this->_resource);
} catch (Exception $e) {
throw new Kronolith_Exception(sprintf(_("Unable to delete \"%s\": %s"), $this->_resource->get('name'), $e->getMessage()));
}
}
}
kronolith-4.2.13/lib/Form/DeleteResourceGroup.php 0000664 0000765 0000024 00000004052 12654566222 016656 0 ustar
* @author Michael J. Rubinsky
* @package Kronolith
*/
class Kronolith_Form_DeleteResourceGroup extends Horde_Form
{
/**
* Resource group being deleted.
*
* @var Kronolith_Resource_Group
*/
protected $_resource;
public function __construct($vars, $resource)
{
$this->_resource = $resource;
parent::__construct($vars, sprintf(_("Delete %s"), $resource->get('name')));
$this->addHidden('', 'c', 'text', true);
$this->addVariable(
sprintf(_("Really delete the resource \"%s\"? This cannot be undone and all data on this resource will be permanently removed."), htmlspecialchars($this->_resource->get('name'))),
'desc', 'description', false);
$this->setButtons(array(
array('class' => 'horde-delete', 'value' => _("Delete")),
array('class' => 'horde-cancel', 'value' => _("Cancel")),
));
}
/**
* @throws Kronolith_Exception
*/
public function execute()
{
if ($this->_vars->get('submitbutton') == _("Cancel")) {
Horde::url($GLOBALS['prefs']->getValue('defaultview') . '.php', true)
->redirect();
}
if (!($this->_resource->hasPermission($GLOBALS['registry']->getAuth(), Horde_Perms::DELETE))) {
throw new Kronolith_Exception(_("Permission denied"));
}
// Delete the resource.
try {
Kronolith::getDriver('Resource')->delete($this->_resource);
} catch (Exception $e) {
throw new Kronolith_Exception(sprintf(_("Unable to delete \"%s\": %s"), $this->_resource->get('name'), $e->getMessage()));
}
}
}
kronolith-4.2.13/lib/Form/EditCalendar.php 0000664 0000765 0000024 00000016752 12654566222 015260 0 ustar
* @package Kronolith
*/
class Kronolith_Form_EditCalendar extends Horde_Form
{
/**
* Calendar being edited.
*
* @var Horde_Share_Object
*/
protected $_calendar;
public function __construct($vars, $calendar)
{
global $conf, $injector, $registry;
$this->_calendar = $calendar;
$owner = $calendar->get('owner') == $registry->getAuth() ||
(is_null($calendar->get('owner')) &&
$registry->isAdmin());
parent::__construct(
$vars,
$owner
? sprintf(_("Edit %s"), $calendar->get('name'))
: $calendar->get('name')
);
$this->addHidden('', 'c', 'text', true);
$this->addVariable(_("Name"), 'name', 'text', true);
if (!$owner) {
$v = $this->addVariable(_("Owner"), 'owner', 'text', false);
$owner_name = $injector
->getInstance('Horde_Core_Factory_Identity')
->create($calendar->get('owner'))
->getValue('fullname');
if (trim($owner_name) == '') {
$owner_name = $calendar->get('owner');
}
$v->setDefault($owner_name ? $owner_name : _("System"));
}
$this->addVariable(_("Color"), 'color', 'colorpicker', false);
if ($registry->isAdmin()) {
$this->addVariable(_("System Calendar"), 'system', 'boolean', false, false, _("System calendars don't have an owner. Only administrators can change the calendar settings and permissions."));
}
$this->addVariable(_("Description"), 'description', 'longtext', false, false, null, array(4, 60));
$this->addVariable(_("Tags"), 'tags', 'Kronolith:KronolithTags', false);
/* Display URL. */
$url = Horde::url('month.php', true, -1)
->add('display_cal', $calendar->getName());
$this->addVariable(
_("Display URL"), '', 'link', false, false, null,
array(array(
'url' => $url,
'text' => $url,
'title' => _("Click or copy this URL to display this calendar"),
'target' => '_blank')
)
);
/* Subscription URLs. */
$url = $registry->get('webroot', 'horde');
if (isset($conf['urls']['pretty']) &&
$conf['urls']['pretty'] == 'rewrite') {
$webdavUrl = $url . '/rpc/kronolith/';
$caldavUrl = $url . '/rpc/calendars/';
$accountUrl = $url . '/rpc/';
} else {
$webdavUrl = $url . '/rpc.php/kronolith/';
$caldavUrl = $url . '/rpc.php/calendars/';
$accountUrl = $url . '/rpc.php/';
}
try {
$accountUrl = Horde::url($accountUrl, true, -1)
. 'principals/' . $registry->convertUsername($registry->getAuth(), false) . '/';
$caldavUrl = Horde::url($caldavUrl, true, -1)
. $registry->convertUsername($registry->getAuth(), false)
. '/'
. $injector->getInstance('Horde_Dav_Storage')->getExternalCollectionId($calendar->getName(), 'calendar')
. '/';
$this->addVariable(
_("CalDAV Subscription URL"), '', 'link', false, false, null,
array(array(
'url' => $caldavUrl,
'text' => $caldavUrl,
'title' => _("Copy this URL to a CalDAV client to subscribe to this calendar"),
'target' => '_blank')
)
);
$this->addVariable(
_("CalDAV Account URL"), '', 'link', false, false, null,
array(array(
'url' => $accountUrl,
'text' => $accountUrl,
'title' => _("Copy this URL to a CalDAV client to subscribe to all your calendars"),
'target' => '_blank')
)
);
} catch (Horde_Exception $e) {
}
$webdavUrl = Horde::url($webdavUrl, true, -1)
. ($calendar->get('owner')
? $registry->convertUsername($calendar->get('owner'), false)
: '-system-')
. '/' . $calendar->getName() . '.ics';
$this->addVariable(
_("WebDAV/ICS Subscription URL"), '', 'link', false, false, null,
array(array(
'url' => $webdavUrl,
'text' => $webdavUrl,
'title' => _("Copy this URL to a WebDAV or ICS client to subscribe to this calendar"),
'target' => '_blank')
)
);
/* Feed URL. */
$url = Kronolith::feedUrl($calendar->getName());
$this->addVariable(
_("Feed URL"), '', 'link', false, false, null,
array(array(
'url' => $url,
'text' => $url,
'title' => _("Copy this URL to a news feed reader to subscribe to this calendar"),
'target' => '_blank')
)
);
/* Embed code. */
$v = $this->addVariable(
_("Embed code"), '', 'longtext', false, false,
_("To embed this calendar in another website, use the code above."),
array(4, 60));
$v->setHelp('embed');
$v->setDefault(Kronolith::embedCode($calendar->getName()));
/* Permissions link. */
if (empty($conf['share']['no_sharing']) && $owner) {
$url = Horde::url('perms.php')->add('share', $calendar->getName());
$this->addVariable(
'', '', 'link', false, false, null,
array(array(
'url' => $url,
'text' => _("Change Permissions"),
'onclick' => Horde::popupJs(
$url,
array('params' => array('urlencode' => true)))
. 'return false;',
'class' => 'horde-button',
'target' => '_blank')
)
);
}
$this->setButtons(array(
_("Save"),
array('class' => 'horde-delete', 'value' => _("Delete")),
array('class' => 'horde-cancel', 'value' => _("Cancel"))
));
}
/**
* @throws Kronolith_Exception
*/
public function execute()
{
switch ($this->_vars->submitbutton) {
case _("Save"):
$info = array();
foreach (array('name', 'color', 'description', 'tags', 'system') as $key) {
$info[$key] = $this->_vars->get($key);
}
Kronolith::updateShare($this->_calendar, $info);
break;
case _("Delete"):
Horde::url('calendars/delete.php')
->add('c', $this->_vars->c)
->redirect();
break;
case _("Cancel"):
Horde::url($GLOBALS['prefs']->getValue('defaultview') . '.php', true)
->redirect();
break;
}
}
public function renderActive()
{
return parent::renderActive(
$this->getRenderer(array('varrenderer_driver' => array('kronolith', 'kronolith'))),
$this->_vars);
}
}
kronolith-4.2.13/lib/Form/EditRemoteCalendar.php 0000664 0000765 0000024 00000004245 12654566222 016426 0 ustar
* @package Kronolith
*/
class Kronolith_Form_EditRemoteCalendar extends Horde_Form
{
public function __construct($vars, $remote_calendar)
{
parent::__construct($vars, sprintf(_("Edit %s"), $remote_calendar['name']));
$this->addHidden('', 'url', 'text', true);
$this->addVariable(_("Name"), 'name', 'text', true);
$v = $this->addVariable(_("URL"), 'new_url', 'text', true);
$v->setDefault($vars->get('url'));
$this->addVariable(_("Username"), 'user', 'text', false);
$this->addVariable(_("Password"), 'password', 'password', false);
$this->addVariable(_("Color"), 'color', 'colorpicker', false);
$this->addVariable(_("Description"), 'desc', 'longtext', false, false, null, array(4, 60));
$this->setButtons(array(
_("Save"),
array('class' => 'horde-delete', 'value' => _("Unsubscribe")),
array('class' => 'horde-cancel', 'value' => _("Cancel"))
));
}
/**
* @throws Kronolith_Exception
*/
public function execute()
{
switch ($this->_vars->submitbutton) {
case _("Save"):
$info = array();
foreach (array('name', 'new_url', 'user', 'password', 'color', 'desc') as $key) {
$info[$key == 'new_url' ? 'url' : $key] = $this->_vars->get($key);
}
Kronolith::subscribeRemoteCalendar($info, trim($this->_vars->get('url')));
break;
case _("Unsubscribe"):
Horde::url('calendars/remote_unsubscribe.php')
->add('url', $this->_vars->url)
->redirect();
break;
case _("Cancel"):
Horde::url($GLOBALS['prefs']->getValue('defaultview') . '.php', true)
->redirect();
break;
}
}
}
kronolith-4.2.13/lib/Form/EditResource.php 0000664 0000765 0000024 00000012616 12654566222 015331 0 ustar
* @author Michael J. Rubinsky
* @package Kronolith
*/
class Kronolith_Form_EditResource extends Horde_Form
{
/**
* Resource being edited.
*
* @var Kronolith_Resource_Single
*/
protected $_resource;
/**
* @throws Kronolith_Exception
*/
public function __construct($vars, $resource)
{
$this->_resource = $resource;
parent::__construct($vars, sprintf(_("Edit %s"), $resource->get('name')));
$responses = array(Kronolith_Resource::RESPONSETYPE_ALWAYS_ACCEPT => _("Always Accept"),
Kronolith_Resource::RESPONSETYPE_ALWAYS_DECLINE => _("Always Decline"),
Kronolith_Resource::RESPONSETYPE_AUTO => _("Automatically"),
Kronolith_Resource::RESPONSETYPE_MANUAL => _("Manual"),
Kronolith_Resource::RESPONSETYPE_NONE => _("None"));
/* Get a list of available resource groups */
$groups = Kronolith::getDriver('Resource')
->listResources(Horde_Perms::READ,
array('type' => Kronolith_Resource::TYPE_GROUP));
$enum = array();
foreach ($groups as $id => $group) {
$enum[$id] = $group->get('name');
}
$this->addHidden('', 'c', 'text', true);
$this->addVariable(_("Name"), 'name', 'text', true);
$this->addVariable(_("Email"), 'email', 'email', false);
$this->addVariable(_("Description"), 'description', 'longtext', false, false, null, array(4, 60));
$this->addVariable(_("Response type"), 'responsetype', 'enum', true, false, null, array('enum' => $responses));
$this->addVariable(_("Groups"), 'category', 'multienum', false, false, null, array('enum' => $enum));
/* Display URL. */
$url = Horde::url('month.php', true, -1)
->add('display_cal', $resource->get('calendar'));
$this->addVariable(
_("Display URL"), '', 'link', false, false, null,
array(array(
'url' => $url,
'text' => $url,
'title' => _("Click or copy this URL to display the calendar of this resource"),
'target' => '_blank')
)
);
$this->setButtons(array(
_("Save"),
array('class' => 'horde-delete', 'value' => _("Delete")),
array('class' => 'horde-cancel', 'value' => _("Cancel"))
));
}
/**
* @throws Kronolith_Exception
*/
public function execute()
{
switch ($this->_vars->submitbutton) {
case _("Save"):
$new_name = $this->_vars->get('name');
$this->_resource->set('name', $new_name);
$this->_resource->set('description', $this->_vars->get('description'));
$this->_resource->set('response_type', $this->_vars->get('responsetype'));
$this->_resource->set('email', $this->_vars->get('email'));
/* Update group memberships */
$driver = Kronolith::getDriver('Resource');
$existing_groups = $driver->getGroupMemberships($this->_resource->getId());
$new_groups = $this->_vars->get('category');
$new_groups = (is_null($new_groups) ? array() : $new_groups);
foreach ($existing_groups as $gid) {
$i = array_search($gid, $new_groups);
if ($i === false) {
// No longer in this group
$group = $driver->getResource($gid);
$members = $group->get('members');
$idx = array_search($this->_resource->getId(), $members);
if ($idx !== false) {
unset($members[$idx]);
reset($members);
$group->set('members', $members);
$group->save();
}
} else {
// We know it's already in the group, remove it so we don't
// have to check/add it again later.
unset($new_groups[$i]);
}
}
reset($new_groups);
foreach ($new_groups as $gid) {
$group = $driver->getResource($gid);
$members = $group->get('members');
$members[] = $this->_resource->getId();
$group->set('members', $members);
$group->save();
}
try {
$this->_resource->save();
} catch (Exception $e) {
throw new Kronolith_Exception(sprintf(_("Unable to save resource \"%s\": %s"), $new_name, $e->getMessage()));
}
return $this->_resource;
case _("Delete"):
Horde::url('resources/delete.php')
->add('c', $this->_vars->c)
->redirect();
break;
case _("Cancel"):
Horde::url($GLOBALS['prefs']->getValue('defaultview') . '.php', true)
->redirect();
break;
}
}
}
kronolith-4.2.13/lib/Form/EditResourceGroup.php 0000664 0000765 0000024 00000005262 12654566222 016345 0 ustar
* @author Michael J. Rubinsky
* @package Kronolith
*/
class Kronolith_Form_EditResourceGroup extends Horde_Form
{
/**
* Resource group being edited.
*
* @var Kronolith_Resource_Single
*/
protected $_resource;
/**
* @throws Kronolith_Exception
*/
public function __construct($vars, $resource)
{
$this->_resource = $resource;
parent::__construct($vars, sprintf(_("Edit %s"), $resource->get('name')));
$resources = Kronolith::getDriver('Resource')->listResources(Horde_Perms::READ, array('type' => Kronolith_Resource::TYPE_SINGLE));
$enum = array();
foreach ($resources as $r) {
$enum[$r->getId()] = htmlspecialchars($r->get('name'));
}
$this->addHidden('', 'c', 'text', true);
$this->addVariable(_("Name"), 'name', 'text', true);
$this->addVariable(_("Description"), 'description', 'longtext', false, false, null, array(4, 60));
$this->addVariable(_("Resources"), 'members', 'multienum', false, false, null, array('enum' => $enum));
$this->setButtons(array(
_("Save"),
array('class' => 'horde-delete', 'value' => _("Delete")),
array('class' => 'horde-cancel', 'value' => _("Cancel"))
));
}
/**
* @throws Kronolith_Exception
*/
public function execute()
{
switch ($this->_vars->submitbutton) {
case _("Save"):
$new_name = $this->_vars->get('name');
$this->_resource->set('name', $new_name);
$this->_resource->set('description', $this->_vars->get('description'));
$this->_resource->set('members', $this->_vars->get('members'));
try {
$this->_resource->save();
} catch (Exception $e) {
throw new Kronolith_Exception(sprintf(_("Unable to save resource \"%s\": %s"), $new_name, $e->getMessage()));
}
return $this->_resource;
case _("Delete"):
Horde::url('resources/groups/delete.php')
->add('c', $this->_vars->c)
->redirect();
break;
case _("Cancel"):
Horde::url($GLOBALS['prefs']->getValue('defaultview') . '.php', true)
->redirect();
break;
}
}
}
kronolith-4.2.13/lib/Form/SubscribeRemoteCalendar.php 0000664 0000765 0000024 00000003051 12654566222 017454 0 ustar
* @package Kronolith
*/
class Kronolith_Form_SubscribeRemoteCalendar extends Horde_Form
{
public function __construct($vars)
{
parent::__construct($vars, _("Subscribe to a Remote Calendar"));
$this->addVariable(_("Name"), 'name', 'text', true);
$v = $this->addVariable(_("Color"), 'color', 'colorpicker', false);
$color = '#';
for ($i = 0; $i < 3; $i++) {
$color .= sprintf('%02x', mt_rand(0, 255));
}
$v->setDefault($color);
$this->addVariable(_("URL"), 'url', 'text', true);
$this->addVariable(_("Description"), 'desc', 'longtext', false, false, null, array(4, 60));
$this->addVariable(_("Username"), 'user', 'text', false);
$this->addVariable(_("Password"), 'password', 'password', false);
$this->setButtons(array(_("Subscribe")));
}
/**
* @throws Kronolith_Exception
*/
public function execute()
{
$info = array();
foreach (array('name', 'url', 'user', 'password', 'color', 'desc') as $key) {
$info[$key] = $this->_vars->get($key);
}
Kronolith::subscribeRemoteCalendar($info);
}
}
kronolith-4.2.13/lib/Form/UnsubscribeRemoteCalendar.php 0000664 0000765 0000024 00000002653 12654566222 020026 0 ustar
* @package Kronolith
*/
class Kronolith_Form_UnsubscribeRemoteCalendar extends Horde_Form
{
public function __construct($vars, $calendar)
{
parent::__construct($vars, sprintf(_("Unsubscribe from %s"), $calendar['name']));
$this->addHidden('', 'url', 'text', true);
$this->addVariable(sprintf(_("Really unsubscribe from the calendar \"%s\" (%s)?"), htmlspecialchars($calendar['name']), htmlspecialchars($calendar['url'])), 'desc', 'description', false);
$this->setButtons(array(
array('class' => 'horde-delete', 'value' => _("Unsubscribe")),
array('class' => 'horde-cancel', 'value' => _("Cancel"))
));
}
/**
* @throws Kronolith_Exception
*/
public function execute()
{
if ($this->_vars->get('submitbutton') == _("Cancel")) {
Horde::url($GLOBALS['prefs']->getValue('defaultview') . '.php', true)
->redirect();
}
return Kronolith::unsubscribeRemoteCalendar($this->_vars->get('url'));
}
}
kronolith-4.2.13/lib/FreeBusy/View/Day.php 0000664 0000765 0000024 00000003732 12654566222 015203 0 ustar
* @author Jan Schneider
* @package Kronolith
*/
class Kronolith_FreeBusy_View_Day extends Kronolith_FreeBusy_View
{
public $view = 'day';
protected function _title()
{
global $prefs;
$prev = new Horde_Date($this->_start);
$prev->mday--;
$next = new Horde_Date($this->_start);
$next->mday++;
return Horde::url('#')->link(array('title' => _("Previous Day"), 'onclick' => 'return switchDate(' . $prev->dateString() . ');'))
. Horde::img('nav/left.png', '<')
. ''
. $this->_start->strftime($prefs->getValue('date_format'))
. Horde::url('#')->link(array('title' => _("Next Day"), 'onclick' => 'return switchDate(' . $next->dateString() . ');'))
. Horde::img('nav/right.png', '>')
. '';
}
protected function _hours()
{
global $prefs;
$hours_html = '';
$width = round(100 / ($this->_endHour - $this->_startHour + 1));
$start = new Horde_Date($this->_start);
$end = new Horde_Date($this->_start);
$end->min = 59;
for ($i = $this->_startHour; $i < $this->_endHour; $i++) {
$start->hour = $end->hour = $i;
$this->_timeBlocks[] = array(clone $start, clone $end);
$hours_html .= '' . $start->strftime($prefs->getValue('twentyFour') ? '%H:00' : '%I:00') . ' | ';
}
return $hours_html;
}
protected function _render(Horde_Date $day = null)
{
$this->_start = new Horde_Date($day);
$this->_start->hour = $this->_startHour;
$this->_end = new Horde_Date($this->_start);
$this->_end->hour = $this->_endHour;
}
}
kronolith-4.2.13/lib/FreeBusy/View/Month.php 0000664 0000765 0000024 00000007451 12654566222 015555 0 ustar
* @author Jan Schneider
* @package Kronolith
*/
class Kronolith_FreeBusy_View_Month extends Kronolith_FreeBusy_View
{
/**
* This view type
*
* @var string
*/
public $view = 'month';
/**
* Number of days
*
* @var integer
*/
protected $_days = 30;
protected function _title()
{
$end = new Horde_Date($this->_start);
$end->mday += $this->_days - 1;
$prev = new Horde_Date($this->_start);
$prev->month--;
$next = new Horde_Date($this->_start);
$next->month++;
return Horde::url('#')->link(array('title' => _("Previous Month"), 'onclick' => 'return switchDate(' . $prev->dateString() . ');'))
. Horde::img('nav/left.png', '<')
. ''
. $this->_start->strftime('%B %Y')
. Horde::url('#')->link(array('title' => _("Next Month"), 'onclick' => 'return switchDate(' . $next->dateString() . ');'))
. Horde::img('nav/right.png', '>')
. '';
}
protected function _hours()
{
$hours_html = '';
$dayWidth = round(100 / $this->_days);
$week = Date_Calc::weekOfYear(1, $this->_start->month, $this->_start->year);
$span = (7 - $week) % 7 + 1;
$span_left = $this->_days;
$t = new Horde_Date($this->_start);
while ($span_left > 0) {
$span_left -= $span;
$week_label = Horde::url('#')->link(array('onclick' => 'return switchDateView(\'Week\',' . $t->dateString() . ');'))
. ("Week") . ' ' . $week . '';
$hours_html .= sprintf('%s | ',
$span, $dayWidth, $week_label);
$week++;
$t->mday += 7;
$span = min($span_left, 7);
}
$hours_html .= ' |