1<?php 2/** 3 * Horde_ActiveSync_Message_Task:: 4 * 5 * Portions of this class were ported from the Z-Push project: 6 * File : wbxml.php 7 * Project : Z-Push 8 * Descr : WBXML mapping file 9 * 10 * Created : 01.10.2007 11 * 12 * � Zarafa Deutschland GmbH, www.zarafaserver.de 13 * This file is distributed under GPL-2.0. 14 * Consult COPYING file for details 15 * 16 * @license http://www.horde.org/licenses/gpl GPLv2 17 * 18 * @copyright 2010-2020 Horde LLC (http://www.horde.org) 19 * @author Michael J Rubinsky <mrubinsk@horde.org> 20 * @package ActiveSync 21 */ 22/** 23 * Horde_ActiveSync_Message_Task:: 24 * 25 * @license http://www.horde.org/licenses/gpl GPLv2 26 * 27 * @copyright 2010-2020 Horde LLC (http://www.horde.org) 28 * @author Michael J Rubinsky <mrubinsk@horde.org> 29 * @package ActiveSync 30 * 31 * @property boolean $complete Completion flag 32 * @property Horde_Date $datecompleted The date the task was completed, in UTC. 33 * @property Horde_Date $utcduedate The date this task is due, in UTC. 34 * @property integer $importance The importance flag. 35 * @property Horde_ActiveSync_Message_TaskRecurrence $recurrence 36 * The recurrence object. 37 * @property integer $sensitivity The sensitivity flag. 38 * @property Horde_Date $utcstartdate The date this task starts, in UTC. 39 * @property string $subject The task subject. 40 * @property array $categories An array of categories. 41 * @property string $body The task body (EAS Version < 12.0) 42 * @property boolean $bodytruncated Truncation flag (EAS Version < 12.0) 43 * @property Horde_ActiveSync_Message_AirSyncBaseBody $airsyncbasebody 44 * The task body (EAS Version >= 12.0) 45 */ 46class Horde_ActiveSync_Message_Task extends Horde_ActiveSync_Message_Base 47{ 48 /* POOMTASKS */ 49 const POOMTASKS_BODY = 'POOMTASKS:Body'; 50 const POOMTASKS_BODYSIZE = 'POOMTASKS:BodySize'; 51 const POOMTASKS_BODYTRUNCATED = 'POOMTASKS:BodyTruncated'; 52 const POOMTASKS_CATEGORIES = 'POOMTASKS:Categories'; 53 const POOMTASKS_CATEGORY = 'POOMTASKS:Category'; 54 const POOMTASKS_COMPLETE = 'POOMTASKS:Complete'; 55 const POOMTASKS_DATECOMPLETED = 'POOMTASKS:DateCompleted'; 56 const POOMTASKS_DUEDATE = 'POOMTASKS:DueDate'; 57 const POOMTASKS_UTCDUEDATE = 'POOMTASKS:UtcDueDate'; 58 const POOMTASKS_IMPORTANCE = 'POOMTASKS:Importance'; 59 const POOMTASKS_RECURRENCE = 'POOMTASKS:Recurrence'; 60 const POOMTASKS_TYPE = 'POOMTASKS:Type'; 61 const POOMTASKS_START = 'POOMTASKS:Start'; 62 const POOMTASKS_UNTIL = 'POOMTASKS:Until'; 63 const POOMTASKS_OCCURRENCES = 'POOMTASKS:Occurrences'; 64 const POOMTASKS_INTERVAL = 'POOMTASKS:Interval'; 65 const POOMTASKS_DAYOFWEEK = 'POOMTASKS:DayOfWeek'; 66 const POOMTASKS_DAYOFMONTH = 'POOMTASKS:DayOfMonth'; 67 const POOMTASKS_WEEKOFMONTH = 'POOMTASKS:WeekOfMonth'; 68 const POOMTASKS_MONTHOFYEAR = 'POOMTASKS:MonthOfYear'; 69 const POOMTASKS_REGENERATE = 'POOMTASKS:Regenerate'; 70 const POOMTASKS_DEADOCCUR = 'POOMTASKS:DeadOccur'; 71 const POOMTASKS_REMINDERSET = 'POOMTASKS:ReminderSet'; 72 const POOMTASKS_REMINDERTIME = 'POOMTASKS:ReminderTime'; 73 const POOMTASKS_SENSITIVITY = 'POOMTASKS:Sensitivity'; 74 const POOMTASKS_STARTDATE = 'POOMTASKS:StartDate'; 75 const POOMTASKS_UTCSTARTDATE = 'POOMTASKS:UtcStartDate'; 76 const POOMTASKS_SUBJECT = 'POOMTASKS:Subject'; 77 const POOMTASKS_RTF = 'POOMTASKS:Rtf'; 78 79 // EAS 12.0 80 const POOMTASKS_ORDINALDATE = 'POOMTASKS:OrdinalDate'; 81 const POOMTASKS_SUBORDINALDATE = 'POOMTASKS:SubOrdinalDate'; 82 83 // EAS 14 84 const POOMTASKS_CALENDARTYPE = 'POOMTASKS:CalendarType'; 85 const POOMTASKS_ISLEAPMONTH = 'POOMTASKS:IsLeapMonth'; 86 const POOMTASKS_FIRSTDAYOFWEEK = 'POOMTASKS:FirstDayOfWeek'; 87 88 const TASK_COMPLETE_TRUE = 1; 89 const TASK_COMPLETE_FALSE = 0; 90 91 const IMPORTANCE_LOW = 0; 92 const IMPORTANCE_NORMAL = 1; 93 const IMPORTANCE_HIGH = 2; 94 95 const REMINDER_SET_FALSE = 0; 96 const REMINDER_SET_TRUE = 1; 97 98 /** 99 * DOW mapping for DATE to MASK 100 * 101 * @var array 102 */ 103 protected $_dayOfWeekMap = array( 104 Horde_Date::DATE_SUNDAY => Horde_Date::MASK_SUNDAY, 105 Horde_Date::DATE_MONDAY => Horde_Date::MASK_MONDAY, 106 Horde_Date::DATE_TUESDAY => Horde_Date::MASK_TUESDAY, 107 Horde_Date::DATE_WEDNESDAY => Horde_Date::MASK_WEDNESDAY, 108 Horde_Date::DATE_THURSDAY => Horde_Date::MASK_THURSDAY, 109 Horde_Date::DATE_FRIDAY => Horde_Date::MASK_FRIDAY, 110 Horde_Date::DATE_SATURDAY => Horde_Date::MASK_SATURDAY, 111 ); 112 113 /** 114 * Property mapping 115 * 116 * @var array 117 */ 118 protected $_mapping = array ( 119 self::POOMTASKS_COMPLETE => array (self::KEY_ATTRIBUTE => 'complete'), 120 self::POOMTASKS_DATECOMPLETED => array (self::KEY_ATTRIBUTE => 'datecompleted', self::KEY_TYPE => self::TYPE_DATE_DASHES), 121 self::POOMTASKS_DUEDATE => array (self::KEY_ATTRIBUTE => 'duedate', self::KEY_TYPE => self::TYPE_DATE_LOCAL), 122 self::POOMTASKS_UTCDUEDATE => array (self::KEY_ATTRIBUTE => 'utcduedate', self::KEY_TYPE => self::TYPE_DATE_DASHES), 123 self::POOMTASKS_IMPORTANCE => array (self::KEY_ATTRIBUTE => 'importance'), 124 self::POOMTASKS_RECURRENCE => array (self::KEY_ATTRIBUTE => 'recurrence', self::KEY_TYPE => 'Horde_ActiveSync_Message_TaskRecurrence'), 125 self::POOMTASKS_REMINDERSET => array (self::KEY_ATTRIBUTE => 'reminderset'), 126 self::POOMTASKS_REMINDERTIME => array (self::KEY_ATTRIBUTE => 'remindertime', self::KEY_TYPE => self::TYPE_DATE_DASHES), 127 self::POOMTASKS_SENSITIVITY => array (self::KEY_ATTRIBUTE => 'sensitiviy'), 128 self::POOMTASKS_STARTDATE => array (self::KEY_ATTRIBUTE => 'startdate', self::KEY_TYPE => self::TYPE_DATE_LOCAL), 129 self::POOMTASKS_UTCSTARTDATE => array (self::KEY_ATTRIBUTE => 'utcstartdate', self::KEY_TYPE => self::TYPE_DATE_DASHES), 130 self::POOMTASKS_SUBJECT => array (self::KEY_ATTRIBUTE => 'subject'), 131 self::POOMTASKS_CATEGORIES => array (self::KEY_ATTRIBUTE => 'categories', self::KEY_VALUES => self::POOMTASKS_CATEGORY), 132 ); 133 134 /** 135 * Property values. 136 * 137 * @var array 138 */ 139 protected $_properties = array( 140 'subject' => false, 141 'importance' => false, 142 'categories' => array(), 143 'startdate' => false, 144 'duedate' => false, 145 'utcduedate' => false, 146 'complete' => false, 147 'datecompleted' => false, 148 'remindertime' => false, 149 'sensitiviy' => false, 150 'reminderset' => false, 151 'deadoccur' => false, 152 'recurrence' => false, 153 'regenerate' => false, 154 'sensitiviy' => false, 155 'utcstartdate' => false, 156 ); 157 158 /** 159 * Const'r 160 * 161 * @see Horde_ActiveSync_Message_Base::__construct() 162 */ 163 public function __construct(array $options = array()) 164 { 165 parent::__construct($options); 166 if ($this->_version < Horde_ActiveSync::VERSION_TWELVE) { 167 $this->_mapping += array( 168 self::POOMTASKS_BODY => array(self::KEY_ATTRIBUTE => 'body'), 169 self::POOMTASKS_RTF => array(self::KEY_ATTRIBUTE => 'rtf'), 170 self::POOMTASKS_BODYTRUNCATED => array(self::KEY_ATTRIBUTE => 'bodytruncated') 171 ); 172 173 $this->_properties += array( 174 'body' => false, 175 'rtf' => false, 176 'bodytruncated' => 0, 177 ); 178 } else { 179 $this->_mapping += array( 180 Horde_ActiveSync::AIRSYNCBASE_BODY => array(self::KEY_ATTRIBUTE => 'airsyncbasebody', self::KEY_TYPE=> 'Horde_ActiveSync_Message_AirSyncBaseBody'), 181 ); 182 183 $this->_properties += array( 184 'airsyncbasebody' => false, 185 ); 186 } 187 } 188 189 /** 190 * Set the importance 191 * 192 * @param integer $importance A IMPORTANCE_* flag 193 */ 194 public function setImportance($importance) 195 { 196 if (is_null($importance)) { 197 $importance = self::IMPORTANCE_NORMAL; 198 } 199 200 $this->_properties['importance'] = $importance; 201 } 202 203 /** 204 * Get the task importance level 205 * 206 * @return integer A IMPORTANCE_* constant 207 */ 208 public function getImportance() 209 { 210 return $this->_getAttribute('importance', self::IMPORTANCE_NORMAL); 211 } 212 213 /** 214 * Set the reminder datetime 215 * 216 * @param Horde_Date $datetime The time to trigger the alarm in local tz. 217 */ 218 public function setReminder(Horde_Date $datetime) 219 { 220 $this->_properties['remindertime'] = $datetime; 221 $this->_properties['reminderset'] = self::REMINDER_SET_TRUE; 222 } 223 224 /** 225 * Get the reminder time. 226 * 227 * @return Horde_Date in local tz 228 */ 229 public function getReminder() 230 { 231 if (!$this->_getAttribute('reminderset')) { 232 return false; 233 } 234 return $this->_getAttribute('remindertime'); 235 } 236 237 /** 238 * Set recurrence information for this task 239 * 240 * @param Horde_Date_Recurrence $recurrence 241 */ 242 public function setRecurrence(Horde_Date_Recurrence $recurrence) 243 { 244 $r = Horde_ActiveSync::messageFactory('TaskRecurrence'); 245 246 // Map the type fields 247 switch ($recurrence->recurType) { 248 case Horde_Date_Recurrence::RECUR_DAILY: 249 $r->type = Horde_ActiveSync_Message_Recurrence::TYPE_DAILY; 250 break; 251 case Horde_Date_Recurrence::RECUR_WEEKLY: 252 $r->type = Horde_ActiveSync_Message_Recurrence::TYPE_WEEKLY; 253 $r->dayofweek = $recurrence->getRecurOnDays(); 254 break; 255 case Horde_Date_Recurrence::RECUR_MONTHLY_DATE: 256 $r->type = Horde_ActiveSync_Message_Recurrence::TYPE_MONTHLY; 257 $r->dayofmonth = $recurrence->start->mday; 258 break; 259 case Horde_Date_Recurrence::RECUR_MONTHLY_WEEKDAY; 260 $r->type = Horde_ActiveSync_Message_Recurrence::TYPE_MONTHLY_NTH; 261 $r->weekofmonth = ceil($recurrence->start->mday / 7); 262 $r->dayofweek = $this->_dayOfWeekMap[$recurrence->start->dayOfWeek()]; 263 break; 264 case Horde_Date_Recurrence::RECUR_YEARLY_DATE: 265 $r->type = Horde_ActiveSync_Message_Recurrence::TYPE_YEARLY; 266 break; 267 case Horde_Date_Recurrence::RECUR_YEARLY_WEEKDAY: 268 $r->type = Horde_ActiveSync_Message_Recurrence::TYPE_YEARLYNTH; 269 $r->dayofweek = $this->_dayOfWeekMap[$recurrence->start->dayOfWeek()]; 270 $r->weekofmonth = ceil($recurrence->start->mday / 7); 271 $r->monthofyear = $recurrence->start->month; 272 break; 273 } 274 if (!empty($recurrence->recurInterval)) { 275 $r->interval = $recurrence->recurInterval; 276 } 277 278 // AS messages can only have one or the other (or none), not both 279 if ($recurrence->hasRecurCount()) { 280 $r->occurrences = $recurrence->getRecurCount(); 281 } elseif ($recurrence->hasRecurEnd()) { 282 $r->until = $recurrence->getRecurEnd(); 283 } 284 285 // Set the start of the recurrence series. 286 $r->start = clone $this->duedate; 287 288 $this->_properties['recurrence'] = $r; 289 } 290 291 /** 292 * Obtain a recurrence object. Note this returns a Horde_Date_Recurrence 293 * object, not Horde_ActiveSync_Message_Recurrence. 294 * 295 * @return Horde_Date_Recurrence 296 */ 297 public function getRecurrence() 298 { 299 if (!$recurrence = $this->_getAttribute('recurrence')) { 300 return false; 301 } 302 303 $d = clone($this->getDueDate()); 304 // $d->setTimezone($this->getTimezone()); 305 306 $rrule = new Horde_Date_Recurrence($d); 307 308 /* Map MS AS type field to Horde_Date_Recurrence types */ 309 switch ($recurrence->type) { 310 case Horde_ActiveSync_Message_Recurrence::TYPE_DAILY: 311 $rrule->setRecurType(Horde_Date_Recurrence::RECUR_DAILY); 312 break; 313 case Horde_ActiveSync_Message_Recurrence::TYPE_WEEKLY: 314 $rrule->setRecurType(Horde_Date_Recurrence::RECUR_WEEKLY); 315 $rrule->setRecurOnDay($recurrence->dayofweek); 316 break; 317 case Horde_ActiveSync_Message_Recurrence::TYPE_MONTHLY: 318 $rrule->setRecurType(Horde_Date_Recurrence::RECUR_MONTHLY_DATE); 319 break; 320 case Horde_ActiveSync_Message_Recurrence::TYPE_MONTHLY_NTH: 321 $rrule->setRecurType(Horde_Date_Recurrence::RECUR_MONTHLY_WEEKDAY); 322 $rrule->setRecurOnDay($recurrence->dayofweek); 323 break; 324 case Horde_ActiveSync_Message_Recurrence::TYPE_YEARLY: 325 $rrule->setRecurType(Horde_Date_Recurrence::RECUR_YEARLY_DATE); 326 break; 327 case Horde_ActiveSync_Message_Recurrence::TYPE_YEARLYNTH: 328 $rrule->setRecurType(Horde_Date_Recurrence::RECUR_YEARLY_WEEKDAY); 329 $rrule->setRecurOnDay($recurrence->dayofweek); 330 break; 331 } 332 333 if ($rcnt = $recurrence->occurrences) { 334 $rrule->setRecurCount($rcnt); 335 } 336 if ($runtil = $recurrence->until) { 337 $rrule->setRecurEnd(new Horde_Date($runtil)); 338 } 339 if ($interval = $recurrence->interval) { 340 $rrule->setRecurInterval($interval); 341 } 342 343 return $rrule; 344 } 345 346 /** 347 * Return this object's folder class 348 * 349 * @return string 350 */ 351 public function getClass() 352 { 353 return 'Tasks'; 354 } 355 356 /** 357 * Check if a field should be sent to the device even if it is empty. 358 * 359 * @param string $tag The field tag. 360 * 361 * @return boolean 362 */ 363 protected function _checkSendEmpty($tag) 364 { 365 if ($tag == self::POOMTASKS_BODYTRUNCATED && $this->bodysize > 0) { 366 return true; 367 } 368 369 return false; 370 } 371 372} 373