622 lines
22 KiB
PHP
622 lines
22 KiB
PHP
<?php
|
|
/**
|
|
* Copyright 2013-2017 Horde LLC (http://www.horde.org/)
|
|
*
|
|
* See the enclosed file COPYING for license information (GPL). If you
|
|
* did not receive this file, see http://www.horde.org/licenses/gpl.
|
|
*
|
|
* @author Michael J Rubinsky <mrubinsk@horde.org>
|
|
* @license http://www.horde.org/licenses/gpl GPL
|
|
* @package Kronolith
|
|
* @category Horde
|
|
*/
|
|
|
|
/**
|
|
* Handles management of the various global calendar lists.
|
|
*
|
|
* @author Michael J Rubinsky <mrubinsk@horde.org>
|
|
* @license http://www.horde.org/licenses/gpl GPL
|
|
* @package Kronolith
|
|
* @category Horde
|
|
*/
|
|
class Kronolith_CalendarsManager
|
|
{
|
|
/**
|
|
* List of all available internal calendars.
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $_allCalendars = array();
|
|
|
|
/**
|
|
* List of all available remote calendars.
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $_allRemote = false;
|
|
|
|
/**
|
|
* List of all available external calendars.
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $_allExternal = false;
|
|
|
|
/**
|
|
* List of all available Holiday calendars.
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $_allHolidays = false;
|
|
|
|
/**
|
|
* List of all internal calendars that are currently selected to be visible.
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $_displayCalendars;
|
|
|
|
/**
|
|
* List of remote calendars selected for display.
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $_displayRemote;
|
|
|
|
/**
|
|
* List of resource calendars selected for display.
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $_displayResource;
|
|
|
|
/**
|
|
* Lazy loaded list of all resource calendars.
|
|
*
|
|
* @var array.
|
|
*/
|
|
protected $_allResource = false;
|
|
|
|
/**
|
|
* List of holiday calendars selected for display. Used internally to hold
|
|
* the user prefs for displayed holiday calendars before we need to see
|
|
* if they are all available.
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $_displayHolidaysInternal = array();
|
|
|
|
/**
|
|
* List of all holidays selected for display.
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $_displayHolidays = false;
|
|
|
|
/**
|
|
* List of external (listTimeObjects) calendars selected for display.
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $_displayExternal = false;
|
|
|
|
/**
|
|
* Const'r
|
|
* Sets up various display lists and session variables:
|
|
*
|
|
* Always set:
|
|
* - allCalendars
|
|
* - displayCalendars
|
|
* - displayResource
|
|
*
|
|
* Lazy loaded:
|
|
* - allRemote
|
|
* - allExternal
|
|
* - allHolidays
|
|
* - allResource
|
|
* - displayRemote
|
|
* - displayExternal
|
|
* - displayHolidays
|
|
*
|
|
* @param string $user The user to initialize for, if not the current.
|
|
* @since 4.2.4
|
|
*/
|
|
public function __construct($user = null)
|
|
{
|
|
$emptyUser = false;
|
|
if (empty($user)) {
|
|
$user = $GLOBALS['registry']->getAuth();
|
|
$emptyUser = true;
|
|
}
|
|
// Always perform the display related checks.
|
|
$this->_checkDisplayCals();
|
|
$this->_checkToggleCalendars();
|
|
|
|
// Check that all selected shares still exist.
|
|
foreach (Kronolith::listInternalCalendars(false, Horde_Perms::SHOW, $user) as $id => $calendar) {
|
|
$this->_allCalendars[$id] = new Kronolith_Calendar_Internal(array('share' => $calendar));
|
|
}
|
|
$this->_displayCalendars = array_intersect($this->_displayCalendars, array_keys($this->_allCalendars));
|
|
|
|
// Check that the user owns a calendar if we aren't loading a different
|
|
// user.
|
|
if ($emptyUser) {
|
|
$this->_checkForOwnedCalendar();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Return the requested list.
|
|
*
|
|
* @param string $list A Kronolith:: calendar manager constant.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function get($list)
|
|
{
|
|
switch ($list) {
|
|
case Kronolith::ALL_CALENDARS:
|
|
case Kronolith::DISPLAY_CALENDARS:
|
|
case Kronolith::DISPLAY_RESOURCE_CALENDARS:
|
|
$property = '_' . $list;
|
|
return $this->$property;
|
|
|
|
//Lazy loaded
|
|
case Kronolith::ALL_RESOURCE_CALENDARS:
|
|
if ($this->_allResource !== false) {
|
|
return $this->_allResource;
|
|
}
|
|
return $this->_getAllResource();
|
|
|
|
case Kronolith::ALL_REMOTE_CALENDARS:
|
|
if ($this->_allRemote !== false) {
|
|
return $this->_allRemote;
|
|
}
|
|
return $this->_getRemoteCalendars();
|
|
|
|
case Kronolith::DISPLAY_REMOTE_CALENDARS:
|
|
// Need to run this at least once to validate remote calendars
|
|
// still exist in prefs.
|
|
if ($this->_allRemote === false) {
|
|
$this->_getRemoteCalendars();
|
|
}
|
|
return $this->_displayRemote;
|
|
|
|
case Kronolith::ALL_EXTERNAL_CALENDARS:
|
|
if ($this->_allExternal !== false) {
|
|
return $this->_allExternal;
|
|
}
|
|
return $this->_getAllExternal();
|
|
|
|
case Kronolith::DISPLAY_EXTERNAL_CALENDARS:
|
|
if ($this->_displayExternal !== false) {
|
|
return $this->_displayExternal;
|
|
}
|
|
return $this->_getDisplayExternal();
|
|
|
|
case Kronolith::ALL_HOLIDAYS:
|
|
if ($this->_allHolidays !== false) {
|
|
return $this->_allHolidays;
|
|
}
|
|
return $this->_getAllHolidays();
|
|
|
|
case Kronolith::DISPLAY_HOLIDAYS:
|
|
if ($this->_displayHolidays !== false) {
|
|
return $this->_displayHolidays;
|
|
}
|
|
return $this->_getDisplayHolidays();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set or replace an existing list with $value.
|
|
*
|
|
* @param string $list The list to set.
|
|
* @param array $value The value to set it to.
|
|
*/
|
|
public function set($list, array $value)
|
|
{
|
|
$property = '_' . $list;
|
|
$this->$property = $value;
|
|
}
|
|
|
|
/**
|
|
* Shortcut method for obtaining a single entry in one of the calendar lists
|
|
*
|
|
* @param string $list The calendar list to obtain an entry from.
|
|
* @param string $entry The entry to retrieve.
|
|
*
|
|
* @return mixed The requested value | false if not found.
|
|
*/
|
|
public function getEntry($list, $entry)
|
|
{
|
|
$temp = $this->get($list);
|
|
if (isset($temp[$entry])) {
|
|
return $temp[$entry];
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Update display preferences
|
|
*/
|
|
protected function _checkDisplayCals()
|
|
{
|
|
global $session, $prefs, $conf;
|
|
|
|
// Update preferences for which calendars to display. If the
|
|
// user doesn't have any selected calendars to view then fall
|
|
// back to an available calendar. An empty string passed in this
|
|
// parameter will clear any existing session value.
|
|
if (($calId = Horde_Util::getFormData('display_cal')) !== null) {
|
|
$session->set('kronolith', 'display_cal', $calId);
|
|
} else {
|
|
$calId = $session->get('kronolith', 'display_cal');
|
|
}
|
|
|
|
if (strlen($calId)) {
|
|
// Specifying a value for display_cal is always to make sure
|
|
// that only the specified calendars are shown. Use the
|
|
// "toggle_calendar" argument to toggle the state of a single
|
|
// calendar.
|
|
$this->_displayCalendars = array();
|
|
$this->_displayRemote = array();
|
|
$this->_displayExternal = array();
|
|
$this->_displayResource = array();
|
|
$this->_displayHolidaysInternal = array();
|
|
|
|
if (strncmp($calId, 'remote_', 7) === 0) {
|
|
$this->_displayRemote[] = substr($calId, 7);
|
|
} elseif (strncmp($calId, 'external_', 9) === 0) {
|
|
$this->_displayExternal[] = substr($calId, 9);
|
|
} elseif (strncmp($calId, 'resource_', 9) === 0) {
|
|
$this->_displayResource[] = substr($calId, 9);
|
|
} elseif (strncmp($calId, 'holidays_', 9) === 0) {
|
|
$this->_displayHolidaysInternal[] = substr($calId, 9);
|
|
} else {
|
|
$this->_displayCalendars[] = (strncmp($calId, 'internal_', 9) === 0)
|
|
? substr($calId, 9)
|
|
: $calId;
|
|
}
|
|
} else {
|
|
// Fetch display preferences.
|
|
$display_prefs = array(
|
|
'display_cals' => 'displayCalendars',
|
|
'display_remote_cals' => 'displayRemote',
|
|
'display_external_cals' => 'displayExternal',
|
|
'holiday_drivers' => 'displayHolidaysInternal',
|
|
'display_resource_cals' => 'displayResource'
|
|
);
|
|
foreach ($display_prefs as $key => $val) {
|
|
$pref_val = @unserialize($prefs->getValue($key));
|
|
$val = '_' . $val;
|
|
$this->$val = is_array($pref_val)
|
|
? $pref_val
|
|
: array();
|
|
}
|
|
|
|
// Run through getDisplayExternal to trim any that no longer exist.
|
|
$this->_getDisplayExternal();
|
|
|
|
if (empty($conf['holidays']['enable'])) {
|
|
$this->_displayHolidays = array();
|
|
$this->_displayHolidaysInternal = array();
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check for single, "toggle" calendars and set display lists and
|
|
* session values appropriately.
|
|
*/
|
|
protected function _checkToggleCalendars()
|
|
{
|
|
global $prefs, $registry;
|
|
|
|
if (($calId = Horde_Util::getFormData('toggle_calendar')) !== null) {
|
|
if (strncmp($calId, 'remote_', 7) === 0) {
|
|
$calId = substr($calId, 7);
|
|
if (($key = array_search($calId, $this->_displayRemote)) === false) {
|
|
$this->_displayRemote[] = $calId;
|
|
} else {
|
|
unset($this->_displayRemote[$key]);
|
|
}
|
|
$prefs->setValue('display_remote_cals', serialize($this->_displayRemote));
|
|
} elseif ((strncmp($calId, 'external_', 9) === 0 &&
|
|
($calId = substr($calId, 9))) ||
|
|
(strncmp($calId, 'tasklists_', 10) === 0 &&
|
|
($calId = substr($calId, 10)))) {
|
|
if (($key = array_search($calId, $this->_displayExternal)) === false) {
|
|
$this->_displayExternal[] = $calId;
|
|
} else {
|
|
unset($this->_displayExternal[$key]);
|
|
}
|
|
$prefs->setValue('display_external_cals', serialize($this->_displayExternal));
|
|
|
|
if (strpos($calId, 'tasks/') === 0) {
|
|
$tasklists = array();
|
|
foreach ($this->_displayExternal as $id) {
|
|
if (strpos($id, 'tasks/') === 0) {
|
|
$tasklists[] = substr($id, 6);
|
|
}
|
|
}
|
|
try {
|
|
$registry->tasks->setDisplayedTasklists($tasklists);
|
|
} catch (Horde_Exception $e) {}
|
|
}
|
|
} elseif (strncmp($calId, 'holiday_', 8) === 0) {
|
|
$calId = substr($calId, 8);
|
|
if (($key = array_search($calId, $this->_displayHolidaysInternal)) === false) {
|
|
$this->_displayHolidaysInternal[] = $calId;
|
|
} else {
|
|
unset($this->_displayHolidaysInternal[$key]);
|
|
}
|
|
$prefs->setValue('holiday_drivers', serialize($this->_displayHolidaysInternal));
|
|
} elseif (strncmp($calId, 'resource_', 9) === 0) {
|
|
$calId = substr($calId, 9);
|
|
if (($key = array_search($calId, $this->_displayResource)) === false) {
|
|
$this->_displayResource[] = $calId;
|
|
} else {
|
|
unset($this->_displayResource[$key]);
|
|
}
|
|
$prefs->setValue('display_resource_cals', serialize($this->_displayResource));
|
|
} elseif (($key = array_search($calId, $this->_displayCalendars)) === false) {
|
|
$this->_displayCalendars[] = $calId;
|
|
} else {
|
|
unset($this->_displayCalendars[$key]);
|
|
}
|
|
|
|
$prefs->setValue('display_cals', serialize($this->_displayCalendars));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check that the user owns a calendar and if not, creates one.
|
|
*/
|
|
protected function _checkForOwnedCalendar()
|
|
{
|
|
global $prefs, $registry, $conf;
|
|
|
|
if (!empty($conf['share']['auto_create']) &&
|
|
$registry->getAuth() &&
|
|
!count(Kronolith::listInternalCalendars(true))) {
|
|
$calendars = $GLOBALS['injector']
|
|
->getInstance('Kronolith_Factory_Calendars')
|
|
->create();
|
|
|
|
$share = $calendars->createDefaultShare();
|
|
$this->_allCalendars[$share->getName()] = new Kronolith_Calendar_Internal(array('share' => $share));
|
|
$this->_displayCalendars[] = $share->getName();
|
|
$prefs->setValue('default_share', $share->getName());
|
|
|
|
// Calendar auto-sharing with the user's groups
|
|
if ($conf['autoshare']['shareperms'] != 'none') {
|
|
$perm_value = 0;
|
|
switch ($conf['autoshare']['shareperms']) {
|
|
case 'read':
|
|
$perm_value = Horde_Perms::READ | Horde_Perms::SHOW;
|
|
break;
|
|
case 'edit':
|
|
$perm_value = Horde_Perms::READ | Horde_Perms::SHOW | Horde_Perms::EDIT;
|
|
break;
|
|
case 'full':
|
|
$perm_value = Horde_Perms::READ | Horde_Perms::SHOW | Horde_Perms::EDIT | Horde_Perms::DELETE;
|
|
break;
|
|
}
|
|
|
|
try {
|
|
$group_list = $GLOBALS['injector']
|
|
->getInstance('Horde_Group')
|
|
->listGroups($registry->getAuth());
|
|
if (count($group_list)) {
|
|
$perm = $share->getPermission();
|
|
// Add the default perm, not added otherwise
|
|
foreach (array_keys($group_list) as $group_id) {
|
|
$perm->addGroupPermission($group_id, $perm_value, false);
|
|
}
|
|
$share->setPermission($perm);
|
|
$GLOBALS['notification']->push(sprintf(_("New calendar created and automatically shared with the following group(s): %s."), implode(', ', $group_list)), 'horde.success');
|
|
}
|
|
} catch (Horde_Group_Exception $e) {}
|
|
}
|
|
|
|
$prefs->setValue('display_cals', serialize($this->_displayCalendars));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Return all known external calendars.
|
|
*
|
|
* @return array
|
|
*/
|
|
protected function _getAllExternal()
|
|
{
|
|
global $registry, $session;
|
|
|
|
$this->_allExternal = array();
|
|
|
|
// Make sure all task lists exist.
|
|
if (Kronolith::hasApiPermission('tasks') &&
|
|
$registry->hasMethod('tasks/listTimeObjects')) {
|
|
try {
|
|
$tasklists = $registry->tasks->listTasklists();
|
|
$categories = $registry->call('tasks/listTimeObjectCategories');
|
|
foreach ($categories as $name => $description) {
|
|
if (!isset($tasklists[$name])) {
|
|
continue;
|
|
}
|
|
$this->_allExternal['tasks/' . $name] = new Kronolith_Calendar_External_Tasks(array('api' => 'tasks', 'name' => $description['title'], 'share' => $tasklists[$name], 'type' => 'share'));
|
|
}
|
|
} catch (Horde_Exception $e) {
|
|
Horde::log($e, 'DEBUG');
|
|
}
|
|
}
|
|
|
|
if ($session->exists('kronolith', 'all_external_calendars')) {
|
|
foreach ($session->get('kronolith', 'all_external_calendars') as $calendar) {
|
|
if (!Kronolith::hasApiPermission($calendar['a']) ||
|
|
$calendar['a'] == 'tasks') {
|
|
continue;
|
|
}
|
|
$this->_allExternal[$calendar['a'] . '/' . $calendar['n']] = new Kronolith_Calendar_External(array('api' => $calendar['a'], 'name' => $calendar['d'], 'id' => $calendar['n'], 'type' => $calendar['t'], 'background' => $calendar['b']));
|
|
}
|
|
} else {
|
|
$apis = array_unique($registry->listAPIs());
|
|
$ext_cals = array();
|
|
|
|
foreach ($apis as $api) {
|
|
if ($api == 'tasks' ||
|
|
!Kronolith::hasApiPermission($api) ||
|
|
!$registry->hasMethod($api . '/listTimeObjects')) {
|
|
continue;
|
|
}
|
|
try {
|
|
$categories = $registry->call($api . '/listTimeObjectCategories');
|
|
} catch (Horde_Exception $e) {
|
|
Horde::log($e, 'DEBUG');
|
|
continue;
|
|
}
|
|
|
|
foreach ($categories as $name => $description) {
|
|
if (empty($description['background'])) {
|
|
$description['background'] = '#dddddd';
|
|
}
|
|
$this->_allExternal[$api . '/' . $name] = new Kronolith_Calendar_External(array(
|
|
'api' => $api,
|
|
'name' => $description['title'],
|
|
'id' => $name,
|
|
'type' => $description['type'],
|
|
'background' => $description['background']));
|
|
$ext_cals[] = array(
|
|
'a' => $api,
|
|
'n' => $name,
|
|
'd' => $description['title'],
|
|
't' => $description['type'],
|
|
'b' => $description['background']
|
|
);
|
|
}
|
|
}
|
|
|
|
$session->set('kronolith', 'all_external_calendars', $ext_cals);
|
|
}
|
|
|
|
return $this->_allExternal;
|
|
}
|
|
|
|
/**
|
|
* Return all external calendars selected for display.
|
|
*
|
|
* @return array
|
|
*/
|
|
protected function _getDisplayExternal()
|
|
{
|
|
global $registry, $prefs;
|
|
|
|
// Make sure all the external calendars still exist.
|
|
$_tasklists = $_temp = $this->_displayExternal;
|
|
if (Kronolith::hasApiPermission('tasks')) {
|
|
try {
|
|
$_tasklists = $registry->tasks->getDisplayedTasklists();
|
|
} catch (Horde_Exception $e) {
|
|
}
|
|
}
|
|
$this->_displayExternal = array();
|
|
foreach ($this->get(Kronolith::ALL_EXTERNAL_CALENDARS) as $id => $calendar) {
|
|
if ((substr($id, 0, 6) == 'tasks/' &&
|
|
in_array(substr($id, 6), $_tasklists)) ||
|
|
in_array($id, $_temp)) {
|
|
$this->_displayExternal[] = $id;
|
|
}
|
|
}
|
|
$prefs->setValue('display_external_cals', serialize($this->_displayExternal));
|
|
|
|
return $this->_displayExternal;
|
|
}
|
|
|
|
/**
|
|
* Return list of all available holidays drivers.
|
|
*
|
|
* @return array The available holidays.
|
|
*/
|
|
protected function _getAllHolidays()
|
|
{
|
|
$this->_allHolidays = array();
|
|
if (!empty($GLOBALS['conf']['holidays']['enable'])) {
|
|
if (class_exists('Date_Holidays')) {
|
|
$dh = new Date_Holidays();
|
|
foreach ($dh->getInstalledDrivers() as $driver) {
|
|
if ($driver['id'] == 'Composite') {
|
|
continue;
|
|
}
|
|
$this->_allHolidays[$driver['id']] = new Kronolith_Calendar_Holiday(array('driver' => $driver));
|
|
ksort($this->_allHolidays);
|
|
}
|
|
}
|
|
}
|
|
|
|
return $this->_allHolidays;
|
|
}
|
|
|
|
/**
|
|
* Return list of holiday calendars to be displayed.
|
|
*
|
|
* @return array The holiday calendars to display.
|
|
*/
|
|
protected function _getDisplayHolidays()
|
|
{
|
|
$this->_displayHolidays = array();
|
|
foreach (array_keys($this->get(Kronolith::ALL_HOLIDAYS)) as $id) {
|
|
if (in_array($id, $this->_displayHolidaysInternal)) {
|
|
$this->_displayHolidays[] = $id;
|
|
}
|
|
}
|
|
$GLOBALS['prefs']->setValue('holiday_drivers', serialize($this->_displayHolidays));
|
|
|
|
return $this->_displayHolidays;
|
|
}
|
|
|
|
/**
|
|
* Return list of all resource calendars.
|
|
*
|
|
* @return array Resource calendars, keyed by calendar id.
|
|
*/
|
|
protected function _getAllResource()
|
|
{
|
|
$this->_allResource = array();
|
|
if (!empty($GLOBALS['conf']['resource']['driver'])) {
|
|
foreach (Kronolith::getDriver('Resource')->listResources(Horde_Perms::READ, array('type' => Kronolith_Resource::TYPE_SINGLE)) as $resource) {
|
|
$rcal = new Kronolith_Calendar_Resource(array(
|
|
'resource' => $resource
|
|
));
|
|
$this->_allResource[$resource->get('calendar')] = $rcal;
|
|
}
|
|
}
|
|
|
|
return $this->_allResource;
|
|
}
|
|
|
|
protected function _getRemoteCalendars()
|
|
{
|
|
if ($this->_allRemote === false) {
|
|
// Check that all selected remote calendars are still configured.
|
|
$tmp = $this->_displayRemote;
|
|
$this->_allRemote = $this->_displayRemote = array();
|
|
$calendars = @unserialize($GLOBALS['prefs']->getValue('remote_cals'));
|
|
if (!is_array($calendars)) {
|
|
$calendars = array();
|
|
}
|
|
foreach ($calendars as $calendar) {
|
|
$this->_allRemote[$calendar['url']] = new Kronolith_Calendar_Remote($calendar);
|
|
if (in_array($calendar['url'], $tmp)) {
|
|
$this->_displayRemote[] = $calendar['url'];
|
|
}
|
|
}
|
|
$GLOBALS['prefs']->setValue('display_remote_cals', serialize($this->_displayRemote));
|
|
}
|
|
|
|
return $this->_allRemote;
|
|
}
|
|
|
|
}
|