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