1<?php 2 3// An event model that is used by the calendar view to show the correct event data. 4/** 5 * Copyright Intermesh 6 * 7 * This file is part of Group-Office. You should have received a copy of the 8 * Group-Office license along with Group-Office. See the file /LICENSE.TXT 9 * 10 * If you have questions write an e-mail to info@intermesh.nl 11 * 12 * 13 * @property Event $_event 14 * @property Calendar $_calendar 15 * @property string $_startTime 16 * @property string $_endTime 17 * @property string $_alternateEndTime 18 * @property string $_alternateStartTime 19 * 20 * @copyright Copyright Intermesh 21 * @author Wesley Smits <wsmits@intermesh.nl> 22 */ 23 24namespace GO\Calendar\Model; 25 26 27class LocalEvent extends \GO\Base\Model { 28 29 30 private $_initials = array(); 31 private $_calendarNames = array(); 32 33 private $_isMerged = false; 34 35 private $_backgroundColor = ''; 36 37 public $displayId = 0; 38 39 private $_displayName = ''; 40 41 /** 42 * 43 * @var Event 44 */ 45 private $_event; 46 47 /** 48 * 49 * @var Calendar 50 */ 51 private $_calendar; 52 53 /** 54 * 55 * @var StringHelper 56 */ 57 private $_startTime; 58 59 /** 60 * 61 * @var StringHelper 62 */ 63 private $_endTime; 64 65 /** 66 * The end time of an recurring event in the current period 67 * 68 * @var StringHelper 69 */ 70 private $_alternateEndTime; 71 72 /** 73 * The start time of an recurring event in the current period 74 * 75 * @var StringHelper 76 */ 77 private $_alternateStartTime; 78 79 /** 80 * Constructor 81 * 82 * @param Event $event 83 * @param StringHelper $periodStartTime 84 * @param StringHelper $periodEndTime 85 */ 86 public function __construct(Event $event, $periodStartTime, $periodEndTime){ 87 $this->_event = $event; 88 $this->_startTime = $periodStartTime; 89 $this->_endTime = $periodEndTime; 90 $this->_backgroundColor = $event->background; 91 $this->_displayName = $event->name; 92 93 $this->_calendar = $this->_event->calendar; 94 95 // If there is no user attached to this event (user_id = 0) then create a temporary user object 96// if(!$event->user){ 97// $event->user = new \GO\Base\Model_User(); 98// $event->user->first_name = \GO::t("Unknown").' '.\GO::t("User"); 99// } 100 101 $this->_initials[] = $event->user ? $event->user->getShortName() : '??'; 102 $this->_calendarNames[] = $this->_calendar->name; 103 } 104 105 public function setBackgroundColor($color){ 106 $this->_backgroundColor = $color; 107 } 108 109 public function getUuid(){ 110 return $this->_event->uuid; 111 } 112 113 public function getResponseData(){ 114 115 $dayString = \GO::t("full_days"); 116 117 $response = $this->_event->getAttributes('formatted'); 118 119 if($this->isAllDay()){ 120 $response['time'] = $this->getFormattedTime(); 121 } else { 122 if (date(\GO::user()->date_format, $this->getAlternateStartTime()) != date(\GO::user()->date_format, $this->getAlternateEndTime())) 123 $response['time'] = $this->getFormattedTime(); 124 else 125 $response['time'] = $this->getFormattedTime(); 126 } 127// $response['time_of_day'] = $this->getTimeOfDay(); 128 129 $response['status'] = $this->_event->status; 130 $response['username'] = $this->_event->user ? $this->_event->user->getName() : \GO::t("Unknown").' '.\GO::t("User"); 131 $response['musername'] = !empty($this->_event->mUser) ? $this->_event->mUser->getName() : ''; 132 133// if($this->_event->status==Event::STATUS_CANCELLED){ 134// $response['name'] .= ' ('.$this->_event->localizedStatus.')'; 135// } 136// 137 if($this->_isMerged){ 138 $response['name'] = $response['name'] .' ('.implode(',',$this->_initials).')'; 139 $response['calendar_name'] = implode('; ',$this->_calendarNames); 140 unset($response['status']); // unset this, it is not relevant to show this in merge view 141 unset($response['username']); // unset this, it is not relevant to show this in merge view. 142 }else 143 { 144 $response['calendar_name']=$this->_calendarNames[0]; 145 } 146 147 $response['id'] = $this->_event->id.':'.$this->getAlternateStartTime(); // a unique id for the data store. Is not really used. 148 $response['background'] = $this->_backgroundColor; 149 $response['recurring_start_time'] = date('Y-m-d H:i', $this->_event->start_time); 150 $response['start_time'] = date('Y-m-d H:i', $this->getAlternateStartTime()); 151 $response['end_time'] = date('Y-m-d H:i', $this->getAlternateEndTime()); 152 $response['ctime'] = date('Y-m-d H:i', $this->_event->ctime); 153 $response['mtime'] = date('Y-m-d H:i', $this->_event->mtime); 154 $response['event_id'] = $this->_event->id; 155 $response['description'] = \GO\Base\Util\StringHelper::cut_string($this->_event->description, 800); 156 $response['private'] = $this->isPrivate(); 157 158 $response['private_enabled']=$this->_event->private; 159 160 $response['resources'] = array(); 161 162 if($response['private']){ 163 $response['name']=\GO::t("Private", "calendar"); 164 $response['description']=""; 165 $response['location']=""; 166 $response['repeats'] = false; 167 $response['has_reminder'] = false; 168 $response['link_count'] = false; 169 $response['status_color'] = false; 170 $response['status'] = false; 171 } else { 172 $response['repeats'] = $this->isRepeating(); 173 $response['has_reminder'] = $this->_event->hasReminders()?1:0; 174 $response['link_count'] = $this->getLinkCount(); 175 $response['status_color'] = $this->_event->getStatusColor(); 176 177 if ($this->_event->resources) { 178 foreach ($this->_event->resources as $resourceModel) { 179 $response['resources'][$resourceModel->id] = $resourceModel->calendar->name; 180 } 181 } 182 183 } 184 185 186 $response['permission_level']=$this->_event->permissionLevel; 187 $response['all_day_event'] = $this->isAllDay(); 188 $response['day'] = $dayString[date('w', $this->getAlternateStartTime())].' '.\GO\Base\Util\Date::get_timestamp($this->getAlternateStartTime(),false); // date(implode(\GO::user()->date_separator,str_split(\GO::user()->date_format,1)), ($eventModel->start_time)); 189 $response['read_only'] = $this->isReadOnly(); 190 $response['model_name'] = $this->_event->className(); 191 192 $response['partstatus']="none"; 193 if(isset($response['status']) && $response['status']==Event::STATUS_CANCELLED){ 194 //hack to make it transparent on cancelled status too in the view. 195 $response['partstatus']= Participant::STATUS_DECLINED; 196 }else{ 197 if($participant = $this->_event->getParticipantOfCalendar()){ 198 $response['partstatus']=$participant->status; 199 } 200 } 201 202 $duration = $this->getDurationInMinutes(); 203 204 if($duration >= 60){ 205 $durationHours = floor($duration / 60); 206 $durationRestMinutes = $duration % 60; 207 $response['duration'] = $durationHours.' '.\GO::t("hours").', '.$durationRestMinutes.' '.\GO::t("Mins"); 208 } else { 209 $response['duration'] = $duration.'m'; 210 } 211 212 return array_map(array("\GO\Base\Util\StringHelper", "encodeHtml"),$response); 213 } 214 215 public function getName(){ 216 return $this->_displayName; 217 } 218// 219// /** 220// * Get the time of day the event occurs. 221// * If event is not set or there is no start_time we return "FullDay" 222// * @return string (morning|afternoon|evening|fullday) 223// */ 224// public function getTimeOfDay() 225// { 226// if(!isset($this->_event) && empty($this->_event->start_time)) 227// return "fullday"; 228// $hour = date('G', $this->_event->start_time); //0 - 23 229// 230// if($hour >= 0 && $hour < 12) 231// return "morning"; 232// elseif($hour >= 12 && $hour < 18) 233// return "afternoon"; 234// elseif($hour >= 18) 235// return "evening"; 236// } 237 238 239 public function mergeWithEvent($event){ 240 241 //echo $this->_event->user->getShortName().' : '. $event->getEvent()->user->getShortName().', '; 242 243 244 $this->_isMerged = true; 245 $this->_initials[] = $event->getCalendar()->user->getShortName(); 246 $this->_calendarNames[] = $event->getCalendar()->name; 247 $this->_backgroundColor = 'FFFFFF'; 248 249 if($event->getEvent()->is_organizer){ 250 $this->_event = $event->getEvent(); 251 } 252 253 } 254 255 /** 256 * Get the start time of the recurring event in the selected period 257 * 258 * @return int Unix timestamp 259 */ 260 public function getAlternateStartTime(){ 261 if(empty($this->_alternateStartTime)) { 262 $this->setAlternateStartTime($this->_event->start_time); 263 } 264 return $this->_alternateStartTime; 265 } 266 267 /** 268 * Get the end time of the recurring event in the selected period 269 * 270 * @return int Unix timestamp 271 */ 272 public function getAlternateEndTime(){ 273 if(empty($this->_alternateEndTime)) { 274 $this->setAlternateEndTime($this->_event->end_time); 275 } 276 return $this->_alternateEndTime; 277 } 278 279 /** 280 * Set the start time of the recurring event in the selected period 281 * 282 * @param int $time Unix timestamp 283 */ 284 public function setAlternateStartTime($time){ 285 // Convert timestamp to the zone of the user who has entered the event 286 // Timezone may set the date incorrect so setTimezone() is needed 287 if($this->_event->isFullDay()) { 288 try { 289 $eventTimezone = new \DateTimeZone($this->_event->timezone); 290 } catch(\Exception $e) { 291 $eventTimezone = new \DateTimeZone(GO::config()->default_timezone); 292 trigger_error("The timezone ".$this->_event->timezone." is invalid in event: ".$this->_event->id, E_USER_WARNING); 293 } 294 $startTime = new \DateTime(); 295 $startTime->setTimestamp($time); 296 $startTime->setTimezone($eventTimezone); 297 $this->_alternateStartTime = strtotime($startTime->format('Y-m-d 00:00:00')); 298 } else { 299 $this->_alternateStartTime = $time; 300 } 301 } 302 303 /** 304 * Set the end time of the recurring event in the selected period 305 * 306 * @param int $time Unix timestamp 307 */ 308 public function setAlternateEndTime($time){ 309 310 if($this->_event->isFullDay()) { 311 try { 312 $eventTimezone = new \DateTimeZone($this->_event->timezone); 313 } catch(\Exception $e) { 314 $eventTimezone = new \DateTimeZone(GO::config()->default_timezone); 315 trigger_error("The timezone ".$this->_event->timezone." is invalid in event: ".$this->_event->id, E_USER_WARNING); 316 } 317 $endTime = new \DateTime(); 318 $endTime->setTimestamp($time); 319 $endTime->setTimezone($eventTimezone); 320 $this->_alternateEndTime = strtotime($endTime->format('Y-m-d 23:59:59')); 321 } else { 322 $this->_alternateEndTime = $time; 323 } 324 } 325 326 /** 327 * Get the period start time 328 * 329 * @return StringHelper 330 */ 331 public function getPeriodStartTime(){ 332 return $this->_startTime; 333 } 334 335 /** 336 * Get the period end time 337 * 338 * @return StringHelper 339 */ 340 public function getPeriodEndTime(){ 341 return $this->_endTime; 342 } 343 344 345 /** 346 * 347 * @return Event 348 */ 349 public function getEvent(){ 350 return $this->_event; 351 } 352 353 /** 354 * 355 * @return Calendar 356 */ 357 public function getCalendar(){ 358 return $this->_calendar; 359 } 360 361 /** 362 * Get the number of links that this events has 363 * 364 * @return int 365 */ 366 public function getLinkCount(){ 367 return $this->_event->countLinks(); 368 } 369 370 /** 371 * Get the formatted starting date of this event 372 * 373 * @return StringHelper 374 */ 375 public function getFormattedDate(){ 376 return date(\GO::user()->date_format,$this->_event->start_time); 377 } 378 379 /** 380 * Get the formatted starting date and time of this event 381 * 382 * @return StringHelper 383 */ 384 public function getFormattedDateAndTime(){ 385 return date(\GO::user()->date_format.' '.\GO::user()->time_format,$this->_event->start_time); 386 } 387 388 /** 389 * Get the formatted starting time of this event 390 * 391 * @return StringHelper 392 */ 393 public function getFormattedTime(){ 394 return date(\GO::user()->time_format,$this->_event->start_time); 395 } 396 397 /** 398 * Get the day this event starts on. 399 * 400 * @return StringHelper 401 */ 402 public function getDay(){ 403 $dayString = \GO::t("full_days", "common"); 404 return $dayString[date('w',$this->_event->start_time)]; 405 } 406 407 /** 408 * Get the time of the event duration in minutes 409 * 410 * @return int 411 */ 412 public function getDurationInMinutes(){ 413 414 $durationMinutes = ($this->_event->end_time-$this->_event->start_time)/60; 415 416 return $durationMinutes; 417 } 418 419 /** 420 * Is this an all day event 421 * 422 * @return boolean 423 */ 424 public function isAllDay(){ 425 return $this->_event->all_day_event; 426 } 427 428 /** 429 * Is this a repeating event 430 * 431 * @return boolean 432 */ 433 public function isRepeating(){ 434 return !empty($this->_event->rrule); 435 } 436 437 /** 438 * Is this a private event for the current user. If the event or the calendar 439 * is owned by the current user it will not be displayed as private. 440 * 441 * @return boolean 442 */ 443 public function isPrivate(){ 444 return $this->_event->private && 445 (\GO::user()->id != $this->_event->user_id) && 446 \GO::user()->id!=$this->_event->calendar->user_id; 447 } 448 449 /** 450 * Is this a read only event 451 * 452 * @return boolean 453 */ 454 public function isReadOnly(){ 455 return 456 //$this->_isMerged || 457 $this->_event->read_only || 458 !$this->_event->is_organizer || 459 $this->isPrivate() && \GO::user()->id != $this->_event->user_id || 460 $this->_event->permissionLevel < \GO\Base\Model\Acl::WRITE_PERMISSION; 461 } 462 463 /** 464 * Does this event have more participants 465 * 466 * @return boolean 467 */ 468 public function hasOtherParticipants(){ 469 return $this->_event->hasOtherParticipants(); 470 } 471 472} 473