caldav_EventCalendar   A
last analyzed

Complexity

Total Complexity 1

Size/Duplication

Total Lines 30
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 1

Test Coverage

Coverage 80%

Importance

Changes 0
Metric Value
dl 0
loc 30
rs 10
c 0
b 0
f 0
ccs 4
cts 5
cp 0.8
wmc 1
lcom 0
cbo 1

2 Methods

Rating   Name   Duplication   Size   Complexity  
getCaldavClient() 0 1 ?
A __construct() 0 5 1
1
<?php
2
//-------------------------------------------------------------------------
3
// OVIDENTIA http://www.ovidentia.org
4
// Ovidentia is free software; you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation; either version 2, or (at your option)
7
// any later version.
8
//
9
// This program is distributed in the hope that it will be useful, but
10
// WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
// See the GNU General Public License for more details.
13
//
14
// You should have received a copy of the GNU General Public License
15
// along with this program; if not, write to the Free Software
16
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
17
// USA.
18
//-------------------------------------------------------------------------
19
/**
20
 * @license http://opensource.org/licenses/gpl-license.php GNU General Public License (GPL)
21
 * @copyright Copyright (c) 2010 by CANTICO ({@link http://www.cantico.fr})
22
 */
23
24 1
require_once $GLOBALS['babInstallPath'] . 'utilit/cal.eventcalendar.class.php';
25
26
27
/**
28
 * Ovidentia calendar
29
 */
30
abstract class caldav_EventCalendar extends bab_EventCalendar
31
{
32
33
	/**
34
	 * The backend that was used to create this calendar instance.
35
	 * @var Func_CalendarBackend
36
	 */
37
	protected $backend;
38
39
	/**
40
	 * Calendar ID
41
	 * @var string
42
	 */
43
	protected $id_calendar = null;
44
	
45
	/**
46
	 * @param Func_CalendarBackend $backend
47
	 */
48 7
	public function __construct(Func_CalendarBackend $backend)
49
	{
50 7
		$this->uid = null;
51 7
		$this->backend = $backend;
52 7
	}
53
	
54
	
55
	/**
56
	 * @return CalDAVClient
57
	 */
58
	abstract function getCaldavClient();
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
59
}
60
61
62
63
64
/**
65
 * Personal calendar
66
 */
