Changeset View
Changeset View
Standalone View
Standalone View
plugins/calendar/drivers/calendar_driver.php
Show First 20 Lines • Show All 88 Lines • ▼ Show 20 Lines | |||||
* ); | * ); | ||||
*/ | */ | ||||
/** | /** | ||||
* Interface definition for calendar driver classes | * Interface definition for calendar driver classes | ||||
*/ | */ | ||||
abstract class calendar_driver | abstract class calendar_driver | ||||
{ | { | ||||
const FILTER_ALL = 0; | const FILTER_ALL = 0; | ||||
const FILTER_WRITEABLE = 1; | const FILTER_WRITEABLE = 1; | ||||
const FILTER_INSERTABLE = 2; | const FILTER_INSERTABLE = 2; | ||||
const FILTER_ACTIVE = 4; | const FILTER_ACTIVE = 4; | ||||
const FILTER_PERSONAL = 8; | const FILTER_PERSONAL = 8; | ||||
const FILTER_PRIVATE = 16; | const FILTER_PRIVATE = 16; | ||||
const FILTER_CONFIDENTIAL = 32; | const FILTER_CONFIDENTIAL = 32; | ||||
const FILTER_SHARED = 64; | const FILTER_SHARED = 64; | ||||
const BIRTHDAY_CALENDAR_ID = '__bdays__'; | const BIRTHDAY_CALENDAR_ID = '__bdays__'; | ||||
// features supported by backend | // features supported by backend | ||||
public $alarms = false; | public $alarms = false; | ||||
public $attendees = false; | public $attendees = false; | ||||
public $freebusy = false; | public $freebusy = false; | ||||
public $attachments = false; | public $attachments = false; | ||||
public $undelete = false; | public $undelete = false; | ||||
public $history = false; | public $history = false; | ||||
public $categoriesimmutable = false; | public $alarm_types = ['DISPLAY']; | ||||
public $alarm_types = array('DISPLAY'); | |||||
public $alarm_absolute = true; | public $alarm_absolute = true; | ||||
public $categoriesimmutable = false; | |||||
public $last_error; | public $last_error; | ||||
protected $default_categories = array( | protected $default_categories = [ | ||||
'Personal' => 'c0c0c0', | 'Personal' => 'c0c0c0', | ||||
'Work' => 'ff0000', | 'Work' => 'ff0000', | ||||
'Family' => '00ff00', | 'Family' => '00ff00', | ||||
'Holiday' => 'ff6600', | 'Holiday' => 'ff6600', | ||||
); | ]; | ||||
/** | /** | ||||
* Get a list of available calendars from this source | * Get a list of available calendars from this source | ||||
* | * | ||||
* @param integer Bitmask defining filter criterias. | * @param int $filter Bitmask defining filter criterias. | ||||
* See FILTER_* constants for possible values. | * See FILTER_* constants for possible values. | ||||
* | |||||
* @return array List of calendars | * @return array List of calendars | ||||
*/ | */ | ||||
abstract function list_calendars($filter = 0); | abstract function list_calendars($filter = 0); | ||||
/** | /** | ||||
* Create a new calendar assigned to the current user | * Create a new calendar assigned to the current user | ||||
* | * | ||||
* @param array Hash array with calendar properties | * @param array $prop Hash array with calendar properties | ||||
* name: Calendar name | * name: Calendar name | ||||
* color: The color of the calendar | * color: The color of the calendar | ||||
* showalarms: True if alarms are enabled | * showalarms: True if alarms are enabled | ||||
* | |||||
* @return mixed ID of the calendar on success, False on error | * @return mixed ID of the calendar on success, False on error | ||||
*/ | */ | ||||
abstract function create_calendar($prop); | abstract function create_calendar($prop); | ||||
/** | /** | ||||
* Update properties of an existing calendar | * Update properties of an existing calendar | ||||
* | * | ||||
* @param array Hash array with calendar properties | * @param array $prop Hash array with calendar properties | ||||
* id: Calendar Identifier | * id: Calendar Identifier | ||||
* name: Calendar name | * name: Calendar name | ||||
* color: The color of the calendar | * color: The color of the calendar | ||||
* showalarms: True if alarms are enabled (if supported) | * showalarms: True if alarms are enabled (if supported) | ||||
* @return boolean True on success, Fales on failure | * | ||||
* @return bool True on success, Fales on failure | |||||
*/ | */ | ||||
abstract function edit_calendar($prop); | abstract function edit_calendar($prop); | ||||
/** | /** | ||||
* Set active/subscribed state of a calendar | * Set active/subscribed state of a calendar | ||||
* | * | ||||
* @param array Hash array with calendar properties | * @param array $prop Hash array with calendar properties | ||||
* id: Calendar Identifier | * id: Calendar Identifier | ||||
* active: True if calendar is active, false if not | * active: True if calendar is active, false if not | ||||
* @return boolean True on success, Fales on failure | * | ||||
* @return bool True on success, Fales on failure | |||||
*/ | */ | ||||
abstract function subscribe_calendar($prop); | abstract function subscribe_calendar($prop); | ||||
/** | /** | ||||
* Delete the given calendar with all its contents | * Delete the given calendar with all its contents | ||||
* | * | ||||
* @param array Hash array with calendar properties | * @param array $prop Hash array with calendar properties | ||||
* id: Calendar Identifier | * id: Calendar Identifier | ||||
* @return boolean True on success, Fales on failure | * | ||||
* @return bool True on success, Fales on failure | |||||
*/ | */ | ||||
abstract function delete_calendar($prop); | abstract function delete_calendar($prop); | ||||
/** | /** | ||||
* Search for shared or otherwise not listed calendars the user has access | * Search for shared or otherwise not listed calendars the user has access | ||||
* | * | ||||
* @param string Search string | * @param string $query Search string | ||||
* @param string Section/source to search | * @param string $source Section/source to search | ||||
* | |||||
* @return array List of calendars | * @return array List of calendars | ||||
*/ | */ | ||||
abstract function search_calendars($query, $source); | abstract function search_calendars($query, $source); | ||||
/** | /** | ||||
* Add a single event to the database | * Add a single event to the database | ||||
* | * | ||||
* @param array Hash array with event properties (see header of this file) | * @param array $event Hash array with event properties (see header of this file) | ||||
* | |||||
* @return mixed New event ID on success, False on error | * @return mixed New event ID on success, False on error | ||||
*/ | */ | ||||
abstract function new_event($event); | abstract function new_event($event); | ||||
/** | /** | ||||
* Update an event entry with the given data | * Update an event entry with the given data | ||||
* | * | ||||
* @param array Hash array with event properties (see header of this file) | * @param array $event Hash array with event properties (see header of this file) | ||||
* @return boolean True on success, False on error | * | ||||
* @return bool True on success, False on error | |||||
*/ | */ | ||||
abstract function edit_event($event); | abstract function edit_event($event); | ||||
/** | /** | ||||
* Extended event editing with possible changes to the argument | * Extended event editing with possible changes to the argument | ||||
* | * | ||||
* @param array Hash array with event properties | * @param array &$event Hash array with event properties | ||||
* @param string New participant status | * @param string $status New participant status | ||||
* @param array List of hash arrays with updated attendees | * @param array $attendees List of hash arrays with updated attendees | ||||
* @return boolean True on success, False on error | * | ||||
* @return bool True on success, False on error | |||||
*/ | */ | ||||
public function edit_rsvp(&$event, $status, $attendees) | public function edit_rsvp(&$event, $status, $attendees) | ||||
{ | { | ||||
return $this->edit_event($event); | return $this->edit_event($event); | ||||
} | } | ||||
/** | /** | ||||
* Update the participant status for the given attendee | * Update the participant status for the given attendee | ||||
* | * | ||||
* @param array Hash array with event properties | * @param array &$event Hash array with event properties | ||||
* @param array List of hash arrays each represeting an updated attendee | * @param array $attendees List of hash arrays each represeting an updated attendee | ||||
* @return boolean True on success, False on error | * | ||||
* @return bool True on success, False on error | |||||
*/ | */ | ||||
public function update_attendees(&$event, $attendees) | public function update_attendees(&$event, $attendees) | ||||
{ | { | ||||
return $this->edit_event($event); | return $this->edit_event($event); | ||||
} | } | ||||
/** | /** | ||||
* Move a single event | * Move a single event | ||||
* | * | ||||
* @param array Hash array with event properties: | * @param array $event Hash array with event properties: | ||||
* id: Event identifier | * id: Event identifier | ||||
* start: Event start date/time as DateTime object | * start: Event start date/time as DateTime object | ||||
* end: Event end date/time as DateTime object | * end: Event end date/time as DateTime object | ||||
* allday: Boolean flag if this is an all-day event | * allday: Boolean flag if this is an all-day event | ||||
* @return boolean True on success, False on error | * | ||||
* @return bool True on success, False on error | |||||
*/ | */ | ||||
abstract function move_event($event); | abstract function move_event($event); | ||||
/** | /** | ||||
* Resize a single event | * Resize a single event | ||||
* | * | ||||
* @param array Hash array with event properties: | * @param array $event Hash array with event properties: | ||||
* id: Event identifier | * id: Event identifier | ||||
* start: Event start date/time as DateTime object with timezone | * start: Event start date/time as DateTime object with timezone | ||||
* end: Event end date/time as DateTime object with timezone | * end: Event end date/time as DateTime object with timezone | ||||
* @return boolean True on success, False on error | * | ||||
* @return bool True on success, False on error | |||||
*/ | */ | ||||
abstract function resize_event($event); | abstract function resize_event($event); | ||||
/** | /** | ||||
* Remove a single event from the database | * Remove a single event from the database | ||||
* | * | ||||
* @param array Hash array with event properties: | * @param array $event Hash array with event properties: | ||||
* id: Event identifier | * id: Event identifier | ||||
* @param boolean Remove event irreversible (mark as deleted otherwise, | * @param bool $force Remove event irreversible (mark as deleted otherwise, | ||||
* if supported by the backend) | * if supported by the backend) | ||||
* | * | ||||
* @return boolean True on success, False on error | * @return bool True on success, False on error | ||||
*/ | */ | ||||
abstract function remove_event($event, $force = true); | abstract function remove_event($event, $force = true); | ||||
/** | /** | ||||
* Restores a single deleted event (if supported) | * Restores a single deleted event (if supported) | ||||
* | * | ||||
* @param array Hash array with event properties: | * @param array $event Hash array with event properties: | ||||
* id: Event identifier | * id: Event identifier | ||||
* | * | ||||
* @return boolean True on success, False on error | * @return bool True on success, False on error | ||||
*/ | */ | ||||
public function restore_event($event) | public function restore_event($event) | ||||
{ | { | ||||
return false; | return false; | ||||
} | } | ||||
/** | /** | ||||
* Return data of a single event | * Return data of a single event | ||||
* | * | ||||
* @param mixed UID string or hash array with event properties: | * @param mixed $event UID string or hash array with event properties: | ||||
* id: Event identifier | * id: Event identifier | ||||
* uid: Event UID | * uid: Event UID | ||||
* _instance: Instance identifier in combination with uid (optional) | * _instance: Instance identifier in combination with uid (optional) | ||||
* calendar: Calendar identifier (optional) | * calendar: Calendar identifier (optional) | ||||
* @param integer Bitmask defining the scope to search events in. | * @param int $scope Bitmask defining the scope to search events in. | ||||
* See FILTER_* constants for possible values. | * See FILTER_* constants for possible values. | ||||
* @param boolean If true, recurrence exceptions shall be added | * @param bool $full If true, recurrence exceptions shall be added | ||||
* | * | ||||
* @return array Event object as hash array | * @return array Event object as hash array | ||||
*/ | */ | ||||
abstract function get_event($event, $scope = 0, $full = false); | abstract function get_event($event, $scope = 0, $full = false); | ||||
/** | /** | ||||
* Get events from source. | * Get events from source. | ||||
* | * | ||||
* @param integer Date range start (unix timestamp) | * @param int $start Date range start (unix timestamp) | ||||
* @param integer Date range end (unix timestamp) | * @param int $end Date range end (unix timestamp) | ||||
* @param string Search query (optional) | * @param string $query Search query (optional) | ||||
* @param mixed List of calendar IDs to load events from (either as array or comma-separated string) | * @param mixed $calendars List of calendar IDs to load events from (either as array or comma-separated string) | ||||
* @param boolean Include virtual/recurring events (optional) | * @param bool $virtual Include virtual/recurring events (optional) | ||||
* @param integer Only list events modified since this time (unix timestamp) | * @param int $modifiedsince Only list events modified since this time (unix timestamp) | ||||
* | |||||
* @return array A list of event objects (see header of this file for struct of an event) | * @return array A list of event objects (see header of this file for struct of an event) | ||||
*/ | */ | ||||
abstract function load_events($start, $end, $query = null, $calendars = null, $virtual = 1, $modifiedsince = null); | abstract function load_events($start, $end, $query = null, $calendars = null, $virtual = 1, $modifiedsince = null); | ||||
/** | /** | ||||
* Get number of events in the given calendar | * Get number of events in the given calendar | ||||
* | * | ||||
* @param mixed List of calendar IDs to count events (either as array or comma-separated string) | * @param mixed $calendars List of calendar IDs to count events (either as array or comma-separated string) | ||||
* @param integer Date range start (unix timestamp) | * @param int $start Date range start (unix timestamp) | ||||
* @param integer Date range end (unix timestamp) | * @param int $end Date range end (unix timestamp) | ||||
* | |||||
* @return array Hash array with counts grouped by calendar ID | * @return array Hash array with counts grouped by calendar ID | ||||
*/ | */ | ||||
abstract function count_events($calendars, $start, $end = null); | abstract function count_events($calendars, $start, $end = null); | ||||
/** | /** | ||||
* Get a list of pending alarms to be displayed to the user | * Get a list of pending alarms to be displayed to the user | ||||
* | * | ||||
* @param integer Current time (unix timestamp) | * @param int $time Current time (unix timestamp) | ||||
* @param mixed List of calendar IDs to show alarms for (either as array or comma-separated string) | * @param mixed $calendars List of calendar IDs to show alarms for (either as array or comma-separated string) | ||||
* | |||||
* @return array A list of alarms, each encoded as hash array: | * @return array A list of alarms, each encoded as hash array: | ||||
* id: Event identifier | * id: Event identifier | ||||
* uid: Unique identifier of this event | * uid: Unique identifier of this event | ||||
* start: Event start date/time as DateTime object | * start: Event start date/time as DateTime object | ||||
* end: Event end date/time as DateTime object | * end: Event end date/time as DateTime object | ||||
* allday: Boolean flag if this is an all-day event | * allday: Boolean flag if this is an all-day event | ||||
* title: Event title/summary | * title: Event title/summary | ||||
* location: Location string | * location: Location string | ||||
*/ | */ | ||||
abstract function pending_alarms($time, $calendars = null); | abstract function pending_alarms($time, $calendars = null); | ||||
/** | /** | ||||
* (User) feedback after showing an alarm notification | * (User) feedback after showing an alarm notification | ||||
* This should mark the alarm as 'shown' or snooze it for the given amount of time | * This should mark the alarm as 'shown' or snooze it for the given amount of time | ||||
* | * | ||||
* @param string Event identifier | * @param string $event_id Event identifier | ||||
* @param integer Suspend the alarm for this number of seconds | * @param int $snooze Suspend the alarm for this number of seconds | ||||
*/ | */ | ||||
abstract function dismiss_alarm($event_id, $snooze = 0); | abstract function dismiss_alarm($event_id, $snooze = 0); | ||||
/** | /** | ||||
* Check the given event object for validity | * Check the given event object for validity | ||||
* | * | ||||
* @param array Event object as hash array | * @param array $event Event object as hash array | ||||
* | |||||
* @return boolean True if valid, false if not | * @return boolean True if valid, false if not | ||||
*/ | */ | ||||
public function validate($event) | public function validate($event) | ||||
{ | { | ||||
$valid = true; | $valid = true; | ||||
if (!is_object($event['start']) || !is_a($event['start'], 'DateTime')) | if (empty($event['start']) || !is_object($event['start']) || !is_a($event['start'], 'DateTime')) { | ||||
$valid = false; | $valid = false; | ||||
if (!is_object($event['end']) || !is_a($event['end'], 'DateTime')) | } | ||||
if (empty($event['end']) || !is_object($event['end']) || !is_a($event['end'], 'DateTime')) { | |||||
$valid = false; | $valid = false; | ||||
} | |||||
return $valid; | return $valid; | ||||
} | } | ||||
/** | /** | ||||
* Get list of event's attachments. | * Get list of event's attachments. | ||||
* Drivers can return list of attachments as event property. | * Drivers can return list of attachments as event property. | ||||
* If they will do not do this list_attachments() method will be used. | * If they will do not do this list_attachments() method will be used. | ||||
* | * | ||||
* @param array $event Hash array with event properties: | * @param array $event Hash array with event properties: | ||||
* id: Event identifier | * id: Event identifier | ||||
* calendar: Calendar identifier | * calendar: Calendar identifier | ||||
* | * | ||||
* @return array List of attachments, each as hash array: | * @return array List of attachments, each as hash array: | ||||
* id: Attachment identifier | * id: Attachment identifier | ||||
* name: Attachment name | * name: Attachment name | ||||
* mimetype: MIME content type of the attachment | * mimetype: MIME content type of the attachment | ||||
* size: Attachment size | * size: Attachment size | ||||
*/ | */ | ||||
public function list_attachments($event) { } | public function list_attachments($event) { } | ||||
/** | /** | ||||
* Get attachment properties | * Get attachment properties | ||||
* | * | ||||
* @param string $id Attachment identifier | * @param string $id Attachment identifier | ||||
* @param array $event Hash array with event properties: | * @param array $event Hash array with event properties: | ||||
* id: Event identifier | * id: Event identifier | ||||
* calendar: Calendar identifier | * calendar: Calendar identifier | ||||
* | * | ||||
* @return array Hash array with attachment properties: | * @return array Hash array with attachment properties: | ||||
* id: Attachment identifier | * id: Attachment identifier | ||||
* name: Attachment name | * name: Attachment name | ||||
* mimetype: MIME content type of the attachment | * mimetype: MIME content type of the attachment | ||||
* size: Attachment size | * size: Attachment size | ||||
*/ | */ | ||||
public function get_attachment($id, $event) { } | public function get_attachment($id, $event) { } | ||||
/** | /** | ||||
* Get attachment body | * Get attachment body | ||||
* | * | ||||
* @param string $id Attachment identifier | * @param string $id Attachment identifier | ||||
* @param array $event Hash array with event properties: | * @param array $event Hash array with event properties: | ||||
* id: Event identifier | * id: Event identifier | ||||
* calendar: Calendar identifier | * calendar: Calendar identifier | ||||
* | * | ||||
* @return string Attachment body | * @return string Attachment body | ||||
*/ | */ | ||||
public function get_attachment_body($id, $event) { } | public function get_attachment_body($id, $event) { } | ||||
/** | /** | ||||
* Build a struct representing the given message reference | * Build a struct representing the given message reference | ||||
* | * | ||||
* @param object|string $uri_or_headers rcube_message_header instance holding the message headers | * @param object|string $uri_or_headers rcube_message_header instance holding the message headers | ||||
* or an URI from a stored link referencing a mail message. | * or an URI from a stored link referencing a mail message. | ||||
* @param string $folder IMAP folder the message resides in | * @param string $folder IMAP folder the message resides in | ||||
* | * | ||||
* @return array An struct referencing the given IMAP message | * @return array An struct referencing the given IMAP message | ||||
*/ | */ | ||||
public function get_message_reference($uri_or_headers, $folder = null) | public function get_message_reference($uri_or_headers, $folder = null) | ||||
{ | { | ||||
// to be implemented by the derived classes | // to be implemented by the derived classes | ||||
return false; | return false; | ||||
} | } | ||||
/** | /** | ||||
* List availabale categories | * List availabale categories | ||||
* The default implementation reads them from config/user prefs | * The default implementation reads them from config/user prefs | ||||
*/ | */ | ||||
public function list_categories() | public function list_categories() | ||||
{ | { | ||||
$rcmail = rcube::get_instance(); | $rcmail = rcube::get_instance(); | ||||
return $rcmail->config->get('calendar_categories', $this->default_categories); | return $rcmail->config->get('calendar_categories', $this->default_categories); | ||||
} | } | ||||
/** | /** | ||||
* Create a new category | * Create a new category | ||||
*/ | */ | ||||
public function add_category($name, $color) { } | public function add_category($name, $color) { } | ||||
/** | /** | ||||
* Remove the given category | * Remove the given category | ||||
*/ | */ | ||||
public function remove_category($name) { } | public function remove_category($name) { } | ||||
/** | /** | ||||
* Update/replace a category | * Update/replace a category | ||||
*/ | */ | ||||
public function replace_category($oldname, $name, $color) { } | public function replace_category($oldname, $name, $color) { } | ||||
/** | /** | ||||
* Fetch free/busy information from a person within the given range | * Fetch free/busy information from a person within the given range | ||||
* | * | ||||
* @param string E-mail address of attendee | * @param string $email E-mail address of attendee | ||||
* @param integer Requested period start date/time as unix timestamp | * @param int $start Requested period start date/time as unix timestamp | ||||
* @param integer Requested period end date/time as unix timestamp | * @param int $end Requested period end date/time as unix timestamp | ||||
* | * | ||||
* @return array List of busy timeslots within the requested range | * @return array List of busy timeslots within the requested range | ||||
*/ | */ | ||||
public function get_freebusy_list($email, $start, $end) | public function get_freebusy_list($email, $start, $end) | ||||
{ | { | ||||
return false; | return false; | ||||
} | } | ||||
/** | /** | ||||
* Create instances of a recurring event | * Create instances of a recurring event | ||||
* | * | ||||
* @param array Hash array with event properties | * @param array $event Hash array with event properties | ||||
* @param object DateTime Start date of the recurrence window | * @param DateTime $start Start date of the recurrence window | ||||
* @param object DateTime End date of the recurrence window | * @param DateTime $end End date of the recurrence window | ||||
* | |||||
* @return array List of recurring event instances | * @return array List of recurring event instances | ||||
*/ | */ | ||||
public function get_recurring_events($event, $start, $end = null) | public function get_recurring_events($event, $start, $end = null) | ||||
{ | { | ||||
$events = array(); | $events = []; | ||||
if ($event['recurrence']) { | if (!empty($event['recurrence'])) { | ||||
// include library class | // include library class | ||||
require_once(dirname(__FILE__) . '/../lib/calendar_recurrence.php'); | require_once(dirname(__FILE__) . '/../lib/calendar_recurrence.php'); | ||||
$rcmail = rcmail::get_instance(); | $rcmail = rcmail::get_instance(); | ||||
$recurrence = new calendar_recurrence($rcmail->plugins->get_plugin('calendar'), $event); | $recurrence = new calendar_recurrence($rcmail->plugins->get_plugin('calendar'), $event); | ||||
$recurrence_id_format = libcalendaring::recurrence_id_format($event); | $recurrence_id_format = libcalendaring::recurrence_id_format($event); | ||||
// determine a reasonable end date if none given | // determine a reasonable end date if none given | ||||
if (!$end) { | if (!$end) { | ||||
switch ($event['recurrence']['FREQ']) { | switch ($event['recurrence']['FREQ']) { | ||||
case 'YEARLY': $intvl = 'P100Y'; break; | case 'YEARLY': $intvl = 'P100Y'; break; | ||||
case 'MONTHLY': $intvl = 'P20Y'; break; | case 'MONTHLY': $intvl = 'P20Y'; break; | ||||
default: $intvl = 'P10Y'; break; | default: $intvl = 'P10Y'; break; | ||||
} | } | ||||
$end = clone $event['start']; | $end = clone $event['start']; | ||||
$end->add(new DateInterval($intvl)); | $end->add(new DateInterval($intvl)); | ||||
} | } | ||||
$i = 0; | $i = 0; | ||||
while ($next_event = $recurrence->next_instance()) { | while ($next_event = $recurrence->next_instance()) { | ||||
// add to output if in range | // add to output if in range | ||||
if (($next_event['start'] <= $end && $next_event['end'] >= $start)) { | if (($next_event['start'] <= $end && $next_event['end'] >= $start)) { | ||||
$next_event['_instance'] = $next_event['start']->format($recurrence_id_format); | $next_event['_instance'] = $next_event['start']->format($recurrence_id_format); | ||||
$next_event['id'] = $next_event['uid'] . '-' . $exception['_instance']; | $next_event['id'] = $next_event['uid'] . '-' . $exception['_instance']; | ||||
$next_event['recurrence_id'] = $event['uid']; | $next_event['recurrence_id'] = $event['uid']; | ||||
$events[] = $next_event; | $events[] = $next_event; | ||||
} | } | ||||
else if ($next_event['start'] > $end) { // stop loop if out of range | else if ($next_event['start'] > $end) { // stop loop if out of range | ||||
break; | break; | ||||
} | } | ||||
// avoid endless recursion loops | // avoid endless recursion loops | ||||
if (++$i > 1000) { | if (++$i > 1000) { | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
return $events; | return $events; | ||||
} | } | ||||
/** | /** | ||||
* Provide a list of revisions for the given event | * Provide a list of revisions for the given event | ||||
* | * | ||||
* @param array $event Hash array with event properties: | * @param array $event Hash array with event properties: | ||||
* id: Event identifier | * id: Event identifier | ||||
* calendar: Calendar identifier | * calendar: Calendar identifier | ||||
* | * | ||||
* @return array List of changes, each as a hash array: | * @return array List of changes, each as a hash array: | ||||
* rev: Revision number | * rev: Revision number | ||||
* type: Type of the change (create, update, move, delete) | * type: Type of the change (create, update, move, delete) | ||||
* date: Change date | * date: Change date | ||||
* user: The user who executed the change | * user: The user who executed the change | ||||
* ip: Client IP | * ip: Client IP | ||||
* destination: Destination calendar for 'move' type | * destination: Destination calendar for 'move' type | ||||
*/ | */ | ||||
public function get_event_changelog($event) | public function get_event_changelog($event) | ||||
{ | { | ||||
return false; | return false; | ||||
} | } | ||||
/** | /** | ||||
* Get a list of property changes beteen two revisions of an event | * Get a list of property changes beteen two revisions of an event | ||||
* | * | ||||
* @param array $event Hash array with event properties: | * @param array $event Hash array with event properties: | ||||
* id: Event identifier | * id: Event identifier | ||||
* calendar: Calendar identifier | * calendar: Calendar identifier | ||||
* @param mixed $rev1 Old Revision | * @param mixed $rev1 Old Revision | ||||
* @param mixed $rev2 New Revision | * @param mixed $rev2 New Revision | ||||
* | * | ||||
* @return array List of property changes, each as a hash array: | * @return array List of property changes, each as a hash array: | ||||
* property: Revision number | * property: Revision number | ||||
* old: Old property value | * old: Old property value | ||||
* new: Updated property value | * new: Updated property value | ||||
*/ | */ | ||||
public function get_event_diff($event, $rev1, $rev2) | public function get_event_diff($event, $rev1, $rev2) | ||||
{ | { | ||||
return false; | return false; | ||||
} | } | ||||
/** | /** | ||||
* Return full data of a specific revision of an event | * Return full data of a specific revision of an event | ||||
* | * | ||||
* @param mixed UID string or hash array with event properties: | * @param mixed $event UID string or hash array with event properties: | ||||
* id: Event identifier | * id: Event identifier | ||||
* calendar: Calendar identifier | * calendar: Calendar identifier | ||||
* @param mixed $rev Revision number | * @param mixed $rev Revision number | ||||
* | * | ||||
* @return array Event object as hash array | * @return array Event object as hash array | ||||
* @see self::get_event() | * @see self::get_event() | ||||
*/ | */ | ||||
public function get_event_revison($event, $rev) | public function get_event_revison($event, $rev) | ||||
{ | { | ||||
return false; | return false; | ||||
} | } | ||||
/** | /** | ||||
* Command the backend to restore a certain revision of an event. | * Command the backend to restore a certain revision of an event. | ||||
* This shall replace the current event with an older version. | * This shall replace the current event with an older version. | ||||
* | * | ||||
* @param mixed UID string or hash array with event properties: | * @param mixed $event UID string or hash array with event properties: | ||||
* id: Event identifier | * id: Event identifier | ||||
* calendar: Calendar identifier | * calendar: Calendar identifier | ||||
* @param mixed $rev Revision number | * @param mixed $rev Revision number | ||||
* | * | ||||
* @return boolean True on success, False on failure | * @return boolean True on success, False on failure | ||||
*/ | */ | ||||
public function restore_event_revision($event, $rev) | public function restore_event_revision($event, $rev) | ||||
{ | { | ||||
return false; | return false; | ||||
} | } | ||||
/** | /** | ||||
* Callback function to produce driver-specific calendar create/edit form | * Callback function to produce driver-specific calendar create/edit form | ||||
* | * | ||||
* @param string Request action 'form-edit|form-new' | * @param string $action Request action 'form-edit|form-new' | ||||
* @param array Calendar properties (e.g. id, color) | * @param array $calendar Calendar properties (e.g. id, color) | ||||
* @param array Edit form fields | * @param array $formfields Edit form fields | ||||
* | * | ||||
* @return string HTML content of the form | * @return string HTML content of the form | ||||
*/ | */ | ||||
public function calendar_form($action, $calendar, $formfields) | public function calendar_form($action, $calendar, $formfields) | ||||
{ | { | ||||
$table = new html_table(array('cols' => 2, 'class' => 'propform')); | $table = new html_table(['cols' => 2, 'class' => 'propform']); | ||||
foreach ($formfields as $col => $colprop) { | foreach ($formfields as $col => $colprop) { | ||||
$label = !empty($colprop['label']) ? $colprop['label'] : $rcmail->gettext("$domain.$col"); | $label = !empty($colprop['label']) ? $colprop['label'] : $rcmail->gettext("$domain.$col"); | ||||
$table->add('title', html::label($colprop['id'], rcube::Q($label))); | $table->add('title', html::label($colprop['id'], rcube::Q($label))); | ||||
$table->add(null, $colprop['value']); | $table->add(null, $colprop['value']); | ||||
} | } | ||||
return $table->show(); | return $table->show(); | ||||
} | } | ||||
/** | /** | ||||
* Compose a list of birthday events from the contact records in the user's address books. | * Compose a list of birthday events from the contact records in the user's address books. | ||||
* | * | ||||
* This is a default implementation using Roundcube's address book API. | * This is a default implementation using Roundcube's address book API. | ||||
* It can be overriden with a more optimized version by the individual drivers. | * It can be overriden with a more optimized version by the individual drivers. | ||||
* | * | ||||
* @param integer Event's new start (unix timestamp) | * @param int $start Event's new start (unix timestamp) | ||||
* @param integer Event's new end (unix timestamp) | * @param int $end Event's new end (unix timestamp) | ||||
* @param string Search query (optional) | * @param string $search Search query (optional) | ||||
* @param integer Only list events modified since this time (unix timestamp) | * @param int $modifiedsince Only list events modified since this time (unix timestamp) | ||||
* | |||||
* @return array A list of event records | * @return array A list of event records | ||||
*/ | */ | ||||
public function load_birthday_events($start, $end, $search = null, $modifiedsince = null) | public function load_birthday_events($start, $end, $search = null, $modifiedsince = null) | ||||
{ | { | ||||
// ignore update requests for simplicity reasons | // ignore update requests for simplicity reasons | ||||
if (!empty($modifiedsince)) { | if (!empty($modifiedsince)) { | ||||
return array(); | return []; | ||||
} | } | ||||
// convert to DateTime for comparisons | // convert to DateTime for comparisons | ||||
$start = new DateTime('@'.$start); | $start = new DateTime('@'.$start); | ||||
$end = new DateTime('@'.$end); | $end = new DateTime('@'.$end); | ||||
// extract the current year | // extract the current year | ||||
$year = $start->format('Y'); | $year = $start->format('Y'); | ||||
$year2 = $end->format('Y'); | $year2 = $end->format('Y'); | ||||
$events = array(); | $events = []; | ||||
$search = mb_strtolower($search); | $search = mb_strtolower($search); | ||||
$rcmail = rcmail::get_instance(); | $rcmail = rcmail::get_instance(); | ||||
$cache = $rcmail->get_cache('calendar.birthdays', 'db', 3600); | $cache = $rcmail->get_cache('calendar.birthdays', 'db', 3600); | ||||
$cache->expunge(); | $cache->expunge(); | ||||
$alarm_type = $rcmail->config->get('calendar_birthdays_alarm_type', ''); | $alarm_type = $rcmail->config->get('calendar_birthdays_alarm_type', ''); | ||||
$alarm_offset = $rcmail->config->get('calendar_birthdays_alarm_offset', '-1D'); | $alarm_offset = $rcmail->config->get('calendar_birthdays_alarm_offset', '-1D'); | ||||
$alarms = $alarm_type ? $alarm_offset . ':' . $alarm_type : null; | $alarms = $alarm_type ? $alarm_offset . ':' . $alarm_type : null; | ||||
// let the user select the address books to consider in prefs | // let the user select the address books to consider in prefs | ||||
$selected_sources = $rcmail->config->get('calendar_birthday_adressbooks'); | $selected_sources = $rcmail->config->get('calendar_birthday_adressbooks'); | ||||
$sources = $selected_sources ?: array_keys($rcmail->get_address_sources(false, true)); | $sources = $selected_sources ?: array_keys($rcmail->get_address_sources(false, true)); | ||||
foreach ($sources as $source) { | foreach ($sources as $source) { | ||||
$abook = $rcmail->get_address_book($source); | $abook = $rcmail->get_address_book($source); | ||||
// skip LDAP address books unless selected by the user | // skip LDAP address books unless selected by the user | ||||
if (!$abook || ($abook instanceof rcube_ldap && empty($selected_sources))) { | if (!$abook || ($abook instanceof rcube_ldap && empty($selected_sources))) { | ||||
continue; | continue; | ||||
} | } | ||||
// skip collected recipients/senders addressbooks | |||||
if (is_a($abook, 'rcube_addresses')) { | |||||
continue; | |||||
} | |||||
$abook->set_pagesize(10000); | $abook->set_pagesize(10000); | ||||
// check for cached results | // check for cached results | ||||
$cache_records = array(); | $cache_records = []; | ||||
$cached = $cache->get($source); | $cached = $cache->get($source); | ||||
// iterate over (cached) contacts | // iterate over (cached) contacts | ||||
foreach (($cached ?: $abook->search('*', '', 2, true, true, array('birthday'))) as $contact) { | foreach (($cached ?: $abook->search('*', '', 2, true, true, ['birthday'])) as $contact) { | ||||
$event = self::parse_contact($contact, $source); | $event = self::parse_contact($contact, $source); | ||||
if (empty($event)) { | if (empty($event)) { | ||||
continue; | continue; | ||||
} | } | ||||
// add stripped record to cache | // add stripped record to cache | ||||
if (empty($cached)) { | if (empty($cached)) { | ||||
$cache_records[] = array( | $cache_records[] = [ | ||||
'ID' => $contact['ID'], | 'ID' => $contact['ID'], | ||||
'name' => $event['_displayname'], | 'name' => $event['_displayname'], | ||||
'birthday' => $event['start']->format('Y-m-d'), | 'birthday' => $event['start']->format('Y-m-d'), | ||||
); | ]; | ||||
} | } | ||||
// filter by search term (only name is involved here) | // filter by search term (only name is involved here) | ||||
if (!empty($search) && strpos(mb_strtolower($event['title']), $search) === false) { | if (!empty($search) && strpos(mb_strtolower($event['title']), $search) === false) { | ||||
continue; | continue; | ||||
} | } | ||||
$bday = clone $event['start']; | $bday = clone $event['start']; | ||||
$byear = $bday->format('Y'); | $byear = $bday->format('Y'); | ||||
// quick-and-dirty recurrence computation: just replace the year | // quick-and-dirty recurrence computation: just replace the year | ||||
$bday->setDate($year, $bday->format('n'), $bday->format('j')); | $bday->setDate($year, $bday->format('n'), $bday->format('j')); | ||||
$bday->setTime(12, 0, 0); | $bday->setTime(12, 0, 0); | ||||
$this_year = $year; | $this_year = $year; | ||||
// date range reaches over multiple years: use end year if not in range | // date range reaches over multiple years: use end year if not in range | ||||
if (($bday > $end || $bday < $start) && $year2 != $year) { | if (($bday > $end || $bday < $start) && $year2 != $year) { | ||||
$bday->setDate($year2, $bday->format('n'), $bday->format('j')); | $bday->setDate($year2, $bday->format('n'), $bday->format('j')); | ||||
$this_year = $year2; | $this_year = $year2; | ||||
} | } | ||||
// birthday is within requested range | // birthday is within requested range | ||||
if ($bday <= $end && $bday >= $start) { | if ($bday <= $end && $bday >= $start) { | ||||
unset($event['_displayname']); | unset($event['_displayname']); | ||||
$event['alarms'] = $alarms; | $event['alarms'] = $alarms; | ||||
// if this is not the first occurence modify event details | // if this is not the first occurence modify event details | ||||
// but not when this is "all birthdays feed" request | // but not when this is "all birthdays feed" request | ||||
if ($year2 - $year < 10 && ($age = ($this_year - $byear))) { | if ($year2 - $year < 10 && ($age = ($this_year - $byear))) { | ||||
$event['description'] = $rcmail->gettext(array('name' => 'birthdayage', 'vars' => array('age' => $age)), 'calendar'); | $label = ['name' => 'birthdayage', 'vars' => ['age' => $age]]; | ||||
$event['description'] = $rcmail->gettext($label, 'calendar'); | |||||
$event['start'] = $bday; | $event['start'] = $bday; | ||||
$event['end'] = clone $bday; | $event['end'] = clone $bday; | ||||
unset($event['recurrence']); | unset($event['recurrence']); | ||||
} | } | ||||
// add the main instance | // add the main instance | ||||
$events[] = $event; | $events[] = $event; | ||||
} | } | ||||
} | } | ||||
// store collected contacts in cache | // store collected contacts in cache | ||||
if (empty($cached)) { | if (empty($cached)) { | ||||
$cache->write($source, $cache_records); | $cache->write($source, $cache_records); | ||||
} | } | ||||
} | } | ||||
return $events; | return $events; | ||||
} | } | ||||
/** | /** | ||||
* Get a single birthday calendar event | * Get a single birthday calendar event | ||||
*/ | */ | ||||
public function get_birthday_event($id) | public function get_birthday_event($id) | ||||
{ | { | ||||
// decode $id | // decode $id | ||||
list(,$source,$contact_id,$year) = explode(':', rcube_ldap::dn_decode($id)); | list(, $source, $contact_id, $year) = explode(':', rcube_ldap::dn_decode($id)); | ||||
$rcmail = rcmail::get_instance(); | $rcmail = rcmail::get_instance(); | ||||
if (strlen($source) && $contact_id && ($abook = $rcmail->get_address_book($source))) { | if (strlen($source) && $contact_id && ($abook = $rcmail->get_address_book($source))) { | ||||
if ($contact = $abook->get_record($contact_id, true)) { | if ($contact = $abook->get_record($contact_id, true)) { | ||||
return self::parse_contact($contact, $source); | return self::parse_contact($contact, $source); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
/** | /** | ||||
* Parse contact and create an event for its birthday | * Parse contact and create an event for its birthday | ||||
* | * | ||||
* @param array $contact Contact data | * @param array $contact Contact data | ||||
* @param string $source Addressbook source ID | * @param string $source Addressbook source ID | ||||
* | * | ||||
* @return array Birthday event data | * @return array|null Birthday event data | ||||
*/ | */ | ||||
public static function parse_contact($contact, $source) | public static function parse_contact($contact, $source) | ||||
{ | { | ||||
if (!is_array($contact)) { | if (!is_array($contact)) { | ||||
return; | return; | ||||
} | } | ||||
if (is_array($contact['birthday'])) { | if (!empty($contact['birthday']) && is_array($contact['birthday'])) { | ||||
$contact['birthday'] = reset($contact['birthday']); | $contact['birthday'] = reset($contact['birthday']); | ||||
} | } | ||||
if (empty($contact['birthday'])) { | if (empty($contact['birthday'])) { | ||||
return; | return; | ||||
} | } | ||||
try { | try { | ||||
$bday = $contact['birthday']; | $bday = $contact['birthday']; | ||||
if (!$bday instanceof DateTime) { | if (!$bday instanceof DateTime) { | ||||
$bday = new DateTime($bday, new DateTimezone('UTC')); | $bday = new DateTime($bday, new DateTimezone('UTC')); | ||||
} | } | ||||
$bday->_dateonly = true; | $bday->_dateonly = true; | ||||
} | } | ||||
catch (Exception $e) { | catch (Exception $e) { | ||||
rcube::raise_error(array( | rcube::raise_error([ | ||||
'code' => 600, 'type' => 'php', | 'code' => 600, | ||||
'file' => __FILE__, 'line' => __LINE__, | 'file' => __FILE__, | ||||
'message' => 'BIRTHDAY PARSE ERROR: ' . $e->getMessage()), | 'line' => __LINE__, | ||||
true, false); | 'message' => 'BIRTHDAY PARSE ERROR: ' . $e->getMessage() | ||||
], | |||||
true, false | |||||
); | |||||
return; | return; | ||||
} | } | ||||
$rcmail = rcmail::get_instance(); | $rcmail = rcmail::get_instance(); | ||||
$birthyear = $bday->format('Y'); | $birthyear = $bday->format('Y'); | ||||
$display_name = rcube_addressbook::compose_display_name($contact); | $display_name = rcube_addressbook::compose_display_name($contact); | ||||
$label = array('name' => 'birthdayeventtitle', 'vars' => array('name' => $display_name)); | $label = ['name' => 'birthdayeventtitle', 'vars' => ['name' => $display_name]]; | ||||
$event_title = $rcmail->gettext($label, 'calendar'); | $event_title = $rcmail->gettext($label, 'calendar'); | ||||
$uid = rcube_ldap::dn_encode('bday:' . $source . ':' . $contact['ID'] . ':' . $birthyear); | $uid = rcube_ldap::dn_encode('bday:' . $source . ':' . $contact['ID'] . ':' . $birthyear); | ||||
$event = array( | return [ | ||||
'id' => $uid, | 'id' => $uid, | ||||
'uid' => $uid, | 'uid' => $uid, | ||||
'calendar' => self::BIRTHDAY_CALENDAR_ID, | 'calendar' => self::BIRTHDAY_CALENDAR_ID, | ||||
'title' => $event_title, | 'title' => $event_title, | ||||
'description' => '', | 'description' => '', | ||||
'allday' => true, | 'allday' => true, | ||||
'start' => $bday, | 'start' => $bday, | ||||
'end' => clone $bday, | 'end' => clone $bday, | ||||
'recurrence' => array('FREQ' => 'YEARLY', 'INTERVAL' => 1), | 'recurrence' => ['FREQ' => 'YEARLY', 'INTERVAL' => 1], | ||||
'free_busy' => 'free', | 'free_busy' => 'free', | ||||
'_displayname' => $display_name, | '_displayname' => $display_name, | ||||
); | ]; | ||||
return $event; | |||||
} | } | ||||
/** | /** | ||||
* Store alarm dismissal for birtual birthay events | * Store alarm dismissal for birtual birthay events | ||||
* | * | ||||
* @param string Event identifier | * @param string $event_id Event identifier | ||||
* @param integer Suspend the alarm for this number of seconds | * @param int $snooze Suspend the alarm for this number of seconds | ||||
*/ | */ | ||||
public function dismiss_birthday_alarm($event_id, $snooze = 0) | public function dismiss_birthday_alarm($event_id, $snooze = 0) | ||||
{ | { | ||||
$rcmail = rcmail::get_instance(); | $rcmail = rcmail::get_instance(); | ||||
$cache = $rcmail->get_cache('calendar.birthdayalarms', 'db', 86400 * 30); | $cache = $rcmail->get_cache('calendar.birthdayalarms', 'db', 86400 * 30); | ||||
$cache->remove($event_id); | $cache->remove($event_id); | ||||
// compute new notification time or disable if not snoozed | // compute new notification time or disable if not snoozed | ||||
$notifyat = $snooze > 0 ? time() + $snooze : null; | $notifyat = $snooze > 0 ? time() + $snooze : null; | ||||
$cache->set($event_id, array('snooze' => $snooze, 'notifyat' => $notifyat)); | $cache->set($event_id, ['snooze' => $snooze, 'notifyat' => $notifyat]); | ||||
return true; | return true; | ||||
} | } | ||||
/** | /** | ||||
* Handler for user_delete plugin hook | * Handler for user_delete plugin hook | ||||
* | * | ||||
* @param array Hash array with hook arguments | * @param array $args Hash array with hook arguments | ||||
* | |||||
* @return array Return arguments for plugin hooks | * @return array Return arguments for plugin hooks | ||||
*/ | */ | ||||
public function user_delete($args) | public function user_delete($args) | ||||
{ | { | ||||
// TO BE OVERRIDDEN | // TO BE OVERRIDDEN | ||||
return $args; | return $args; | ||||
} | } | ||||
} | } |