Completed
Push — master ( 14bed3...7a3751 )
by Markus
05:16 queued 03:20
created

Event   C

Complexity

Total Complexity 69

Size/Duplication

Total Lines 749
Duplicated Lines 1.74 %

Coupling/Cohesion

Components 1
Dependencies 8

Test Coverage

Coverage 25.47%

Importance

Changes 41
Bugs 4 Features 23
Metric Value
wmc 69
c 41
b 4
f 23
lcom 1
cbo 8
dl 13
loc 749
ccs 54
cts 212
cp 0.2547
rs 5

41 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 8 2
A getType() 0 4 1
F buildPropertyBag() 0 116 22
A setDtEnd() 0 6 1
A getDtEnd() 0 4 1
A setDtStart() 0 6 1
A setDtStamp() 0 6 1
A setDuration() 0 6 1
A setLocation() 0 8 1
A setNoTime() 0 6 1
A setSequence() 0 6 1
A getSequence() 0 4 1
A setOrganizer() 0 6 1
A setSummary() 0 6 1
A setUniqueId() 0 6 1
A getUniqueId() 0 4 1
A setUrl() 0 6 1
A setUseTimezone() 0 6 1
A getUseTimezone() 0 4 1
A setAttendees() 0 6 1
A addAttendee() 0 9 2
A getAttendees() 0 4 1
A setDescription() 0 6 1
A setDescriptionHTML() 0 6 1
A setUseUtc() 0 6 1
A getDescription() 0 4 1
A getDescriptionHTML() 0 4 1
A setCancelled() 0 6 1
A setTimeTransparency() 13 13 3
A setStatus() 0 14 4
A setRecurrenceRule() 0 6 1
A getRecurrenceRule() 0 4 1
A setCreated() 0 6 1
A setModified() 0 6 1
A setCategories() 0 6 1
A setIsPrivate() 0 6 1
A addExDate() 0 5 1
A getExDates() 0 4 1
A setExDates() 0 5 1
A getRecurrenceId() 0 4 1
A setRecurrenceId() 0 5 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like Event often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Event, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/*
4
 * This file is part of the eluceo/iCal package.
5
 *
6
 * (c) Markus Poerschke <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Eluceo\iCal\Component;
13
14
use Eluceo\iCal\Component;
15
use Eluceo\iCal\Property;
16
use Eluceo\iCal\Property\DateTimeProperty;
17
use Eluceo\iCal\Property\Event\Attendees;
18
use Eluceo\iCal\Property\Event\Organizer;
19
use Eluceo\iCal\Property\Event\RecurrenceRule;
20
use Eluceo\iCal\Property\Event\Description;
21
use Eluceo\iCal\PropertyBag;
22
use Eluceo\iCal\Property\Event\RecurrenceId;
23
use Eluceo\iCal\Property\DateTimesProperty;
24
25
/**
26
 * Implementation of the EVENT component.
27
 */