67
class caldav_PersonalCalendar extends caldav_EventCalendar implements bab_PersonalCalendar 
68
{
69
70
71
	/**
72
	 * Sets the name of the calendar.
73
	 * 
74
	 * @param string $name
75
	 * 
76
	 * @return caldav_PersonalCalendar
77
	 */
78
	public function setName($name)
79
	{
80
		$this->name = $name;
81
		
82
		return $this;
83
	}
84
85
	/**
86
	 * (non-PHPdoc)
87
	 * @see utilit/bab_EventCalendar::getBackend()
88
	 * 
89
	 * @return Func_CalendarBackend_Caldav
90
	 */
91 7
	public function getBackend()
92
	{
93 7
		return $this->backend;
94
	}
95
96
97
	/**
98
	 * Sets the user associated to this personal calendar.
99
	 * 
100
	 * @param int $userId
101
	 * 
102
	 * @return caldav_PersonalCalendar
103
	 */
104 7
	public function setIdUser($userId)
105
	{
106 7
		$this->id_user = $userId;
107 7
		$this->name = bab_getUserName($userId);
0 ignored issues
show
Documentation Bug introduced by
It seems like bab_getUserName($userId) can also be of type false or array<string,string,{"fi...","lastname":"string"}>. However, the property $name is declared as type string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
108
		
109 7
		$this->uid = bab_getICalendars()->getPersonalCalendarUid($userId);
110 7
		if (!$this->uid)
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->uid of type integer|null is loosely compared to false; this is ambiguous if the integer can be zero. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
111 7
		{
112
			throw new Exception('Missing calendar UID');
113
		}
114
		
115 7
		return $this;
116
	}
117
	
118
	/**
119
	 * (non-PHPdoc)
120
	 * @see utilit/bab_EventCalendar::getType()
121
	 */
122
	public function getType() 
123
	{
124
		return bab_translate('Personal calendar');
125
	}
126
127
128
	/**
129
	 * Get the type part of the reference
130
	 * @return string
131
	 */
132 6
	public function getReferenceType()
133
	{
134 6
		return 'caldav_personal';
0 ignored issues
show
Bug Best Practice introduced by
The return type of return 'caldav_personal'; (string) is incompatible with the return type declared by the abstract method bab_EventCalendar::getReferenceType of type unknown_type.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
135
	}
136
	
137
138
	
139
	/**
140
	 * Test if an event can be added on a calendar
141
	 * @return bool
142
	 */
143
	public function canAddEvent()
144
	{
145
		
146
		if (((int) $this->access_user) === (int) $this->getIdUser()) {
147
			// i am the author
148
			return true;
149
		}
150
		
151
		
152
		switch($this->getSharingAccess()) {
153
			case BAB_CAL_ACCESS_SHARED_UPDATE:
154
			case BAB_CAL_ACCESS_UPDATE:
155
			case BAB_CAL_ACCESS_FULL:
156
				return true;
157
		}
158
159
		return false;
160
	}
161
162
163
	/**
164
	 * Test if the current user can update the specified event of the calendar.
165
	 * 
166
	 * @param bab_calendarPeriod $event
167
	 * @return bool
168
	 */
169
	public function canUpdateEvent(bab_CalendarPeriod $event)
170
	{	
171
		$collection = $event->getCollection();
172
173
		if ($collection instanceof bab_ReadOnlyCollection) {
174
			return false;
175
		}
176
		
177
		$author = $event->getAuthorId();
178
		if (null === $author)
179
		{
180
			bab_debug('Missing author ID for event '.$event->getUrlIdentifier());
181
			return (((int) $this->getIdUser()) === (int) $this->access_user);
182
		}
183
		
184
		
185
186
187
		if (((int) $this->access_user) === $author) {
188
			// i am the author
189
			return true;
190
		}
191
192
		if ($event->isLocked()) {
193
			return false;
194
		}
195
196
197
		switch($this->getSharingAccess()) {
198
				
199
			case BAB_CAL_ACCESS_UPDATE:
200
				if (((int) $this->access_user) === $author)
201
				{
202
					return true;
203
				}
204
				break;
205
206
			case BAB_CAL_ACCESS_SHARED_UPDATE:
207
				if ($this->isSharedAccessForCalendar($this, $event))
208
				{
209
					return true;
210
				}
211
				break;
212
213
			case BAB_CAL_ACCESS_FULL:
214
				return true;
215
		}
216
		
217
		
218
		
219
		$main = $event->getCollection()->getCalendar();
220
		if ($main === $this)
221
		{
222
			return true;
223
		}
224
		
225
		
226
		return false;
227
	}
228
229
230
	/**
231
	 * Test if the current user can delete the specified event from the calendar.
232
	 * 
233
	 * @param bab_calendarPeriod $event
234
	 * @return bool
235
	 */
236
	public function canDeleteEvent(bab_CalendarPeriod $event)
237
	{
238
		return $this->canUpdateEvent($event);
239
	}
240
241
	/**
242
	 * Access level for calendar sharing of the access_user
243
	 */
244
	public function getSharingAccess()
245
	{
246
		return $this->getSharingAccessForCalendar($this);
247
	}
248
249
250
	/**
251
	 * Get default attendee PARTSTAT property value for new attendee associated to an event of this calendar
252
	 * The calendar as given parameter must return an interger value with the method getIdUser
253
	 * the return value will be one of the following values from the iCalendar spec :
254
	 * <ul>
255
	 * 	<li>NEEDS-ACTION : the event will appear on the attendee calendar and request validation from him (default value)</li>
256
	 *  <li>ACCEPTED : the event will appear on the attendee calendar</li>
257
	 * </ul>
258
	 * if the user is the attendee or if the user have full access, the attendee is considered accepted
259
	 * 
260
	 * @link http://www.kanzaki.com/docs/ical/partstat.html
261
	 * 
262
	 * @see bab_EventCalendar::getIdUser()
263
	 * 
264
	 * 
265
	 * @return 	string
266
	 */
267
	public function getDefaultAttendeePARTSTAT()
268
	{
269
		
270
		if ($this->access_user == $this->getIdUser())
271
		{
272
			// I add myself as attendee on an event
273
			return 'ACCEPTED';
274
		}
275
		
276
//		switch($this->getSharingAccess()) {
277
//
278
//			case BAB_CAL_ACCESS_FULL:
279
//				// i have full access on the attendee calendar where the event is
280
//				return 'ACCEPTED';
281
//		}
282
283
		return 'NEEDS-ACTION';
284
	}
285
	
286
	
287
	/**
288
	 * 
289
	 *
290
	 *
291
	 */
292
	protected function inviteTo(bab_ICalendarObject $icalendarObject)
293
	{
294
		$mail = bab_mail();
295
		if ($mail === false) {
296
			throw new Exception('Sending error( Mail sending disabled )');
297
		}
298
		
299
		$senderId = $GLOBALS['BAB_SESS_USERID'];
300
		$senderEmailAddress = bab_getUserEmail($senderId);
301
		$senderFullname = bab_getUserName($senderId, true);
302
		 
303
		$mail->mailFrom($senderEmailAddress, $senderFullname);
304
//		$mail->mailBody('');
305
		$mail->mailSubject($icalendarObject->getProperty('SUMMARY'));
306
		
307
		$userId = $this->getIdUser();
308
		$userEmailAddress = bab_getUserEmail($userId);
309
		$userFullname = bab_getUserName($userId, true);
310
		$mail->mailStringAttach($this->getBackend()->iCalObjectToVcalendarInvitation($icalendarObject, $this), $icalendarObject->getProperty('UID') . '.ics', 'text/calendar');
311
		$mail->mailTo($userEmailAddress, $userFullname);
312
		
313
		if (!$mail->send()) {
314
			throw new Exception('Error occured when sending email: ' . $mail->ErrorInfo());
315
		}
316
		
317
	}
318
	
319
	
320
	
321
	
322
	/**
323
	 * save or update an event
324
	 * this method is called on the attendee calendar of the event
325
	 * 
326
	 * @param	bab_CalendarPeriod 	$event
327
	 */
328 1
	protected function saveToCaldavInbox(bab_CalendarPeriod $event)
329
	{
330 1
		$collection = $event->getCollection();
331
		
332 1
		if (!($collection instanceof bab_CalendarEventCollection))
333 1
		{
334
			// do nothing because the event is not a regular calendar event
335
			return;	
336
		}
337
		
338 1
		$backend = $this->getBackend();
339
		
340 1
		$attendeeEvent = clone $event;
341
		
342
		// create a new collection into the attendee calendar
343 1
		$collection = $backend->CalendarEventCollection($this);
344 1
		$collection->addPeriod($attendeeEvent);
345
		
346
		// save a copy of the event into the attendee calendar
347
		// if the event allready exists, it will be updated
348
		// TODO : save the event into the .in folder if possible
349 1
		$backend->savePeriod($attendeeEvent);
350 1
	}
351
	
352
	
353
	
354
	
355
	
356
	
357
358
	/**
359
	 * Triggered when the calendar has been added as an attendee on $event
360
	 * @param bab_CalendarPeriod $event
361
	 * @return unknown_type
362
	 */
363 1
	public function onAddAttendee(bab_CalendarPeriod $event)
364
	{
365
		// do not invite organizer
366
		
367 1
		$collection = $event->getCollection();
368 1
		$calendar = $collection->getCalendar();
369
370 1
		if ($calendar === $this)
371 1
		{
372
			return;
373
		}
374
		
375
		// send mail with ics attachment
376
		// $this->inviteTo($event);
377
		
378
		// call parent to add the event in ovidentia inbox
379
		// event will be displayed but not created in calendar
380
		// if this line is active, the inviteTo method should not be called 
381
		// $this->addToOviInbox($event);
382
		
383
		
384
		
385
		// save the event into the calendar on caldav server
386
		try {
387 1
		    $this->saveToCaldavInbox($event);
388 1
		} catch (ErrorException $e) {
0 ignored issues
show
Bug introduced by
The class ErrorException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
389
		    bab_debug($e->getMessage());
390
		    bab_getBody()->addError($e->getMessage());
391
		}
392 1
	}
393
	
394
	/**
395
	 * Triggered when the calendar has been updated as an attendee on $event
396
	 * @param bab_CalendarPeriod $event
397
	 * @return unknown_type
398
	 */
399
	public function onUpdateAttendee(bab_CalendarPeriod $event)
400
	{
401
		// notify the user with the event, he will probablay allready have the event with same uid in his calendar 
402
		// the mail client will propose an event update
403
		// $this->inviteTo($event);
404
		
405
		// update the event into the calendar on caldav server if the event allready exists
406
		// or create the event
407
		$this->saveToCaldavInbox($event);
408
	}
409
	
410
	
411
	
412
	
413
	
414
	/**
415
	 * (non-PHPdoc)
416
	 * @see caldav_EventCalendar::getCaldavClient()
417
	 * 
418
	 * @return CalDAVClient
419
	 */
420 7
	public function getCaldavClient()
421
	{
422 7
		$userId = $this->getIdUser();
423 7
		$backend = $this->getBackend();
424
		
425 7
		$path = $backend->getPersonnalCalendarUrl($userId);
426 7
		list($nickname, $password) = $backend->getPersonalCalendarCredentials($userId);
427
		
428
		
429
		
430 7
		return new CalDAVClient($path, $nickname, $password, 'calendar');
431
	}
432
}
433
434
435
436
437
 class caldav_ResourceCalendar extends caldav_EventCalendar implements bab_ResourceCalendar 
