Completed
Pull Request — master (#83)
by Oliver
03:40
created

Event::setRecurrenceRule()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 2
Bugs 0 Features 0
Metric Value
dl 0
loc 8
ccs 0
cts 0
cp 0
rs 9.4285
c 2
b 0
f 0
nc 1
cc 1
eloc 4
nop 1
crap 2
1
<?php
2
3
/*
4
 * This file is part of the eluceo/iCal package.
5
 *
6
 * (c) Markus Poerschke <[email protected]>
7
 *
8
 * This source file is subject to the MIT license that is bundled
9
 * with this source code in the file LICENSE.
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 bool
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
     * @var array
150
     */
151
    protected $recurrenceRules = array();
152
153
    /**
154
     * This property specifies the date and time that the calendar
155
     * information was created.
156
     *
157
     * The value MUST be specified in the UTC time format.
158
     *
159
     * @var \DateTime
160
     */
161
    protected $created;
162
163
    /**
164
     * The property specifies the date and time that the information
165
     * associated with the calendar component was last revised.
166
     *
167
     * The value MUST be specified in the UTC time format.
168
     *
169
     * @var \DateTime
170
     */
171
    protected $modified;
172
173
    /**
174
     * Indicates if the UTC time should be used or not.
175
     *
176
     * @var bool
177
     */
178
    protected $useUtc = true;
179
180
    /**
181
     * @var bool
182
     */
183
    protected $cancelled;
184
185
    /**
186
     * This property is used to specify categories or subtypes
187
     * of the calendar component.  The categories are useful in searching
188
     * for a calendar component of a particular type and category.
189
     *
190
     * @see https://tools.ietf.org/html/rfc5545#section-3.8.1.2
191
     *
192
     * @var array
193
     */
194
    protected $categories;
195
196
    /**
197
     * https://tools.ietf.org/html/rfc5545#section-3.8.1.3.
198
     *
199
     * @var bool
200
     */
201
    protected $isPrivate = false;
202
203
    /**
204
     * Dates to be excluded from a series of events.
205
     *
206
     * @var \DateTime[]
207
     */
208
    protected $exDates = array();
209
210
    /**
211
     * @var RecurrenceId
212
     */
213
    protected $recurrenceId;
214
215 4
    public function __construct($uniqueId = null)
216
    {
217 4
        if (null == $uniqueId) {
218 2
            $uniqueId = uniqid();
219
        }
220
221 4
        $this->uniqueId = $uniqueId;
222 4
    }
223
224
    /**
225
     * {@inheritdoc}
226
     */
227 4
    public function getType()
228
    {
229 4
        return 'VEVENT';
230
    }
231
232
    /**
233
     * {@inheritdoc}
234
     */
235 4
    public function buildPropertyBag()
236
    {
237 4
        $propertyBag = new PropertyBag();
238
239
        // mandatory information
240 4
        $propertyBag->set('UID', $this->uniqueId);
241
242 4
        $propertyBag->add(new DateTimeProperty('DTSTART', $this->dtStart, $this->noTime, $this->useTimezone, $this->useUtc));
243 4
        $propertyBag->set('SEQUENCE', $this->sequence);
244 4
        $propertyBag->set('TRANSP', $this->transparency);
245
246 4
        if ($this->status) {
247
            $propertyBag->set('STATUS', $this->status);
248
        }
249
250
        // An event can have a 'dtend' or 'duration', but not both.
251 4
        if (null != $this->dtEnd) {
252 2
            $propertyBag->add(new DateTimeProperty('DTEND', $this->dtEnd, $this->noTime, $this->useTimezone, $this->useUtc));
253 2
        } elseif (null != $this->duration) {
254
            $propertyBag->set('DURATION', $this->duration->format('P%dDT%hH%iM%sS'));
255
        }
256
257
        // optional information
258 4
        if (null != $this->url) {
259
            $propertyBag->set('URL', $this->url);
260
        }
261
262 4
        if (null != $this->location) {
263
            $propertyBag->set('LOCATION', $this->location);
264
265
            if (null != $this->locationGeo) {
266
                $propertyBag->add(
267
                    new Property(
268
                        'X-APPLE-STRUCTURED-LOCATION',
269
                        'geo:' . $this->locationGeo,
270
                        array(
271
                            'VALUE'          => 'URI',
272
                            'X-ADDRESS'      => $this->location,
273
                            'X-APPLE-RADIUS' => 49,
274
                            'X-TITLE'        => $this->locationTitle,
275
                        )
276
                    )
277
                );
278
                $propertyBag->set('GEO', str_replace(',', ';', $this->locationGeo));
279
            }
280
        }
281
282 4
        if (null != $this->summary) {
283
            $propertyBag->set('SUMMARY', $this->summary);
284
        }
285
286 4
        if (null != $this->attendees) {
287
            $propertyBag->add($this->attendees);
288
        }
289
290 4
        $propertyBag->set('CLASS', $this->isPrivate ? 'PRIVATE' : 'PUBLIC');
291
292 4
        if (null != $this->description) {
293 2
            $propertyBag->set('DESCRIPTION', new Description($this->description));
294
        }
295
296 4
        if (null != $this->descriptionHTML) {
297
            $propertyBag->add(
298
                new Property(
299
                    'X-ALT-DESC',
300
                    $this->descriptionHTML,
301
                    array(
302
                        'FMTTYPE' => 'text/html',
303
                    )
304
                )
305
            );
306
        }
307
308 4
        if (null != $this->recurrenceRule) {
309
            $propertyBag->set('RRULE', $this->recurrenceRule);
310
        }
311
312 4
        foreach ($this->recurrenceRules as $recurrenceRule) {
313
            $propertyBag->set('RRULE', $recurrenceRule);
314
        }
315
316 4
        if (null != $this->recurrenceId) {
317
            $this->recurrenceId->applyTimeSettings($this->noTime, $this->useTimezone, $this->useUtc);
318
            $propertyBag->add($this->recurrenceId);
319
        }
320
321 4
        if (!empty($this->exDates)) {
322
            $propertyBag->add(new DateTimesProperty('EXDATE', $this->exDates, $this->noTime, $this->useTimezone, $this->useUtc));
323
        }
324
325 4
        if ($this->cancelled) {
326
            $propertyBag->set('STATUS', 'CANCELLED');
327
        }
328
329 4
        if (null != $this->organizer) {
330 2
            $propertyBag->add($this->organizer);
331
        }
332
333 4
        if ($this->noTime) {
334
            $propertyBag->set('X-MICROSOFT-CDO-ALLDAYEVENT', 'TRUE');
335
        }
336
337 4
        if (null != $this->categories) {
338
            $propertyBag->set('CATEGORIES', $this->categories);
339
        }
340
341 4
        $propertyBag->add(
342 4
            new DateTimeProperty('DTSTAMP', $this->dtStamp ?: new \DateTime(), false, false, true)
343
        );
344
345 4
        if ($this->created) {
346
            $propertyBag->add(new DateTimeProperty('CREATED', $this->created, false, false, true));
347
        }
348
349 4
        if ($this->modified) {
350
            $propertyBag->add(new DateTimeProperty('LAST-MODIFIED', $this->modified, false, false, true));
351
        }
352
353 4
        return $propertyBag;
354
    }
355
356
    /**
357
     * @param $dtEnd
358
     *
359
     * @return $this
360
     */
361 2
    public function setDtEnd($dtEnd)
362
    {
363 2
        $this->dtEnd = $dtEnd;
364
365 2
        return $this;
366
    }
367
368
    public function getDtEnd()
369
    {
370
        return $this->dtEnd;
371
    }
372
373 2
    public function setDtStart($dtStart)
374
    {
375 2
        $this->dtStart = $dtStart;
376
377 2
        return $this;
378
    }
379
380
    public function getDtStart()
381
    {
382
        return $this->dtStart;
383
    }
384
385
    /**
386
     * @param $dtStamp
387
     *
388
     * @return $this
389
     */
390
    public function setDtStamp($dtStamp)
391
    {
392
        $this->dtStamp = $dtStamp;
393
394
        return $this;
395
    }
396
397
    /**
398
     * @param $duration
399
     *
400
     * @return $this
401
     */
402
    public function setDuration($duration)
403
    {
404
        $this->duration = $duration;
405
406
        return $this;
407
    }
408
409
    /**
410
     * @param        $location
411
     * @param string $title
412
     * @param null   $geo
413
     *
414
     * @return $this
415
     */
416
    public function setLocation($location, $title = '', $geo = null)
417
    {
418
        $this->location      = $location;
419
        $this->locationTitle = $title;
420
        $this->locationGeo   = $geo;
421
422
        return $this;
423
    }
424
425
    /**
426
     * @param $noTime
427
     *
428
     * @return $this
429
     */
430
    public function setNoTime($noTime)
431
    {
432
        $this->noTime = $noTime;
433
434
        return $this;
435
    }
436
437
    /**
438
     * @param int $sequence
439
     *
440
     * @return $this
441
     */
442
    public function setSequence($sequence)
443
    {
444
        $this->sequence = $sequence;
445
446
        return $this;
447
    }
448
449
    /**
450
     * @return int
451
     */
452
    public function getSequence()
453
    {
454
        return $this->sequence;
455
    }
456
457
    /**
458
     * @param Organizer $organizer
459
     *
460
     * @return $this
461
     */
462 2
    public function setOrganizer(Organizer $organizer)
463
    {
464 2
        $this->organizer = $organizer;
465
466 2
        return $this;
467
    }
468
469
    /**
470
     * @param $summary
471
     *
472
     * @return $this
473
     */
474
    public function setSummary($summary)
475
    {
476
        $this->summary = $summary;
477
478
        return $this;
479
    }
480
481
    /**
482
     * @param $uniqueId
483
     *
484
     * @return $this
485
     */
486
    public function setUniqueId($uniqueId)
487
    {
488
        $this->uniqueId = $uniqueId;
489
490
        return $this;
491
    }
492
493
    /**
494
     * @return string
495
     */
496
    public function getUniqueId()
497
    {
498
        return $this->uniqueId;
499
    }
500
501
    /**
502
     * @param $url
503
     *
504
     * @return $this
505
     */
506
    public function setUrl($url)
507
    {
508
        $this->url = $url;
509
510
        return $this;
511
    }
512
513
    /**
514
     * @param $useTimezone
515
     *
516
     * @return $this
517
     */
518
    public function setUseTimezone($useTimezone)
519
    {
520
        $this->useTimezone = $useTimezone;
521
522
        return $this;
523
    }
524
525
    /**
526
     * @return bool
527
     */
528
    public function getUseTimezone()
529
    {
530
        return $this->useTimezone;
531
    }
532
533
    /**
534
     * @param Attendees $attendees
535
     *
536
     * @return $this
537
     */
538
    public function setAttendees(Attendees $attendees)
539
    {
540
        $this->attendees = $attendees;
541
542
        return $this;
543
    }
544
545
    /**
546
     * @param string $attendee
547
     * @param array  $params
548
     *
549
     * @return $this
550
     */
551
    public function addAttendee($attendee, $params = array())
552
    {
553
        if (!isset($this->attendees)) {
554
            $this->attendees = new Attendees();
555
        }
556
        $this->attendees->add($attendee, $params);
557
558
        return $this;
559
    }
560
561
    /**
562
     * @return Attendees
563
     */
564
    public function getAttendees()
565
    {
566
        return $this->attendees;
567
    }
568
569
    /**
570
     * @param $description
571
     *
572
     * @return $this
573
     */
574 2
    public function setDescription($description)
575
    {
576 2
        $this->description = $description;
577
578 2
        return $this;
579
    }
580
581
    /**
582
     * @param $descriptionHTML
583
     *
584
     * @return $this
585
     */
586
    public function setDescriptionHTML($descriptionHTML)
587
    {
588
        $this->descriptionHTML = $descriptionHTML;
589
590
        return $this;
591
    }
592
593
    /**
594
     * @param bool $useUtc
595
     *
596
     * @return $this
597
     */
598
    public function setUseUtc($useUtc = true)
599
    {
600
        $this->useUtc = $useUtc;
601
602
        return $this;
603
    }
604
605
    /**
606
     * @return string
607
     */
608
    public function getDescription()
609
    {
610
        return $this->description;
611
    }
612
613
    /**
614
     * @return string
615
     */
616
    public function getDescriptionHTML()
617
    {
618
        return $this->descriptionHTML;
619
    }
620
621
    /**
622
     * @param $status
623
     *
624
     * @return $this
625
     */
626
    public function setCancelled($status)
627
    {
628
        $this->cancelled = (bool) $status;
629
630
        return $this;
631
    }
632
633
    /**
634
     * @param $transparency
635
     *
636
     * @return $this
637
     *
638
     * @throws \InvalidArgumentException
639
     */
640 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...
641
    {
642
        $transparency = strtoupper($transparency);
643
        if ($transparency === self::TIME_TRANSPARENCY_OPAQUE
644
            || $transparency === self::TIME_TRANSPARENCY_TRANSPARENT
645
        ) {
646
            $this->transparency = $transparency;
647
        } else {
648
            throw new \InvalidArgumentException('Invalid value for transparancy');
649
        }
650
651
        return $this;
652
    }
653
654
    /**
655
     * @param $status
656
     *
657
     * @return $this
658
     *
659
     * @throws \InvalidArgumentException
660
     */
661
    public function setStatus($status)
662
    {
663
        $status = strtoupper($status);
664
        if ($status == self::STATUS_CANCELLED
665
            || $status == self::STATUS_CONFIRMED
666
            || $status == self::STATUS_TENTATIVE
667
        ) {
668
            $this->status = $status;
669
        } else {
670
            throw new \InvalidArgumentException('Invalid value for status');
671
        }
672
673
        return $this;
674
    }
675
676
    /**
677
     * @deprecated Deprecated since version 0.11.0, to be removed in 1.0. Use addRecurrenceRule instead.
678
     *
679
     * @param RecurrenceRule $recurrenceRule
680
     *
681
     * @return $this
682
     */
683
    public function setRecurrenceRule(RecurrenceRule $recurrenceRule)
684
    {
685
        @trigger_error('setRecurrenceRule() is deprecated since version 0.11.0 and will be removed in 1.0. Use addRecurrenceRule instead.', E_USER_DEPRECATED);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
686
687
        $this->recurrenceRule = $recurrenceRule;
688
689
        return $this;
690
    }
691
692
    /**
693
     * @deprecated Deprecated since version 0.11.0, to be removed in 1.0. Use getRecurrenceRules instead.
694
     *
695
     * @return RecurrenceRule
696
     */
697
    public function getRecurrenceRule()
698
    {
699
        @trigger_error('getRecurrenceRule() is deprecated since version 0.11.0 and will be removed in 1.0. Use getRecurrenceRules instead.', E_USER_DEPRECATED);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
700
701
        return $this->recurrenceRule;
702
    }
703
704
    /**
705
     * @param RecurrenceRule $recurrenceRule
706
     *
707
     * @return $this
708
     */
709
    public function addRecurrenceRule(RecurrenceRule $recurrenceRule)
710
    {
711
        $this->recurrenceRules[] = $recurrenceRule;
712
713
        return $this;
714
    }
715
716
    /**
717
     * @return array
718
     */
719
    public function getRecurrenceRules()
720
    {
721
        return $this->recurrenceRules;
722
    }
723
724
    /**
725
     * @param $dtStamp
726
     *
727
     * @return $this
728
     */
729
    public function setCreated($dtStamp)
730
    {
731
        $this->created = $dtStamp;
732
733
        return $this;
734
    }
735
736
    /**
737
     * @param $dtStamp
738
     *
739
     * @return $this
740
     */
741
    public function setModified($dtStamp)
742
    {
743
        $this->modified = $dtStamp;
744
745
        return $this;
746
    }
747
748
    /**
749
     * @param $categories
750
     *
751
     * @return $this
752
     */
753
    public function setCategories($categories)
754
    {
755
        $this->categories = $categories;
756
757
        return $this;
758
    }
759
760
    /**
761
     * Sets the event privacy.
762
     *
763
     * @param bool $flag
764
     *
765
     * @return $this
766
     */
767
    public function setIsPrivate($flag)
768
    {
769
        $this->isPrivate = (bool) $flag;
770
771
        return $this;
772
    }
773
774
    /**
775
     * @param \DateTime $dateTime
776
     *
777
     * @return \Eluceo\iCal\Component\Event
778
     */
779
    public function addExDate(\DateTime $dateTime)
780
    {
781
        $this->exDates[] = $dateTime;
782
783
        return $this;
784
    }
785
786
    /**
787
     * @return \DateTime[]
788
     */
789
    public function getExDates()
790
    {
791
        return $this->exDates;
792
    }
793
794
    /**
795
     * @param \DateTime[]
796
     *
797
     * @return \Eluceo\iCal\Component\Event
798
     */
799
    public function setExDates(array $exDates)
800
    {
801
        $this->exDates = $exDates;
802
803
        return $this;
804
    }
805
806
    /**
807
     * @return \Eluceo\iCal\Property\Event\RecurrenceId
808
     */
809
    public function getRecurrenceId()
810
    {
811
        return $this->recurrenceId;
812
    }
813
814
    /**
815
     * @param RecurrenceId $recurrenceId
816
     *
817
     * @return \Eluceo\iCal\Component\Event
818
     */
819
    public function setRecurrenceId(RecurrenceId $recurrenceId)
820
    {
821
        $this->recurrenceId = $recurrenceId;
822
823
        return $this;
824
    }
825
}
826