Overview

Packages

  • Kronolith
  • None

Classes

  • Kronolith
  • Kronolith_Ajax_Application
  • Kronolith_Ajax_Imple_ContactAutoCompleter
  • Kronolith_Ajax_Imple_Embed
  • Kronolith_Ajax_Imple_TagActions
  • Kronolith_Ajax_Imple_TagAutoCompleter
  • Kronolith_Api
  • Kronolith_Calendar
  • Kronolith_Calendar_External
  • Kronolith_Calendar_External_Tasks
  • Kronolith_Calendar_Holiday
  • Kronolith_Calendar_Internal
  • Kronolith_Calendar_Remote
  • Kronolith_Calendar_Resource
  • Kronolith_Calendars_Base
  • Kronolith_Calendars_Default
  • Kronolith_Calendars_Kolab
  • Kronolith_Day
  • Kronolith_Driver
  • Kronolith_Driver_Holidays
  • Kronolith_Driver_Horde
  • Kronolith_Driver_Ical
  • Kronolith_Driver_Kolab
  • Kronolith_Driver_Mock
  • Kronolith_Driver_Resource
  • Kronolith_Driver_Sql
  • Kronolith_Event
  • Kronolith_Event_Holidays
  • Kronolith_Event_Horde
  • Kronolith_Event_Ical
  • Kronolith_Event_Kolab
  • Kronolith_Event_Resource
  • Kronolith_Event_Sql
  • Kronolith_Exception
  • Kronolith_Factory_Calendars
  • Kronolith_Factory_Geo
  • Kronolith_Form_CreateCalendar
  • Kronolith_Form_CreateResource
  • Kronolith_Form_CreateResourceGroup
  • Kronolith_Form_DeleteCalendar
  • Kronolith_Form_DeleteResource
  • Kronolith_Form_DeleteResourceGroup
  • Kronolith_Form_EditCalendar
  • Kronolith_Form_EditRemoteCalendar
  • Kronolith_Form_EditResource
  • Kronolith_Form_EditResourceGroup
  • Kronolith_Form_SubscribeRemoteCalendar
  • Kronolith_Form_UnsubscribeRemoteCalendar
  • Kronolith_FreeBusy
  • Kronolith_FreeBusy_View
  • Kronolith_FreeBusy_View_Day
  • Kronolith_FreeBusy_View_Month
  • Kronolith_FreeBusy_View_Week
  • Kronolith_FreeBusy_View_Workweek
  • Kronolith_Geo_Base
  • Kronolith_Geo_Mysql
  • Kronolith_Geo_Sql
  • Kronolith_LoginTasks_SystemTask_Upgrade
  • Kronolith_LoginTasks_Task_PurgeEvents
  • Kronolith_Notification_Listener_AjaxStatus
  • Kronolith_Resource
  • Kronolith_Resource_Base
  • Kronolith_Resource_Group
  • Kronolith_Resource_Single
  • Kronolith_Storage
  • Kronolith_Storage_Kolab
  • Kronolith_Storage_Sql
  • Kronolith_Tagger
  • Kronolith_Test
  • Kronolith_View_Day
  • Kronolith_View_DeleteEvent
  • Kronolith_View_EditEvent
  • Kronolith_View_Event
  • Kronolith_View_ExportEvent
  • Kronolith_View_Month
  • Kronolith_View_Week
  • Kronolith_View_WorkWeek
  • Kronolith_View_Year
  • Overview
  • Package
  • Class
  • Tree
   1: <?php
   2: /**
   3:  * Defines the AJAX interface for Kronolith.
   4:  *
   5:  * Copyright 2010-2012 Horde LLC (http://www.horde.org/)
   6:  *
   7:  * See the enclosed file COPYING for license information (GPL). If you
   8:  * did not receive this file, see http://www.horde.org/licenses/gpl.
   9:  *
  10:  * @author  Michael Slusarz <slusarz@horde.org>
  11:  * @author  Jan Schneider <jan@horde.org>
  12:  * @author  Gonçalo Queirós <mail@goncaloqueiros.net>
  13:  * @package Kronolith
  14:  */
  15: class Kronolith_Ajax_Application extends Horde_Core_Ajax_Application
  16: {
  17:     /**
  18:      * Determines if notification information is sent in response.
  19:      *
  20:      * @var boolean
  21:      */
  22:     public $notify = true;
  23: 
  24:     /**
  25:      * Constructor.
  26:      *
  27:      * @param string $app     The application name.
  28:      * @param string $action  The AJAX action to perform.
  29:      */
  30:     public function __construct($app, $vars, $action = null)
  31:     {
  32:         parent::__construct($app, $vars, $action);
  33:         $this->_defaultDomain = empty($GLOBALS['conf']['storage']['default_domain']) ? null : $GLOBALS['conf']['storage']['default_domain'];
  34:     }
  35: 
  36:     /**
  37:      * Just polls for alarm messages and keeps session fresh for now.
  38:      */
  39:     public function poll()
  40:     {
  41:         return false;
  42:     }
  43: 
  44:     /**
  45:      * TODO
  46:      */
  47:     public function listEvents()
  48:     {
  49:         $start = new Horde_Date($this->_vars->start);
  50:         $end   = new Horde_Date($this->_vars->end);
  51:         $result = $this->_signedResponse($this->_vars->cal);
  52:         if (!($kronolith_driver = $this->_getDriver($this->_vars->cal))) {
  53:             return $result;
  54:         }
  55:         try {
  56:             session_write_close();
  57:             $events = $kronolith_driver->listEvents($start, $end, true, false, true);
  58:             session_start();
  59:             if (count($events)) {
  60:                 $result->events = $events;
  61:             }
  62:         } catch (Exception $e) {
  63:             $GLOBALS['notification']->push($e, 'horde.error');
  64:         }
  65:         return $result;
  66:     }
  67: 
  68:     /**
  69:      * TODO
  70:      */
  71:     public function getEvent()
  72:     {
  73:         $result = new stdClass;
  74: 
  75:         if (!($kronolith_driver = $this->_getDriver($this->_vars->cal)) ||
  76:             !isset($this->_vars->id)) {
  77:             return $result;
  78:         }
  79: 
  80:         try {
  81:             $event = $kronolith_driver->getEvent($this->_vars->id, $this->_vars->date);
  82:             $result->event = $event->toJson(null, true, $GLOBALS['prefs']->getValue('twentyFour') ? 'H:i' : 'h:i A');
  83:         } catch (Horde_Exception_NotFound $e) {
  84:             $GLOBALS['notification']->push(_("The requested event was not found."), 'horde.error');
  85:         } catch (Exception $e) {
  86:             $GLOBALS['notification']->push($e, 'horde.error');
  87:         }
  88: 
  89:         return $result;
  90:     }
  91: 
  92:     /**
  93:      * TODO
  94:      */
  95:     public function saveEvent()
  96:     {
  97:         $result = $this->_signedResponse($this->_vars->targetcalendar);
  98: 
  99:         if (!($kronolith_driver = $this->_getDriver($this->_vars->targetcalendar))) {
 100:             return $result;
 101:         }
 102: 
 103:         if ($this->_vars->as_new) {
 104:             unset($this->_vars->event);
 105:         }
 106:         if (!$this->_vars->event) {
 107:             $perms = $GLOBALS['injector']->getInstance('Horde_Core_Perms');
 108:             if ($perms->hasAppPermission('max_events') !== true &&
 109:                 $perms->hasAppPermission('max_events') <= Kronolith::countEvents()) {
 110:                 Horde::permissionDeniedError(
 111:                     'kronolith',
 112:                     'max_events',
 113:                     sprintf(_("You are not allowed to create more than %d events."), $perms->hasAppPermission('max_events'))
 114:                 );
 115:                 return $result;
 116:             }
 117:         }
 118: 
 119:         if ($this->_vars->event &&
 120:             $this->_vars->cal &&
 121:             $this->_vars->cal != $this->_vars->targetcalendar) {
 122:             if (strpos($kronolith_driver->calendar, '\\')) {
 123:                 list($target, $user) = explode('\\', $kronolith_driver->calendar, 2);
 124:             } else {
 125:                 $target = $kronolith_driver->calendar;
 126:                 $user = $GLOBALS['registry']->getAuth();
 127:             }
 128:             $kronolith_driver = $this->_getDriver($this->_vars->cal);
 129:             // Only delete the event from the source calendar if this user has
 130:             // permissions to do so.
 131:             try {
 132:                 $sourceShare = Kronolith::getInternalCalendar($kronolith_driver->calendar);
 133:                 $share = Kronolith::getInternalCalendar($target);
 134:                 if ($sourceShare->hasPermission($GLOBALS['registry']->getAuth(), Horde_Perms::DELETE) &&
 135:                     (($user == $GLOBALS['registry']->getAuth() &&
 136:                       $share->hasPermission($GLOBALS['registry']->getAuth(), Horde_Perms::EDIT)) ||
 137:                      ($user != $GLOBALS['registry']->getAuth() &&
 138:                       $share->hasPermission($GLOBALS['registry']->getAuth(), Kronolith::PERMS_DELEGATE)))) {
 139:                     $kronolith_driver->move($this->_vars->event, $target);
 140:                     $kronolith_driver = $this->_getDriver($this->_vars->targetcalendar);
 141:                 }
 142:             } catch (Exception $e) {
 143:                 $GLOBALS['notification']->push(sprintf(_("There was an error moving the event: %s"), $e->getMessage()), 'horde.error');
 144:                 return $result;
 145:             }
 146:         }
 147: 
 148:         if ($this->_vars->as_new) {
 149:             $event = $kronolith_driver->getEvent();
 150:         } else {
 151:             try {
 152:                 $event = $kronolith_driver->getEvent($this->_vars->event);
 153:             } catch (Horde_Exception_NotFound $e) {
 154:                 $GLOBALS['notification']->push(_("The requested event was not found."), 'horde.error');
 155:                 return $result;
 156:             } catch (Exception $e) {
 157:                 $GLOBALS['notification']->push($e);
 158:                 return $result;
 159:             }
 160:         }
 161: 
 162:         if (!$event->hasPermission(Horde_Perms::EDIT)) {
 163:             $GLOBALS['notification']->push(_("You do not have permission to edit this event."), 'horde.warning');
 164:             return $result;
 165:         }
 166: 
 167:         try {
 168:             $event->readForm();
 169:             $result = $this->_saveEvent($event);
 170:         } catch (Exception $e) {
 171:             $GLOBALS['notification']->push($e);
 172:             return $result;
 173:         }
 174:         if (($result !== true) && $this->_vars->sendupdates) {
 175:             Kronolith::sendITipNotifications($event, $GLOBALS['notification'], Kronolith::ITIP_REQUEST);
 176:         }
 177:         Kronolith::notifyOfResourceRejection($event);
 178: 
 179:         return $result;
 180:     }
 181: 
 182:     /**
 183:      * TODO
 184:      */
 185:     public function quickSaveEvent()
 186:     {
 187:         $cal = explode('|', $this->_vars->cal, 2);
 188:         try {
 189:             $event = Kronolith::quickAdd($this->_vars->text, $cal[1]);
 190:             return $this->_saveEvent($event);
 191:         } catch (Horde_Exception $e) {
 192:             $GLOBALS['notification']->push($e);
 193:             return $this->_signedResponse($this->_vars->cal);
 194:         }
 195:     }
 196: 
 197:     /**
 198:      * Update event details as a result of a drag/drop operation.
 199:      */
 200:     public function updateEvent()
 201:     {
 202:         $result = $this->_signedResponse($this->_vars->cal);
 203: 
 204:         if (!($kronolith_driver = $this->_getDriver($this->_vars->cal)) ||
 205:             !isset($this->_vars->id)) {
 206:             return $result;
 207:         }
 208: 
 209:         try {
 210:             $oevent = $kronolith_driver->getEvent($this->_vars->id);
 211:         } catch (Exception $e) {
 212:             $GLOBALS['notification']->push($e, 'horde.error');
 213:             return $result;
 214:         }
 215:         if (!$oevent) {
 216:             $GLOBALS['notification']->push(_("The requested event was not found."), 'horde.error');
 217:             return $result;
 218:         } elseif (!$oevent->hasPermission(Horde_Perms::EDIT)) {
 219:             $GLOBALS['notification']->push(_("You do not have permission to edit this event."), 'horde.warning');
 220:             return $result;
 221:         }
 222: 
 223:         $attributes = Horde_Serialize::unserialize($this->_vars->att, Horde_Serialize::JSON);
 224: 
 225:         // If this is a recurring event, need to create an exception.
 226:         if ($oevent->recurs()) {
 227:             $event = $this->_createExceptionEvent($oevent, $attributes);
 228:         } else {
 229:             $event = clone($oevent);
 230:         }
 231: 
 232:         foreach ($attributes as $attribute => $value) {
 233:             switch ($attribute) {
 234:             case 'start':
 235:                 $event->start = new Horde_Date($value);
 236:                 break;
 237: 
 238:             case 'end':
 239:                 $event->end = new Horde_Date($value);
 240:                 if ($event->end->hour == 23 &&
 241:                     $event->end->min == 59 &&
 242:                     $event->end->sec == 59) {
 243:                     $event->end->mday++;
 244:                     $event->end->hour = $event->end->min = $event->end->sec = 0;
 245:                 }
 246:                 break;
 247: 
 248:             case 'offDays':
 249:                 $event->start->mday = $event->start->mday + $value;
 250:                 $event->end->mday = $event->end->mday + $value;
 251:                 break;
 252: 
 253:             case 'offMins':
 254:                 $event->start->min += $value;
 255:                 $event->end->min += $value;
 256:                 break;
 257:             }
 258:         }
 259: 
 260:         // @todo: What about iTip notifications?
 261:         return $this->_saveEvent($event, ($oevent->recurs() ? $oevent : null), $attributes);
 262:     }
 263: 
 264:     /**
 265:      * TODO
 266:      */
 267:     public function deleteEvent()
 268:     {
 269:         $result = new stdClass;
 270: 
 271:         if (!($kronolith_driver = $this->_getDriver($this->_vars->cal)) ||
 272:             !isset($this->_vars->id)) {
 273:             return $result;
 274:         }
 275: 
 276:         try {
 277:             $event = $kronolith_driver->getEvent($this->_vars->id);
 278:             if (!$event->hasPermission(Horde_Perms::DELETE)) {
 279:                 $GLOBALS['notification']->push(_("You do not have permission to delete this event."), 'horde.warning');
 280:                 return $result;
 281:             }
 282:             if ($event->recurs()) {
 283:                 $result->uid = $event->uid;
 284:             }
 285:             $deleted = $kronolith_driver->deleteEvent($event->id);
 286:             if ($this->_vars->sendupdates) {
 287:                 Kronolith::sendITipNotifications($event, $GLOBALS['notification'], Kronolith::ITIP_CANCEL);
 288:             }
 289:             $result->deleted = true;
 290:         } catch (Horde_Exception_NotFound $e) {
 291:             $GLOBALS['notification']->push(_("The requested event was not found."), 'horde.error');
 292:         } catch (Exception $e) {
 293:             $GLOBALS['notification']->push($e, 'horde.error');
 294:         }
 295: 
 296:         return $result;
 297:     }
 298: 
 299:     /**
 300:      * TODO
 301:      */
 302:     public function searchEvents()
 303:     {
 304:         $query = Horde_Serialize::unserialize($this->_vars->query, Horde_Serialize::JSON);
 305:         if (!isset($query->start)) {
 306:             $query->start = new Horde_Date($_SERVER['REQUEST_TIME']);
 307:         }
 308:         if (!isset($query->end)) {
 309:             $query->end = null;
 310:         }
 311:         switch ($this->_vars->time) {
 312:         case 'all':
 313:             $query->start = null;
 314:             $query->end = null;
 315:             break;
 316:         case 'future':
 317:             $query->start = new Horde_Date($_SERVER['REQUEST_TIME']);
 318:             $query->end = null;
 319:             break;
 320:         case 'past':
 321:             $query->start = null;
 322:             $query->end = new Horde_Date($_SERVER['REQUEST_TIME']);
 323:             break;
 324:         }
 325: 
 326:         $tagger = new Kronolith_Tagger();
 327:         $cals = Horde_Serialize::unserialize($this->_vars->cals, Horde_Serialize::JSON);
 328:         $events = array();
 329:         foreach ($cals as $cal) {
 330:             if (!($kronolith_driver = $this->_getDriver($cal))) {
 331:                 continue;
 332:             }
 333:             try {
 334:                 $result = $kronolith_driver->search($query, true);
 335:                 if ($result) {
 336:                     $events[$cal] = $result;
 337:                 }
 338:             } catch (Exception $e) {
 339:                 $GLOBALS['notification']->push($e, 'horde.error');
 340:             }
 341:             $split = explode('|', $cal);
 342:             if ($split[0] == 'internal') {
 343:                 $result = $tagger->search($query->title, array('type' => 'event', 'calendar' => $split[1]));
 344:                 foreach ($result['events'] as $uid) {
 345:                     Kronolith::addSearchEvents($events[$cal], $kronolith_driver->getByUID($uid), $query, true);
 346:                 }
 347:             }
 348:         }
 349: 
 350:         $result = new stdClass;
 351:         $result->view = 'search';
 352:         $result->query = $this->_vars->query;
 353:         if ($events) {
 354:             $result->events = $events;
 355:         }
 356: 
 357:         return $result;
 358:     }
 359: 
 360:     /**
 361:      * TODO
 362:      */
 363:     public function listTasks()
 364:     {
 365:         if (!$GLOBALS['registry']->hasMethod('tasks/listTasks')) {
 366:             return false;
 367:         }
 368: 
 369:         $result = new stdClass;
 370:         $result->list = $this->_vars->list;
 371:         $result->type = $this->_vars->type;
 372: 
 373:         try {
 374:             $tasks = $GLOBALS['registry']->tasks->listTasks(null, null, null, $this->_vars->list, $this->_vars->type == 'incomplete' ? 'future_incomplete' : $this->_vars->type, true);
 375:             if (count($tasks)) {
 376:                 $result->tasks = $tasks;
 377:             }
 378:         } catch (Exception $e) {
 379:             $GLOBALS['notification']->push($e, 'horde.error');
 380:         }
 381: 
 382:         return $result;
 383:     }
 384: 
 385:     /**
 386:      * TODO
 387:      */
 388:     public function getTask()
 389:     {
 390:         if (!$GLOBALS['registry']->hasMethod('tasks/getTask') ||
 391:             !isset($this->_vars->id) ||
 392:             !isset($this->_vars->list)) {
 393:             return false;
 394:         }
 395: 
 396:         $result = new stdClass;
 397:         try {
 398:             $task = $GLOBALS['registry']->tasks->getTask($this->_vars->list, $this->_vars->id);
 399:             if ($task) {
 400:                 $result->task = $task->toJson(true, $GLOBALS['prefs']->getValue('twentyFour') ? 'H:i' : 'h:i A');
 401:             } else {
 402:                 $GLOBALS['notification']->push(_("The requested task was not found."), 'horde.error');
 403:             }
 404:         } catch (Exception $e) {
 405:             $GLOBALS['notification']->push($e, 'horde.error');
 406:         }
 407: 
 408:         return $result;
 409:     }
 410: 
 411:     /**
 412:      * TODO
 413:      */
 414:     public function saveTask()
 415:     {
 416:         if (!$GLOBALS['registry']->hasMethod('tasks/updateTask') ||
 417:             !$GLOBALS['registry']->hasMethod('tasks/addTask')) {
 418:             return false;
 419:         }
 420: 
 421:         $id = $this->_vars->task_id;
 422:         $list = $this->_vars->old_tasklist;
 423:         $task = $this->_vars->task;
 424:         $result = $this->_signedResponse('tasklists|tasks/' . $task['tasklist']);
 425: 
 426:         $due = trim($task['due_date'] . ' ' . $task['due_time']);
 427:         if (!empty($due)) {
 428:             try {
 429:                 $due = Kronolith::parseDate($due);
 430:                 $task['due'] = $due->timestamp();
 431:             } catch (Exception $e) {
 432:                 $GLOBALS['notification']->push($e, 'horde.error');
 433:                 return $result;
 434:             }
 435:         }
 436: 
 437:         if ($task['alarm']['on']) {
 438:             $value = $task['alarm']['value'];
 439:             $unit = $task['alarm']['unit'];
 440:             if ($value == 0) {
 441:                 $value = $unit = 1;
 442:             }
 443:             $task['alarm'] = $value * $unit;
 444:             if (isset($task['alarm_methods']) && isset($task['methods'])) {
 445:                 foreach (array_keys($task['methods']) as $method) {
 446:                     if (!in_array($method, $task['alarm_methods'])) {
 447:                         unset($task['methods'][$method]);
 448:                     }
 449:                 }
 450:                 foreach ($task['alarm_methods'] as $method) {
 451:                     if (!isset($task['methods'][$method])) {
 452:                         $task['methods'][$method] = array();
 453:                     }
 454:                 }
 455:             } else {
 456:                 $task['methods'] = array();
 457:             }
 458:         } else {
 459:             $task['alarm'] = 0;
 460:             $task['methods'] = array();
 461:         }
 462:         unset($task['alarm_methods']);
 463: 
 464:         if (!isset($task['completed'])) {
 465:             $task['completed'] = false;
 466:         }
 467: 
 468:         try {
 469:             $ids = ($id && $list)
 470:                 ? $GLOBALS['registry']->tasks->updateTask($list, $id, $task)
 471:                 : $GLOBALS['registry']->tasks->addTask($task);
 472:             if (!$id) {
 473:                 $id = $ids[0];
 474:             }
 475:             $task = $GLOBALS['registry']->tasks->getTask($task['tasklist'], $id);
 476:             $result->tasks = array($id => $task->toJson(false, $GLOBALS['prefs']->getValue('twentyFour') ? 'H:i' : 'h:i A'));
 477:             $result->type = $task->completed ? 'complete' : 'incomplete';
 478:             $result->list = $task->tasklist;
 479:         } catch (Exception $e) {
 480:             $GLOBALS['notification']->push($e, 'horde.error');
 481:             return $result;
 482:         }
 483: 
 484:         if ($due &&
 485:             $kronolith_driver = $this->_getDriver('tasklists|tasks/' . $task->tasklist)) {
 486:             try {
 487:                 $event = $kronolith_driver->getEvent('_tasks' . $id);
 488:                 $end = clone $due;
 489:                 $end->hour = 23;
 490:                 $end->min = $end->sec = 59;
 491:                 $start = clone $due;
 492:                 $start->hour = $start->min = $start->sec = 0;
 493:                 $events = array();
 494:                 Kronolith::addEvents($events, $event, $start, $end, true, true);
 495:                 if (count($events)) {
 496:                     $result->events = $events;
 497:                 }
 498:             } catch (Horde_Exception_NotFound $e) {
 499:             } catch (Exception $e) {
 500:                 $GLOBALS['notification']->push($e, 'horde.error');
 501:             }
 502:         }
 503: 
 504:         return $result;
 505:     }
 506: 
 507:     /**
 508:      * TODO
 509:      */
 510:     public function deleteTask()
 511:     {
 512:         $result = new stdClass;
 513: 
 514:         if (!$GLOBALS['registry']->hasMethod('tasks/deleteTask') ||
 515:             !isset($this->_vars->id) ||
 516:             !isset($this->_vars->list)) {
 517:             return $result;
 518:         }
 519: 
 520:         try {
 521:             $GLOBALS['registry']->tasks->deleteTask($this->_vars->list, $this->_vars->id);
 522:             $result->deleted = true;
 523:         } catch (Exception $e) {
 524:             $GLOBALS['notification']->push($e, 'horde.error');
 525:         }
 526: 
 527:         return $result;
 528:     }
 529: 
 530:     /**
 531:      * TODO
 532:      */
 533:     public function toggleCompletion()
 534:     {
 535:         $result = new stdClass;
 536: 
 537:         if (!$GLOBALS['registry']->hasMethod('tasks/toggleCompletion')) {
 538:             return $result;
 539:         }
 540: 
 541:         try {
 542:             $GLOBALS['registry']->tasks->toggleCompletion($this->_vars->id, $this->_vars->list);
 543:             $result->toggled = true;
 544:         } catch (Exception $e) {
 545:             $GLOBALS['notification']->push($e, 'horde.error');
 546:         }
 547: 
 548:         return $result;
 549:     }
 550: 
 551:     /**
 552:      * Generate a list of most frequently used tags for the current user.
 553:      */
 554:     public function listTopTags()
 555:     {
 556:         $this->notify = false;
 557:         $tagger = new Kronolith_Tagger();
 558:         $result = new stdClass;
 559:         $result->tags = array();
 560:         $tags = $tagger->getCloud($GLOBALS['registry']->getAuth(), 10);
 561:         foreach ($tags as $tag) {
 562:             $result->tags[] = $tag['tag_name'];
 563:         }
 564:         return $result;
 565:     }
 566: 
 567:     /**
 568:      * TODO
 569:      */
 570:     public function getFreeBusy()
 571:     {
 572:         $result = new stdClass;
 573:         try {
 574:             $result->fb = Kronolith_FreeBusy::get($this->_vars->email, true);
 575:         } catch (Exception $e) {
 576:             $GLOBALS['notification']->push($e->getMessage(), 'horde.warning');
 577:         }
 578:         return $result;
 579:     }
 580: 
 581:     /**
 582:      * TODO
 583:      */
 584:     public function searchCalendars()
 585:     {
 586:         $result = new stdClass;
 587:         $result->events = 'Searched for calendars: ' . $this->_vars->title;
 588:         return $result;
 589:     }
 590: 
 591:     /**
 592:      * TODO
 593:      */
 594:     public function saveCalendar()
 595:     {
 596:         $calendar_id = $this->_vars->calendar;
 597:         $result = new stdClass;
 598: 
 599:         switch ($this->_vars->type) {
 600:         case 'internal':
 601:             $info = array();
 602:             foreach (array('name', 'color', 'description', 'tags') as $key) {
 603:                 $info[$key] = $this->_vars->$key;
 604:             }
 605: 
 606:             // Create a calendar.
 607:             if (!$calendar_id) {
 608:                 if (!$GLOBALS['registry']->getAuth() ||
 609:                     $GLOBALS['prefs']->isLocked('default_share')) {
 610:                     return $result;
 611:                 }
 612:                 try {
 613:                     $calendar = Kronolith::addShare($info);
 614:                     Kronolith::readPermsForm($calendar);
 615:                     if ($calendar->hasPermission($GLOBALS['registry']->getAuth(), Horde_Perms::SHOW)) {
 616:                         $wrapper = new Kronolith_Calendar_Internal(array('share' => $calendar));
 617:                         $result->saved = true;
 618:                         $result->id = $calendar->getName();
 619:                         $result->calendar = $wrapper->toHash();
 620:                     }
 621:                 } catch (Exception $e) {
 622:                     $GLOBALS['notification']->push($e, 'horde.error');
 623:                     return $result;
 624:                 }
 625:                 $GLOBALS['notification']->push(sprintf(_("The calendar \"%s\" has been created."), $info['name']), 'horde.success');
 626:                 break;
 627:             }
 628: 
 629:             // Update a calendar.
 630:             try {
 631:                 $calendar = $GLOBALS['kronolith_shares']->getShare($calendar_id);
 632:                 $original_name = $calendar->get('name');
 633:                 $original_owner = $calendar->get('owner');
 634:                 Kronolith::updateShare($calendar, $info);
 635:                 Kronolith::readPermsForm($calendar);
 636:                 if ($calendar->get('owner') != $original_owner) {
 637:                     $result->deleted = true;
 638:                 }
 639:                 if ($calendar->hasPermission($GLOBALS['registry']->getAuth(), Horde_Perms::SHOW)) {
 640:                     $wrapper = new Kronolith_Calendar_Internal(array('share' => $calendar));
 641:                     $result->saved = true;
 642:                     $result->calendar = $wrapper->toHash();
 643:                 }
 644:             } catch (Exception $e) {
 645:                 $GLOBALS['notification']->push($e, 'horde.error');
 646:                 return $result;
 647: 
 648:             }
 649:             if ($calendar->get('name') != $original_name) {
 650:                 $GLOBALS['notification']->push(sprintf(_("The calendar \"%s\" has been renamed to \"%s\"."), $original_name, $calendar->get('name')), 'horde.success');
 651:             } else {
 652:                 $GLOBALS['notification']->push(sprintf(_("The calendar \"%s\" has been saved."), $original_name), 'horde.success');
 653:             }
 654:             break;
 655: 
 656:         case 'tasklists':
 657:             $calendar = array();
 658:             foreach (array('name', 'color', 'description') as $key) {
 659:                 $calendar[$key] = $this->_vars->$key;
 660:             }
 661: 
 662:             // Create a task list.
 663:             if (!$calendar_id) {
 664:                 if (!$GLOBALS['registry']->getAuth() ||
 665:                     $GLOBALS['prefs']->isLocked('default_share')) {
 666:                     return $result;
 667:                 }
 668:                 try {
 669:                     $tasklistId = $GLOBALS['registry']->tasks->addTasklist($calendar['name'], $calendar['description'], $calendar['color']);
 670:                     $tasklists = $GLOBALS['registry']->tasks->listTasklists(true);
 671:                     if (!isset($tasklists[$tasklistId])) {
 672:                         $GLOBALS['notification']->push(_("Added task list not found."), 'horde.error');
 673:                         return $result;
 674:                     }
 675:                     $tasklist = $tasklists[$tasklistId];
 676:                     Kronolith::readPermsForm($tasklist);
 677:                     if ($tasklist->hasPermission($GLOBALS['registry']->getAuth(), Horde_Perms::SHOW)) {
 678:                         $wrapper = new Kronolith_Calendar_External_Tasks(array('api' => 'tasks', 'name' => $tasklistId, 'share' => $tasklist));
 679: 
 680:                         // Update external calendars caches.
 681:                         $all_external = $GLOBALS['session']->get('kronolith', 'all_external_calendars');
 682:                         $all_external[] = array('a' => 'tasks', 'n' => $tasklistId, 'd' => $tasklist->get('name'));
 683:                         $GLOBALS['session']->set('kronolith', 'all_external_calendars', $all_external);
 684:                         $GLOBALS['display_external_calendars'][] = 'tasks/' . $tasklistId;
 685:                         $GLOBALS['prefs']->setValue('display_external_cals', serialize($GLOBALS['display_external_calendars']));
 686:                         $GLOBALS['all_external_calendars']['tasks/' . $tasklistId] = $wrapper;
 687: 
 688:                         $result->saved = true;
 689:                         $result->id = 'tasks/' . $tasklistId;
 690:                         $result->calendar = $wrapper->toHash();
 691:                     }
 692:                 } catch (Exception $e) {
 693:                     $GLOBALS['notification']->push($e, 'horde.error');
 694:                     return $result;
 695:                 }
 696:                 $GLOBALS['notification']->push(sprintf(_("The task list \"%s\" has been created."), $calendar['name']), 'horde.success');
 697:                 break;
 698:             }
 699: 
 700:             // Update a task list.
 701:             $calendar_id = substr($calendar_id, 6);
 702:             try {
 703:                 $GLOBALS['registry']->tasks->updateTasklist($calendar_id, $calendar);
 704:                 $tasklists = $GLOBALS['registry']->tasks->listTasklists(true, Horde_Perms::EDIT);
 705:                 $tasklist = $tasklists[$calendar_id];
 706:                 $original_owner = $tasklist->get('owner');
 707:                 Kronolith::readPermsForm($tasklist);
 708:                 if ($tasklist->get('owner') != $original_owner) {
 709:                     $result->deleted = true;
 710:                 }
 711:                 if ($tasklist->hasPermission($GLOBALS['registry']->getAuth(), Horde_Perms::SHOW)) {
 712:                     $wrapper = new Kronolith_Calendar_External_Tasks(array('api' => 'tasks', 'name' => $calendar_id, 'share' => $tasklist));
 713:                     $result->saved = true;
 714:                     $result->calendar = $wrapper->toHash();
 715:                 }
 716:             } catch (Exception $e) {
 717:                 $GLOBALS['notification']->push($e, 'horde.error');
 718:                 return $result;
 719:             }
 720:             if ($tasklist->get('name') != $calendar['name']) {
 721:                 $GLOBALS['notification']->push(sprintf(_("The task list \"%s\" has been renamed to \"%s\"."), $tasklist->get('name'), $calendar['name']), 'horde.success');
 722:             } else {
 723:                 $GLOBALS['notification']->push(sprintf(_("The task list \"%s\" has been saved."), $tasklist->get('name')), 'horde.success');
 724:             }
 725:             break;
 726: 
 727:         case 'remote':
 728:             $calendar = array();
 729:             foreach (array('name', 'desc', 'url', 'color', 'user', 'password') as $key) {
 730:                 $calendar[$key] = $this->_vars->$key;
 731:             }
 732:             try {
 733:                 Kronolith::subscribeRemoteCalendar($calendar, $calendar_id);
 734:             } catch (Exception $e) {
 735:                 $GLOBALS['notification']->push($e, 'horde.error');
 736:                 return $result;
 737:             }
 738:             if ($calendar_id) {
 739:                 $GLOBALS['notification']->push(sprintf(_("The calendar \"%s\" has been saved."), $calendar['name']), 'horde.success');
 740:             } else {
 741:                 $GLOBALS['notification']->push(sprintf(_("You have been subscribed to \"%s\" (%s)."), $calendar['name'], $calendar['url']), 'horde.success');
 742:                 $result->id = $calendar['url'];
 743:             }
 744:             $wrapper = new Kronolith_Calendar_Remote($calendar);
 745:             $result->saved = true;
 746:             $result->calendar = $wrapper->toHash();
 747:             break;
 748:         }
 749: 
 750:         return $result;
 751:     }
 752: 
 753:     /**
 754:      * TODO
 755:      */
 756:     public function deleteCalendar()
 757:     {
 758:         $calendar_id = $this->_vars->calendar;
 759:         $result = new stdClass;
 760: 
 761:         switch ($this->_vars->type) {
 762:         case 'internal':
 763:             try {
 764:                 $calendar = $GLOBALS['kronolith_shares']->getShare($calendar_id);
 765:             } catch (Exception $e) {
 766:                 $GLOBALS['notification']->push($e, 'horde.error');
 767:                 return $result;
 768:             }
 769:             try {
 770:                 Kronolith::deleteShare($calendar);
 771:             } catch (Exception $e) {
 772:                 $GLOBALS['notification']->push(sprintf(_("Unable to delete \"%s\": %s"), $calendar->get('name'), $e->getMessage()), 'horde.error');
 773:                 return $result;
 774:             }
 775:             $GLOBALS['notification']->push(sprintf(_("The calendar \"%s\" has been deleted."), $calendar->get('name')), 'horde.success');
 776:             break;
 777: 
 778:         case 'tasklists':
 779:             $calendar_id = substr($calendar_id, 6);
 780:             $tasklists = $GLOBALS['registry']->tasks->listTasklists(true);
 781:             if (!isset($tasklists[$calendar_id])) {
 782:                 $GLOBALS['notification']->push(_("You are not allowed to delete this task list."), 'horde.error');
 783:                 return $result;
 784:             }
 785:             try {
 786:                 $GLOBALS['registry']->tasks->deleteTasklist($calendar_id);
 787:             } catch (Exception $e) {
 788:                 $GLOBALS['notification']->push(sprintf(_("Unable to delete \"%s\": %s"), $tasklists[$calendar_id]->get('name'), $e->getMessage()), 'horde.error');
 789:                 return $result;
 790:             }
 791:             $GLOBALS['notification']->push(sprintf(_("The task list \"%s\" has been deleted."), $tasklists[$calendar_id]->get('name')), 'horde.success');
 792:             break;
 793: 
 794:         case 'remote':
 795:             try {
 796:                 $deleted = Kronolith::unsubscribeRemoteCalendar($calendar_id);
 797:             } catch (Exception $e) {
 798:                 $GLOBALS['notification']->push($e, 'horde.error');
 799:                 return $result;
 800:             }
 801:             $GLOBALS['notification']->push(sprintf(_("You have been unsubscribed from \"%s\" (%s)."), $deleted['name'], $deleted['url']), 'horde.success');
 802:             break;
 803:         }
 804: 
 805:         $result->deleted = true;
 806: 
 807:         return $result;
 808:     }
 809: 
 810:     /**
 811:      * Returns the information for a shared internal calendar.
 812:      */
 813:     public function getCalendar()
 814:     {
 815:         $result = new stdClass;
 816:         if (!isset($GLOBALS['all_calendars'][$this->_vars->cal])) {
 817:             $GLOBALS['notification']->push(_("You are not allowed to view this calendar."), 'horde.error');
 818:             return $result;
 819:         }
 820:         $calendar = $GLOBALS['all_calendars'][$this->_vars->cal];
 821:         $tagger = Kronolith::getTagger();
 822:         $result->calendar = $calendar->toHash();
 823:         return $result;
 824:     }
 825: 
 826:     /**
 827:      * TODO
 828:      */
 829:     public function getRemoteInfo()
 830:     {
 831:         $params = array('timeout' => 15);
 832:         if ($user = $this->_vars->user) {
 833:             $params['user'] = $user;
 834:             $params['password'] = $this->_vars->password;
 835:         }
 836:         if (!empty($GLOBALS['conf']['http']['proxy']['proxy_host'])) {
 837:             $params['proxy'] = $GLOBALS['conf']['http']['proxy'];
 838:         }
 839: 
 840:         $result = new stdClass;
 841:         try {
 842:             $driver = $GLOBALS['injector']->getInstance('Kronolith_Factory_Driver')->create('Ical', $params);
 843:             $driver->open($this->_vars->url);
 844:             if ($driver->isCalDAV()) {
 845:                 $result->success = true;
 846:                 // TODO: find out how to retrieve calendar information via CalDAV.
 847:             } else {
 848:                 $ical = $driver->getRemoteCalendar(false);
 849:                 $result->success = true;
 850:                 try {
 851:                     $name = $ical->getAttribute('X-WR-CALNAME');
 852:                     $result->name = $name;
 853:                 } catch (Horde_Icalendar_Exception $e) {}
 854:                 try {
 855:                     $desc = $ical->getAttribute('X-WR-CALDESC');
 856:                     $result->desc = $desc;
 857:                 } catch (Horde_Icalendar_Exception $e) {}
 858:             }
 859:         } catch (Exception $e) {
 860:             if ($e->getCode() == 401) {
 861:                 $result->auth = true;
 862:             } else {
 863:                 $GLOBALS['notification']->push($e, 'horde.error');
 864:             }
 865:         }
 866: 
 867:         return $result;
 868:     }
 869: 
 870:     /**
 871:      * TODO
 872:      */
 873:     public function saveCalPref()
 874:     {
 875:         return false;
 876:     }
 877: 
 878:     /**
 879:      * Returns the driver object for a calendar.
 880:      *
 881:      * @param string $cal  A calendar string in the format "type|name".
 882:      *
 883:      * @return Kronolith_Driver|boolean  A driver instance or false on failure.
 884:      */
 885:     protected function _getDriver($cal)
 886:     {
 887:         list($driver, $calendar) = explode('|', $cal);
 888:         if ($driver == 'internal' &&
 889:             !Kronolith::hasPermission($calendar, Horde_Perms::SHOW)) {
 890:             $GLOBALS['notification']->push(_("Permission Denied"), 'horde.error');
 891:             return false;
 892:         }
 893:         try {
 894:             $kronolith_driver = Kronolith::getDriver($driver, $calendar);
 895:         } catch (Exception $e) {
 896:             $GLOBALS['notification']->push($e, 'horde.error');
 897:             return false;
 898:         }
 899:         if ($driver == 'remote') {
 900:             $kronolith_driver->setParam('timeout', 15);
 901:         }
 902:         return $kronolith_driver;
 903:     }
 904: 
 905:     /**
 906:      * Saves an event and returns a signed result object including the saved
 907:      * event.
 908:      *
 909:      * @param Kronolith_Event $event     An event object.
 910:      * @param Kronolith_Event $original  If $event is an exception, this should
 911:      *                                   be set to the original event.
 912:      * @param object $attributes         The attributes sent by the client.
 913:      *                                   Expected to contain cstart and cend.
 914:      *
 915:      * @return object  The result object.
 916:      */
 917:     protected function _saveEvent(Kronolith_Event $event,
 918:                                   Kronolith_Event $original = null,
 919:                                   $attributes = null)
 920:     {
 921:         if ($this->_vars->targetcalendar) {
 922:             $cal = $this->_vars->targetcalendar;
 923:         } elseif ($this->_vars->cal) {
 924:             $cal = $this->_vars->cal;
 925:         } else {
 926:             $cal = $event->calendarType . '|' . $event->calendar;
 927:         }
 928:         $result = $this->_signedResponse($cal);
 929:         if (!$this->_vars->view_start || !$this->_vars->view_end) {
 930:             $result->events = array();
 931:             return $result;
 932:         }
 933: 
 934:         try {
 935:             $event->save();
 936:             $end = new Horde_Date($this->_vars->view_end);
 937:             $end->hour = 23;
 938:             $end->min = $end->sec = 59;
 939:             $events = array();
 940:             Kronolith::addEvents($events, $event,
 941:                                  new Horde_Date($this->_vars->view_start),
 942:                                  $end, true, true);
 943: 
 944: 
 945:             /* If this is an exception, we re-add the original event as well
 946:              * cstart and cend are the cacheStart and cacheEnd dates from the
 947:              * client. */
 948:             if (!empty($original)) {
 949:                 Kronolith::addEvents($events, $original,
 950:                                      new Horde_Date($attributes->cstart),
 951:                                      new Horde_Date($attributes->cend),
 952:                                      true, true);
 953:             }
 954:             $result->events = count($events) ? $events : array();
 955:         } catch (Exception $e) {
 956:             $GLOBALS['notification']->push($e, 'horde.error');
 957:         }
 958:         return $result;
 959:     }
 960: 
 961:     /**
 962:      * Creates a result object with the signature of the current request.
 963:      *
 964:      * @param string $calendar  A calendar id.
 965:      *
 966:      * @return object  The result object.
 967:      */
 968:     protected function _signedResponse($calendar)
 969:     {
 970:         $result = new stdClass;
 971:         $result->cal = $calendar;
 972:         $result->view = $this->_vars->view;
 973:         $result->sig = $this->_vars->sig;
 974:         return $result;
 975:     }
 976: 
 977:     /**
 978:      * Creates a new event that represents an exception to a recurring event.
 979:      * Causes an exception to be added to the original event as well.
 980:      *
 981:      * @param Kronolith_Event $event  The recurring event.
 982:      * @param object $attributes      The attributes passed from the client.
 983:      *                                Expected to contain rstart and rend.
 984:      *
 985:      * @return Kronolith_Event  The event representing the exception, with
 986:      *                          the start/end times set the same as the original
 987:      *                          occurence.
 988:      */
 989:     protected function _createExceptionEvent(Kronolith_Event $event, $attributes)
 990:     {
 991:         // Add the exception to the original event
 992:         if ($attributes->rstart) {
 993:             $rstart = new Horde_Date($attributes->rstart);
 994:             $rstart->setTimezone($event->start->timezone);
 995:             $rend = new Horde_Date($attributes->rend);
 996:             $rend->setTimezone($event->end->timezone);
 997:         } else {
 998:             $rstart = new Horde_Date($attributes->rday);
 999:             $rstart->setTimezone($event->start->timezone);
1000:             $rstart->hour = $event->start->hour;
1001:             $rstart->min = $event->start->min;
1002:             $rend = $rstart->add($event->getDuration);
1003:             $rend->setTimezone($event->end->timezone);
1004:             $rend->hour = $event->end->hour;
1005:             $rend->min = $event->end->min;
1006:         }
1007: 
1008:         $event->recurrence->addException($rstart->year, $rstart->month, $rstart->mday);
1009:         $event->save();
1010:         $uid = $event->uid;
1011:         $otime = $event->start->strftime('%T');
1012: 
1013:         // Create new event for the exception
1014:         $nevent = $event->getDriver()->getEvent();
1015:         $nevent->baseid = $uid;
1016:         $nevent->exceptionoriginaldate = new Horde_Date($rstart->strftime('%Y-%m-%d') . 'T' . $otime);
1017:         $nevent->creator = $event->creator;
1018:         $nevent->title = $event->title;
1019:         $nevent->description = $event->description;
1020:         $nevent->location = $event->location;
1021:         $nevent->private = $event->private;
1022:         $nevent->url = $event->url;
1023:         $nevent->status = $event->status;
1024:         $nevent->attendees = $event->attendees;
1025:         //@TODO: add resources - need a Kronolith_Event::setResource() method.
1026:         $nevent->start = $rstart;
1027:         $nevent->end = $rend;
1028:         $nevent->initialized = true;
1029: 
1030:         return $nevent;
1031:     }
1032: }
1033: 
API documentation generated by ApiGen