438
 {
439
 	public function getBackend()
440
 	{
441
 		return $this->backend;
442
 	}
443
 	
0 ignored issues
show
Coding Style introduced by
There is some trailing whitespace on this line which should be avoided as per coding-style.
Loading history...
444
 	
0 ignored issues
show
Coding Style introduced by
There is some trailing whitespace on this line which should be avoided as per coding-style.
Loading history...
445
 	/**
0 ignored issues
show
Coding Style introduced by
There is some trailing whitespace on this line which should be avoided as per coding-style.
Loading history...
446
 	 * (non-PHPdoc)
447
 	 * @see utilit/bab_EventCalendar::getType()
448
 	 */
449
 	public function getType()
450
 	{
451
 		return bab_translate('Resource calendar');
452
 	}
453
 	
0 ignored issues
show
Coding Style introduced by
There is some trailing whitespace on this line which should be avoided as per coding-style.
Loading history...
454
 	
0 ignored issues
show
Coding Style introduced by
There is some trailing whitespace on this line which should be avoided as per coding-style.
Loading history...
455
 	/**
0 ignored issues
show
Coding Style introduced by
There is some trailing whitespace on this line which should be avoided as per coding-style.
Loading history...
456
 	 * Get the type part of the reference
457
 	 * @return string
458
 	 */
459
 	public function getReferenceType()
460
 	{
461
 		return 'caldav_resource';
0 ignored issues
show
Bug Best Practice introduced by
The return type of return 'caldav_resource'; (string) is incompatible with the return type declared by the abstract method bab_EventCalendar::getReferenceType of type unknown_type.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
462
 	}
463
 	
0 ignored issues
show
Coding Style introduced by
There is some trailing whitespace on this line which should be avoided as per coding-style.
Loading history...
464
 	
0 ignored issues
show
Coding Style introduced by
There is some trailing whitespace on this line which should be avoided as per coding-style.
Loading history...
465
 	/**
0 ignored issues
show
Coding Style introduced by
There is some trailing whitespace on this line which should be avoided as per coding-style.
Loading history...
466
 	 * Triggered when the calendar has been added as a relation on $event
467
 	 * @param bab_CalendarPeriod $event
468
 	 * @return unknown_type
469
 	 */
470
 	public function onAddRelation(bab_CalendarPeriod $event) {}
471
 	
0 ignored issues
show
Coding Style introduced by
There is some trailing whitespace on this line which should be avoided as per coding-style.
Loading history...
472
 	/**
0 ignored issues
show
Coding Style introduced by
There is some trailing whitespace on this line which should be avoided as per coding-style.
Loading history...
473
 	 * Triggered when the calendar has been updated as a relation on $event
474
 	 * @param bab_CalendarPeriod $event
475
 	 * @return unknown_type
476
 	 */
477
 	public function onUpdateRelation(bab_CalendarPeriod $event) {}
478
 	
0 ignored issues
show
Coding Style introduced by
There is some trailing whitespace on this line which should be avoided as per coding-style.
Loading history...
479
 	
0 ignored issues
show
Coding Style introduced by
There is some trailing whitespace on this line which should be avoided as per coding-style.
Loading history...
480
 	
0 ignored issues
show
Coding Style introduced by
There is some trailing whitespace on this line which should be avoided as per coding-style.
Loading history...
481
 	public function setUid($uid)
482
 	{
483
 		$this->uid = $uid;
484
 	}
485
 	
0 ignored issues
show
Coding Style introduced by
There is some trailing whitespace on this line which should be avoided as per coding-style.
Loading history...
486
 	
0 ignored issues
show
Coding Style introduced by
There is some trailing whitespace on this line which should be avoided as per coding-style.
Loading history...
487
 	public function setConfiguration(Array $configuration)
488
 	{
489
 		$this->configuration = $configuration;
0 ignored issues
show
Bug introduced by
The property configuration does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
490
 		
491
 	}
492
 	
0 ignored issues
show
Coding Style introduced by
There is some trailing whitespace on this line which should be avoided as per coding-style.
Loading history...
493
 	
0 ignored issues
show
Coding Style introduced by
There is some trailing whitespace on this line which should be avoided as per coding-style.
Loading history...
494
 	public function setName($name)
495
 	{
496
 		$this->name = $name;
497
 	}
498
 	
0 ignored issues
show
Coding Style introduced by
There is some trailing whitespace on this line which should be avoided as per coding-style.
Loading history...
499
 	
0 ignored issues
show
Coding Style introduced by
There is some trailing whitespace on this line which should be avoided as per coding-style.
Loading history...
500
 	/**
0 ignored issues
show
Coding Style introduced by
There is some trailing whitespace on this line which should be avoided as per coding-style.
Loading history...
501
 	 * (non-PHPdoc)
502
 	 * @see caldav_EventCalendar::getCaldavClient()
503
 	 *
504
 	 * @return CalDAVClient
505
 	 */
506
 	public function getCaldavClient()
507
 	{
508
 		return new CalDAVClient($this->configuration['url'], $this->configuration['nickname'], $this->configuration['password'], 'calendar');
509
 	}
510
 }
511