28
class Event extends Component
29
{
30
    const TIME_TRANSPARENCY_OPAQUE      = 'OPAQUE';
31
    const TIME_TRANSPARENCY_TRANSPARENT = 'TRANSPARENT';
32
33
    const STATUS_TENTATIVE = 'TENTATIVE';
34
    const STATUS_CONFIRMED = 'CONFIRMED';
35
    const STATUS_CANCELLED = 'CANCELLED';
36
37
    /**
38
     * @var string
39
     */
40
    protected $uniqueId;
41
42
    /**
43
     * The property indicates the date/time that the instance of
44
     * the iCalendar object was created.
45
     *
46
     * The value MUST be specified in the UTC time format.
47
     *
48
     * @var \DateTime
49
     */
50
    protected $dtStamp;
51
52
    /**
53
     * @var \DateTime
54
     */
55
    protected $dtStart;
56
57
    /**
58
     * Preferentially chosen over the duration if both are set.
59
     *
60
     * @var \DateTime
61
     */
62
    protected $dtEnd;
63
64
    /**
65
     * @var \DateInterval
66
     */
67
    protected $duration;
68
69
    /**
70
     * @var boolean
71
     */
72
    protected $noTime = false;
73
74
    /**
75
     * @var string
76
     */
77
    protected $url;
78
79
    /**
80
     * @var string
81
     */
82
    protected $location;
83
84
    /**
85
     * @var string
86
     */
87
    protected $locationTitle;
88
89
    /**
90
     * @var string
91
     */
92
    protected $locationGeo;
93
94
    /**
95
     * @var string
96
     */
97
    protected $summary;
98
99
    /**
100
     * @var Organizer
101
     */
102
    protected $organizer;
103
104
    /**
105
     * @see http://www.ietf.org/rfc/rfc2445.txt 4.8.2.7 Time Transparency
106
     *
107
     * @var string
108
     */
109
    protected $transparency = self::TIME_TRANSPARENCY_OPAQUE;
110
111
    /**
112
     * If set to true the timezone will be added to the event.
113
     *
114
     * @var bool
115
     */
116
    protected $useTimezone = false;
117
118
    /**
119
     * @var int
120
     */
121
    protected $sequence = 0;
122
123
    /**
124
     * @var Attendees
125
     */
126
    protected $attendees;
127
128
    /**
129
     * @var string
130
     */
131
    protected $description;
132
133
    /**
134
     * @var string
135
     */
136
    protected $descriptionHTML;
137
138
    /**
139
     * @var string
140
     */
141
    protected $status;
142
143
    /**
144
     * @var RecurrenceRule
145
     */
146
    protected $recurrenceRule;
147
148
    /**
149
     * This property specifies the date and time that the calendar
150
     * information was created.
151
     *
152
     * The value MUST be specified in the UTC time format.
153
     *
154
     * @var \DateTime
155
     */
156
    protected $created;
157
158
    /**
159
     * The property specifies the date and time that the information
160
     * associated with the calendar component was last revised.
161
     *
162
     * The value MUST be specified in the UTC time format.
163
     *
164
     * @var \DateTime
165
     */
166
    protected $modified;
167
168
    /**
169
     * Indicates if the UTC time should be used or not.
170
     *
171
     * @var bool
172
     */
173
    protected $useUtc = true;
174
175
    /**
176
     * @var bool
177
     */
178
    protected $cancelled;
179
180
    /**
181
     * This property is used to specify categories or subtypes
182
     * of the calendar component.  The categories are useful in searching
183
     * for a calendar component of a particular type and category.
184
     *
185
     * @see https://tools.ietf.org/html/rfc5545#section-3.8.1.2
186
     *
187
     * @var array
188
     */
189
    protected $categories;
190
191
    /**
192
     * https://tools.ietf.org/html/rfc5545#section-3.8.1.3
193
     *
194
     * @var bool
195
     */
196
    protected $isPrivate = false;
197
    
198
    /**
199
     * Dates to be excluded from a series of events
200
     * 
201
     * @var \DateTime[]
202
     */
203
    protected $exDates = array();
204
    
205
    /**
206
     * @var RecurrenceId
207
     */
208
    protected $recurrenceId;
209
210 4
    public function __construct($uniqueId = null)
211
    {
212 4
        if (null == $uniqueId) {
213 2
            $uniqueId = uniqid();
214 2
        }
215
216 4
        $this->uniqueId = $uniqueId;
217 4
    }
218
219
    /**
220
     * {@inheritdoc}
221
     */
222 4
    public function getType()
223
    {
224 4
        return 'VEVENT';
225
    }
226
227
    /**
228
     * {@inheritdoc}
229
     */
230 4
    public function buildPropertyBag()
231
    {
232 4
        $propertyBag = new PropertyBag();
233
234
        // mandatory information
235 4
        $propertyBag->set('UID', $this->uniqueId);
236
237 4
        $propertyBag->add(new DateTimeProperty('DTSTART', $this->dtStart, $this->noTime, $this->useTimezone, $this->useUtc));
238 4
        $propertyBag->set('SEQUENCE', $this->sequence);
239 4
        $propertyBag->set('TRANSP', $this->transparency);
240
241 4
        if ($this->status) {
242
            $propertyBag->set('STATUS', $this->status);
243
        }
244
245
        // An event can have a 'dtend' or 'duration', but not both.
246 4
        if (null != $this->dtEnd) {
247 2
            $propertyBag->add(new DateTimeProperty('DTEND', $this->dtEnd, $this->noTime, $this->useTimezone, $this->useUtc));
248 4
        } elseif (null != $this->duration) {
249
            $propertyBag->set('DURATION', $this->duration->format('P%dDT%hH%iM%sS'));
250
        }
251
252
        // optional information
253 4
        if (null != $this->url) {
254
            $propertyBag->set('URL', $this->url);
255
        }
256
257 4
        if (null != $this->location) {
258
            $propertyBag->set('LOCATION', $this->location);
259
260
            if (null != $this->locationGeo) {
261
                $propertyBag->add(
262
                    new Property(
263
                        'X-APPLE-STRUCTURED-LOCATION',
264
                        'geo:' . $this->locationGeo,
265
                        array(
266
                            'VALUE'          => 'URI',
267
                            'X-ADDRESS'      => $this->location,
268
                            'X-APPLE-RADIUS' => 49,
269
                            'X-TITLE'        => $this->locationTitle,
270
                        )
271
                    )
272
                );
273
                $propertyBag->set('GEO', $this->locationGeo);
274
            }
275
        }
276
277 4
        if (null != $this->summary) {
278
            $propertyBag->set('SUMMARY', $this->summary);
279
        }
280
281 4
        if (null != $this->attendees) {
282
            $propertyBag->add($this->attendees);
283
        }
284
285 4
        $propertyBag->set('CLASS', $this->isPrivate ? 'PRIVATE' : 'PUBLIC');
286
287 4
        if (null != $this->description) {
288 2
            $propertyBag->set('DESCRIPTION', new Description($this->description));
289 2
        }
290
291 4
        if (null != $this->descriptionHTML) {
292
            $propertyBag->add(
293
                new Property(
294
                    'X-ALT-DESC',
295
                    $this->descriptionHTML,
296
                    array(
297
                        'FMTTYPE'          => 'text/html',
298
                    )
299
                )
300
            );
301
        }
302
303 4
        if (null != $this->recurrenceRule) {
304
            $propertyBag->set('RRULE', $this->recurrenceRule);
305
        }
306
        
307 4
        if (null != $this->recurrenceId) {
308
            $this->recurrenceId->applyTimeSettings($this->noTime, $this->useTimezone, $this->useUtc);
309
            $propertyBag->add($this->recurrenceId);
310
        }
311
        
312 4
        if (!empty($this->exDates)) {
313
            $propertyBag->add(new DateTimesProperty('EXDATE', $this->exDates, $this->noTime, $this->useTimezone, $this->useUtc));
314
        }
315
316 4
        if ($this->cancelled) {
317
            $propertyBag->set('STATUS', 'CANCELLED');
318
        }
319
320 4
        if (null != $this->organizer) {
321 2
            $propertyBag->add($this->organizer);
322 2
        }
323
324 4
        if ($this->noTime) {
325
            $propertyBag->set('X-MICROSOFT-CDO-ALLDAYEVENT', 'TRUE');
326
        }
327
328 4
        if (null != $this->categories) {
329
            $propertyBag->set('CATEGORIES', $this->categories);
330
        }
331
332 4
        $propertyBag->add(
333 4
            new DateTimeProperty('DTSTAMP', $this->dtStamp ?: new \DateTime(), false, false, true)
334 4
        );
335
336 4
        if ($this->created) {
337
            $propertyBag->add(new DateTimeProperty('CREATED', $this->created, false, false, true));
338
        }
339
340 4
        if ($this->modified) {
341
            $propertyBag->add(new DateTimeProperty('LAST-MODIFIED', $this->modified, false, false, true));
342
        }
343
344 4
        return $propertyBag;
345
    }
346
347
    /**
348
     * @param $dtEnd
349
     *
350
     * @return $this
351
     */
352 2
    public function setDtEnd($dtEnd)
353
    {
354 2
        $this->dtEnd = $dtEnd;
355
356 2
        return $this;
357
    }
358
359
    public function getDtEnd()
360
    {
361
        return $this->dtEnd;
362
    }
363
364 2
    public function setDtStart($dtStart)
365
    {
366 2
        $this->dtStart = $dtStart;
367
368 2
        return $this;
369
    }
370
371
    /**
372
     * @param $dtStamp
373
     *
374
     * @return $this
375
     */
376
    public function setDtStamp($dtStamp)
377
    {
378
        $this->dtStamp = $dtStamp;
379
380
        return $this;
381
    }
382
383
    /**
384
     * @param $duration
385
     *
386
     * @return $this
387
     */
388
    public function setDuration($duration)
389
    {
390
        $this->duration = $duration;
391
392
        return $this;
393
    }
394
395
    /**
396
     * @param        $location
397
     * @param string $title
398
     * @param null   $geo
399
     *
400
     * @return $this
401
     */
402
    public function setLocation($location, $title = '', $geo = null)
403
    {
404
        $this->location      = $location;
405
        $this->locationTitle = $title;
406
        $this->locationGeo   = $geo;
407
408
        return $this;
409
    }
410
411
    /**
412
     * @param $noTime
413
     *
414
     * @return $this
415
     */
416
    public function setNoTime($noTime)
417
    {
418
        $this->noTime = $noTime;
419
420
        return $this;
421
    }
422
423
    /**
424
     * @param int $sequence
425
     *
426
     * @return $this
427
     */
428
    public function setSequence($sequence)
429
    {
430
        $this->sequence = $sequence;
431
432
        return $this;
433
    }
434
435
    /**
436
     * @return int
437
     */
438
    public function getSequence()
439
    {
440
        return $this->sequence;
441
    }
442
443
    /**
444
     * @param Organizer $organizer
445
     * @return $this
446
     */
447 2
    public function setOrganizer(Organizer $organizer)
448
    {
449 2
        $this->organizer = $organizer;
450
451 2
        return $this;
452
    }
453
454
    /**
455
     * @param $summary
456
     *
457
     * @return $this
458
     */
459
    public function setSummary($summary)
460
    {
461
        $this->summary = $summary;
462
463
        return $this;
464
    }
465
466
    /**
467
     * @param $uniqueId
468
     *
469
     * @return $this
470
     */
471
    public function setUniqueId($uniqueId)
472
    {
473
        $this->uniqueId = $uniqueId;
474
475
        return $this;
476
    }
477
478
    /**
479
     * @return string
480
     */
481
    public function getUniqueId()
482
    {
483
        return $this->uniqueId;
484
    }
485
486
    /**
487
     * @param $url
488
     *
489
     * @return $this
490
     */
491
    public function setUrl($url)
492
    {
493
        $this->url = $url;
494
495
        return $this;
496
    }
497
498
    /**
499
     * @param $useTimezone
500
     *
501
     * @return $this
502
     */
503
    public function setUseTimezone($useTimezone)
504
    {
505
        $this->useTimezone = $useTimezone;
506
507
        return $this;
508
    }
509
510
    /**
511
     * @return bool
512
     */
513
    public function getUseTimezone()
514
    {
515
        return $this->useTimezone;
516
    }
517
518
    /**
519
     * @param Attendees $attendees
520
     *
521
     * @return $this
522
     */
523
    public function setAttendees(Attendees $attendees)
524
    {
525
        $this->attendees = $attendees;
526
527
        return $this;
528
    }
529
530
    /**
531
     * @param string $attendee
532
     * @param array  $params
533
     *
534
     * @return $this
535
     */
536
    public function addAttendee($attendee, $params = array())
537
    {
538
        if (!isset($this->attendees)) {
539
            $this->attendees = new Attendees();
540
        }
541
        $this->attendees->add($attendee, $params);
542
543
        return $this;
544
    }
545
546
    /**
547
     * @return Attendees
548
     */
549
    public function getAttendees()
550
    {
551
        return $this->attendees;
552
    }
553
554
    /**
555
     * @param $description
556
     *
557
     * @return $this
558
     */
559 2
    public function setDescription($description)
560
    {
561 2
        $this->description = $description;
562
563 2
        return $this;
564
    }
565
566
    /**
567
     * @param $descriptionHTML
568
     *
569
     * @return $this
570
     */
571
    public function setDescriptionHTML($descriptionHTML)
572
    {
573
        $this->descriptionHTML = $descriptionHTML;
574
575
        return $this;
576
    }
577
578
    /**
579
     * @param bool $useUtc
580
     *
581
     * @return $this
582
     */
583
    public function setUseUtc($useUtc = true)
584
    {
585
        $this->useUtc = $useUtc;
586
587
        return $this;
588
    }
589
590
    /**
591
     * @return string
592
     */
593
    public function getDescription()
594
    {
595
        return $this->description;
596
    }
597
598
    /**
599
     * @return string
600
     */
601
    public function getDescriptionHTML()
602
    {
603
        return $this->descriptionHTML;
604
    }
605
606
    /**
607
     * @param $status
608
     *
609
     * @return $this
610
     */
611
    public function setCancelled($status)
612
    {
613
        $this->cancelled = (bool) $status;
614
615
        return $this;
616
    }
617
618
    /**
619
     * @param $transparency
620
     *
621
     * @return $this
622
     *
623
     * @throws \InvalidArgumentException
624
     */
625 View Code Duplication
    public function setTimeTransparency($transparency)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
626
    {
627
        $transparency = strtoupper($transparency);
628
        if ($transparency === self::TIME_TRANSPARENCY_OPAQUE
629
            || $transparency === self::TIME_TRANSPARENCY_TRANSPARENT
630
        ) {
631
            $this->transparency = $transparency;
632
        } else {
633
            throw new \InvalidArgumentException('Invalid value for transparancy');
634
        }
635
636
        return $this;
637
    }
638
639
    /**
640
     * @param $status
641
     *
642
     * @return $this
643
     *
644
     * @throws \InvalidArgumentException
645
     */
646
    public function setStatus($status)
647
    {
648
        $status = strtoupper($status);
649
        if ($status == self::STATUS_CANCELLED
650
            || $status == self::STATUS_CONFIRMED
651
            || $status == self::STATUS_TENTATIVE
652
        ) {
653
            $this->status = $status;
654
        } else {
655
            throw new \InvalidArgumentException('Invalid value for status');
656
        }
657
658
        return $this;
659
    }
660
661
    /**
662
     * @param RecurrenceRule $recurrenceRule
663
     *
664
     * @return $this
665
     */
666
    public function setRecurrenceRule(RecurrenceRule $recurrenceRule)
667
    {
668
        $this->recurrenceRule = $recurrenceRule;
669
670
        return $this;
671
    }
672
673
    /**
674
     * @return RecurrenceRule
675
     */
676
    public function getRecurrenceRule()
677
    {
678
        return $this->recurrenceRule;
679
    }
680
681
    /**
682
     * @param $dtStamp
683
     *
684
     * @return $this
685
     */
686
    public function setCreated($dtStamp)
687
    {
688
        $this->created = $dtStamp;
689
690
        return $this;
691
    }
692
693
    /**
694
     * @param $dtStamp
695
     *
696
     * @return $this
697
     */
698
    public function setModified($dtStamp)
699
    {
700
        $this->modified = $dtStamp;
701
702
        return $this;
703
    }
704
705
    /**
706
     * @param $categories
707
     *
708
     * @return $this
709
     */
710
    public function setCategories($categories)
711
    {
712
        $this->categories = $categories;
713
714
        return $this;
715
    }
716
717
    /**
718
     * Sets the event privacy
719
     *
720
     * @param bool $flag
721
     * @return $this
722
     */
723
    public function setIsPrivate($flag)
724
    {
725
        $this->isPrivate = (bool) $flag;
726
727
        return $this;
728
    }
729
730
    /**
731
     * @param \DateTime $dateTime
732
     * @return \Eluceo\iCal\Component\Event
733
     */
734
    public function addExDate(\DateTime $dateTime)
735
    {
736
        $this->exDates[] = $dateTime;
737
        return $this;
738
    }
739
    
740
    /**
741
     * @return DateTime[]
742
     */
743
    public function getExDates()
744
    {
745
        return $this->exDates;
746
    }
747
748
    /**
749
     * @param \DateTime[]
750
     * @return \Eluceo\iCal\Component\Event
751
     */
752
    public function setExDates(Array $exDates)
753
    {
754
        $this->exDates = $exDates;
755
        return $this;
756
    }
757
758
    /**
759
     * @return \Eluceo\iCal\Property\Event\RecurrenceId
760
     */
761
    public function getRecurrenceId()
762
    {
763
        return $this->recurrenceId;
764
    }
765
766
    /**
767
     * @param RecurrenceId $recurrenceId
768
     * @return \Eluceo\iCal\Component\Event
769
     */
770
    public function setRecurrenceId(RecurrenceId $recurrenceId)
771
    {
772
        $this->recurrenceId = $recurrenceId;
773
        return $this;
774
    }
775
 
776
}
777