1<?php 2 3/** 4 * Driver interface for the Tasklist plugin 5 * 6 * @version @package_version@ 7 * @author Thomas Bruederli <bruederli@kolabsys.com> 8 * 9 * Copyright (C) 2012, Kolab Systems AG <contact@kolabsys.com> 10 * 11 * This program is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Affero General Public License as 13 * published by the Free Software Foundation, either version 3 of the 14 * License, or (at your option) any later version. 15 * 16 * This program is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU Affero General Public License for more details. 20 * 21 * You should have received a copy of the GNU Affero General Public License 22 * along with this program. If not, see <http://www.gnu.org/licenses/>. 23 */ 24 25 /** 26 * Struct of an internal task object how it is passed from/to the driver classes: 27 * 28 * $task = array( 29 * 'id' => 'Task ID used for editing', // must be unique for the current user 30 * 'parent_id' => 'ID of parent task', // null if top-level task 31 * 'uid' => 'Unique identifier of this task', 32 * 'list' => 'Task list identifier to add the task to or where the task is stored', 33 * 'changed' => <DateTime>, // Last modification date/time of the record 34 * 'title' => 'Event title/summary', 35 * 'description' => 'Event description', 36 * 'tags' => array(), // List of tags for this task 37 * 'date' => 'Due date', // as string of format YYYY-MM-DD or null if no date is set 38 * 'time' => 'Due time', // as string of format hh::ii or null if no due time is set 39 * 'startdate' => 'Start date' // Delay start of the task until that date 40 * 'starttime' => 'Start time' // ...and time 41 * 'categories' => 'Task category', 42 * 'flagged' => 'Boolean value whether this record is flagged', 43 * 'complete' => 'Float value representing the completeness state (range 0..1)', 44 * 'status' => 'Task status string according to (NEEDS-ACTION, IN-PROCESS, COMPLETED, CANCELLED) RFC 2445', 45 * 'valarms' => array( // List of reminders (new format), each represented as a hash array: 46 * array( 47 * 'trigger' => '-PT90M', // ISO 8601 period string prefixed with '+' or '-', or DateTime object 48 * 'action' => 'DISPLAY|EMAIL|AUDIO', 49 * 'duration' => 'PT15M', // ISO 8601 period string 50 * 'repeat' => 0, // number of repetitions 51 * 'description' => '', // text to display for DISPLAY actions 52 * 'summary' => '', // message text for EMAIL actions 53 * 'attendees' => array(), // list of email addresses to receive alarm messages 54 * ), 55 * ), 56 * 'recurrence' => array( // Recurrence definition according to iCalendar (RFC 2445) specification as list of key-value pairs 57 * 'FREQ' => 'DAILY|WEEKLY|MONTHLY|YEARLY', 58 * 'INTERVAL' => 1...n, 59 * 'UNTIL' => DateTime, 60 * 'COUNT' => 1..n, // number of times 61 * 'RDATE' => array(), // complete list of DateTime objects denoting individual repeat dates 62 * ), 63 * '_fromlist' => 'List identifier where the task was stored before', 64 * ); 65 */ 66 67/** 68 * Driver interface for the Tasklist plugin 69 */ 70abstract class tasklist_driver 71{ 72 // features supported by the backend 73 public $alarms = false; 74 public $attachments = false; 75 public $attendees = false; 76 public $undelete = false; // task undelete action 77 public $sortable = false; 78 public $alarm_types = array('DISPLAY'); 79 public $alarm_absolute = true; 80 public $last_error; 81 82 const FILTER_ALL = 0; 83 const FILTER_WRITEABLE = 1; 84 const FILTER_INSERTABLE = 2; 85 const FILTER_ACTIVE = 4; 86 const FILTER_PERSONAL = 8; 87 const FILTER_PRIVATE = 16; 88 const FILTER_CONFIDENTIAL = 32; 89 const FILTER_SHARED = 64; 90 91 92 /** 93 * Get a list of available task lists from this source 94 * @param integer Bitmask defining filter criterias. 95 * See FILTER_* constants for possible values. 96 */ 97 abstract function get_lists($filter = 0); 98 99 /** 100 * Create a new list assigned to the current user 101 * 102 * @param array Hash array with list properties 103 * name: List name 104 * color: The color of the list 105 * showalarms: True if alarms are enabled 106 * @return mixed ID of the new list on success, False on error 107 */ 108 abstract function create_list(&$prop); 109 110 /** 111 * Update properties of an existing tasklist 112 * 113 * @param array Hash array with list properties 114 * id: List Identifier 115 * name: List name 116 * color: The color of the list 117 * showalarms: True if alarms are enabled (if supported) 118 * @return boolean True on success, Fales on failure 119 */ 120 abstract function edit_list(&$prop); 121 122 /** 123 * Set active/subscribed state of a list 124 * 125 * @param array Hash array with list properties 126 * id: List Identifier 127 * active: True if list is active, false if not 128 * @return boolean True on success, Fales on failure 129 */ 130 abstract function subscribe_list($prop); 131 132 /** 133 * Delete the given list with all its contents 134 * 135 * @param array Hash array with list properties 136 * id: list Identifier 137 * @return boolean True on success, Fales on failure 138 */ 139 abstract function delete_list($prop); 140 141 /** 142 * Search for shared or otherwise not listed tasklists the user has access 143 * 144 * @param string Search string 145 * @param string Section/source to search 146 * @return array List of tasklists 147 */ 148 abstract function search_lists($query, $source); 149 150 /** 151 * Get number of tasks matching the given filter 152 * 153 * @param array List of lists to count tasks of 154 * @return array Hash array with counts grouped by status (all|flagged|completed|today|tomorrow|nodate) 155 */ 156 abstract function count_tasks($lists = null); 157 158 /** 159 * Get all task records matching the given filter 160 * 161 * @param array Hash array with filter criterias: 162 * - mask: Bitmask representing the filter selection (check against tasklist::FILTER_MASK_* constants) 163 * - from: Date range start as string (Y-m-d) 164 * - to: Date range end as string (Y-m-d) 165 * - search: Search query string 166 * @param array List of lists to get tasks from 167 * @return array List of tasks records matchin the criteria 168 */ 169 abstract function list_tasks($filter, $lists = null); 170 171 /** 172 * Get a list of tags to assign tasks to 173 * 174 * @return array List of tags 175 */ 176 abstract function get_tags(); 177 178 /** 179 * Get a list of pending alarms to be displayed to the user 180 * 181 * @param integer Current time (unix timestamp) 182 * @param mixed List of list IDs to show alarms for (either as array or comma-separated string) 183 * @return array A list of alarms, each encoded as hash array with task properties 184 * id: Task identifier 185 * uid: Unique identifier of this task 186 * date: Task due date 187 * time: Task due time 188 * title: Task title/summary 189 */ 190 abstract function pending_alarms($time, $lists = null); 191 192 /** 193 * (User) feedback after showing an alarm notification 194 * This should mark the alarm as 'shown' or snooze it for the given amount of time 195 * 196 * @param string Task identifier 197 * @param integer Suspend the alarm for this number of seconds 198 */ 199 abstract function dismiss_alarm($id, $snooze = 0); 200 201 /** 202 * Remove alarm dismissal or snooze state 203 * 204 * @param string Task identifier 205 */ 206 abstract public function clear_alarms($id); 207 208 /** 209 * Return data of a specific task 210 * 211 * @param mixed Hash array with task properties or task UID 212 * @param integer Bitmask defining filter criterias for folders. 213 * See FILTER_* constants for possible values. 214 * 215 * @return array Hash array with task properties or false if not found 216 */ 217 abstract public function get_task($prop, $filter = 0); 218 219 /** 220 * Get decendents of the given task record 221 * 222 * @param mixed Hash array with task properties or task UID 223 * @param boolean True if all childrens children should be fetched 224 * @return array List of all child task IDs 225 */ 226 abstract public function get_childs($prop, $recursive = false); 227 228 /** 229 * Add a single task to the database 230 * 231 * @param array Hash array with task properties (see header of this file) 232 * @return mixed New event ID on success, False on error 233 */ 234 abstract function create_task($prop); 235 236 /** 237 * Update an task entry with the given data 238 * 239 * @param array Hash array with task properties (see header of this file) 240 * @return boolean True on success, False on error 241 */ 242 abstract function edit_task($prop); 243 244 /** 245 * Move a single task to another list 246 * 247 * @param array Hash array with task properties: 248 * id: Task identifier 249 * list: New list identifier to move to 250 * _fromlist: Previous list identifier 251 * @return boolean True on success, False on error 252 */ 253 abstract function move_task($prop); 254 255 /** 256 * Remove a single task from the database 257 * 258 * @param array Hash array with task properties: 259 * id: Task identifier 260 * list: Tasklist identifer 261 * @param boolean Remove record irreversible (mark as deleted otherwise, if supported by the backend) 262 * @return boolean True on success, False on error 263 */ 264 abstract function delete_task($prop, $force = true); 265 266 /** 267 * Restores a single deleted task (if supported) 268 * 269 * @param array Hash array with task properties: 270 * id: Task identifier 271 * @return boolean True on success, False on error 272 */ 273 public function undelete_task($prop) 274 { 275 return false; 276 } 277 278 /** 279 * Get attachment properties 280 * 281 * @param string $id Attachment identifier 282 * @param array $task Hash array with event properties: 283 * id: Task identifier 284 * list: List identifier 285 * rev: Revision (optional) 286 * 287 * @return array Hash array with attachment properties: 288 * id: Attachment identifier 289 * name: Attachment name 290 * mimetype: MIME content type of the attachment 291 * size: Attachment size 292 */ 293 public function get_attachment($id, $task) { } 294 295 /** 296 * Get attachment body 297 * 298 * @param string $id Attachment identifier 299 * @param array $task Hash array with event properties: 300 * id: Task identifier 301 * list: List identifier 302 * rev: Revision (optional) 303 * 304 * @return string Attachment body 305 */ 306 public function get_attachment_body($id, $task) { } 307 308 /** 309 * Build a struct representing the given message reference 310 * 311 * @param object|string $uri_or_headers rcube_message_header instance holding the message headers 312 * or an URI from a stored link referencing a mail message. 313 * @param string $folder IMAP folder the message resides in 314 * 315 * @return array An struct referencing the given IMAP message 316 */ 317 public function get_message_reference($uri_or_headers, $folder = null) 318 { 319 // to be implemented by the derived classes 320 return false; 321 } 322 323 /** 324 * Find tasks assigned to a specified message 325 * 326 * @param object $message rcube_message_header instance 327 * @param string $folder IMAP folder the message resides in 328 * 329 * @param array List of linked task objects 330 */ 331 public function get_message_related_tasks($headers, $folder) 332 { 333 // to be implemented by the derived classes 334 return array(); 335 } 336 337 /** 338 * Helper method to determine whether the given task is considered "complete" 339 * 340 * @param array $task Hash array with event properties 341 * @return boolean True if complete, False otherwiese 342 */ 343 public function is_complete($task) 344 { 345 return ($task['complete'] >= 1.0 && empty($task['status'])) || $task['status'] === 'COMPLETED'; 346 } 347 348 /** 349 * Provide a list of revisions for the given task 350 * 351 * @param array $task Hash array with task properties: 352 * id: Task identifier 353 * list: List identifier 354 * 355 * @return array List of changes, each as a hash array: 356 * rev: Revision number 357 * type: Type of the change (create, update, move, delete) 358 * date: Change date 359 * user: The user who executed the change 360 * ip: Client IP 361 * mailbox: Destination list for 'move' type 362 */ 363 public function get_task_changelog($task) 364 { 365 return false; 366 } 367 368 /** 369 * Get a list of property changes beteen two revisions of a task object 370 * 371 * @param array $task Hash array with task properties: 372 * id: Task identifier 373 * list: List identifier 374 * @param mixed $rev1 Old Revision 375 * @param mixed $rev2 New Revision 376 * 377 * @return array List of property changes, each as a hash array: 378 * property: Revision number 379 * old: Old property value 380 * new: Updated property value 381 */ 382 public function get_task_diff($task, $rev1, $rev2) 383 { 384 return false; 385 } 386 387 /** 388 * Return full data of a specific revision of an event 389 * 390 * @param mixed $task UID string or hash array with task properties: 391 * id: Task identifier 392 * list: List identifier 393 * @param mixed $rev Revision number 394 * 395 * @return array Task object as hash array 396 * @see self::get_task() 397 */ 398 public function get_task_revison($task, $rev) 399 { 400 return false; 401 } 402 403 /** 404 * Command the backend to restore a certain revision of a task. 405 * This shall replace the current object with an older version. 406 * 407 * @param mixed $task UID string or hash array with task properties: 408 * id: Task identifier 409 * list: List identifier 410 * @param mixed $rev Revision number 411 * 412 * @return boolean True on success, False on failure 413 */ 414 public function restore_task_revision($task, $rev) 415 { 416 return false; 417 } 418 419 /** 420 * Build the edit/create form for lists. 421 * This gives the drivers the opportunity to add more list properties 422 * 423 * @param string The action called this form 424 * @param array Tasklist properties 425 * @param array List with form fields to be rendered 426 * 427 * @return string HTML content of the form 428 */ 429 public function tasklist_edit_form($action, $list, $formfields) 430 { 431 $table = new html_table(array('cols' => 2, 'class' => 'propform')); 432 433 foreach ($formfields as $col => $colprop) { 434 $label = !empty($colprop['label']) ? $colprop['label'] : $rcmail->gettext("$domain.$col"); 435 436 $table->add('title', html::label($colprop['id'], rcube::Q($label))); 437 $table->add(null, $colprop['value']); 438 } 439 440 return $table->show(); 441 } 442 443 /** 444 * Compose an URL for CalDAV access to the given list (if configured) 445 */ 446 public function tasklist_caldav_url($list) 447 { 448 $rcmail = rcube::get_instance(); 449 if (!empty($list['caldavuid']) && ($template = $rcmail->config->get('calendar_caldav_url', null))) { 450 return strtr($template, array( 451 '%h' => $_SERVER['HTTP_HOST'], 452 '%u' => urlencode($rcmail->get_user_name()), 453 '%i' => urlencode($list['caldavuid']), 454 '%n' => urlencode($list['editname']), 455 )); 456 } 457 458 return null; 459 } 460 461 /** 462 * Handler for user_delete plugin hook 463 * 464 * @param array Hash array with hook arguments 465 * @return array Return arguments for plugin hooks 466 */ 467 public function user_delete($args) 468 { 469 // TO BE OVERRIDDEN 470 return $args; 471 } 472} 473