Completed
Pull Request — master (#83)
by Oliver
02:25
created

Event::getDtStart()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 4
ccs 0
cts 2
cp 0
rs 10
cc 1
eloc 2
nc 1
nop 0
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 2
        }
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
            if($this->noTime === true) {
253
                $this->dtEnd->add(new \DateInterval('P1D'));
254
            }
255 2
            $propertyBag->add(new DateTimeProperty('DTEND', $this->dtEnd, $this->noTime, $this->useTimezone, $this->useUtc));
256 4
        } elseif (null != $this->duration) {
257
            $propertyBag->set('DURATION', $this->duration->format('P%dDT%hH%iM%sS'));
258
        }
259
260
        // optional information
261 4
        if (null != $this->url) {
262
            $propertyBag->set('URL', $this->url);
263
        }
264
265 4
        if (null != $this->location) {
266
            $propertyBag->set('LOCATION', $this->location);
267
268
            if (null != $this->locationGeo) {
269
                $propertyBag->add(
270
                    new Property(
271
                        'X-APPLE-STRUCTURED-LOCATION',
272
                        'geo:' . $this->locationGeo,
273
                        array(
274
                            'VALUE'          => 'URI',
275
                            'X-ADDRESS'      => $this->location,
276
                            'X-APPLE-RADIUS' => 49,
277
                            'X-TITLE'        => $this->locationTitle,
278
                        )
279
                    )
280
                );
281
                $propertyBag->set('GEO', str_replace(',', ';', $this->locationGeo));
282
            }
283
        }
284
285 4
        if (null != $this->summary) {
286
            $propertyBag->set('SUMMARY', $this->summary);
287
        }
288
289 4
        if (null != $this->attendees) {
290
            $propertyBag->add($this->attendees);
291
        }
292
293 4
        $propertyBag->set('CLASS', $this->isPrivate ? 'PRIVATE' : 'PUBLIC');
294
295 4
        if (null != $this->description) {
296 2
            $propertyBag->set('DESCRIPTION', new Description($this->description));
297 2
        }
298
299 4
        if (null != $this->descriptionHTML) {
300
            $propertyBag->add(
301
                new Property(
302
                    'X-ALT-DESC',
303
                    $this->descriptionHTML,
304
                    array(
305
                        'FMTTYPE' => 'text/html',
306
                    )
307
                )
308
            );
309
        }
310
311 4
        if (null != $this->recurrenceRule) {
312
            $propertyBag->set('RRULE', $this->recurrenceRule);
313
        }
314
315 4
        foreach ($this->recurrenceRules as $recurrenceRule) {
316
            $propertyBag->set('RRULE', $recurrenceRule);
317 4
        }
318
319 4
        if (null != $this->recurrenceId) {
320
            $this->recurrenceId->applyTimeSettings($this->noTime, $this->useTimezone, $this->useUtc);
321
            $propertyBag->add($this->recurrenceId);
322
        }
323
324 4
        if (!empty($this->exDates)) {
325
            $propertyBag->add(new DateTimesProperty('EXDATE', $this->exDates, $this->noTime, $this->useTimezone, $this->useUtc));
326
        }
327
328 4
        if ($this->cancelled) {
329
            $propertyBag->set('STATUS', 'CANCELLED');
330
        }
331
332 4
        if (null != $this->organizer) {
333 2
            $propertyBag->add($this->organizer);
334 2
        }
335
336 4
        if ($this->noTime) {
337
            $propertyBag->set('X-MICROSOFT-CDO-ALLDAYEVENT', 'TRUE');
338
        }
339
340 4
        if (null != $this->categories) {
341
            $propertyBag->set('CATEGORIES', $this->categories);
342
        }
343
344 4
        $propertyBag->add(
345 4
            new DateTimeProperty('DTSTAMP', $this->dtStamp ?: new \DateTime(), false, false, true)
346 4
        );
347
348 4
        if ($this->created) {
349
            $propertyBag->add(new DateTimeProperty('CREATED', $this->created, false, false, true));
350
        }
351
352 4
        if ($this->modified) {
353
            $propertyBag->add(new DateTimeProperty('LAST-MODIFIED', $this->modified, false, false, true));
354
        }
355
356 4
        return $propertyBag;
357
    }
358
359
    /**
360
     * @param $dtEnd
361
     *
362
     * @return $this
363
     */
364 2
    public function setDtEnd($dtEnd)
365
    {
366 2
        $this->dtEnd = $dtEnd;
367
368 2
        return $this;
369
    }
370
371
    public function getDtEnd()
372
    {
373
        return $this->dtEnd;
374
    }
375
376 2
    public function setDtStart($dtStart)
377
    {
378 2
        $this->dtStart = $dtStart;
379
380 2
        return $this;
381
    }
382
383
    public function getDtStart()
384
    {
385
        return $this->dtStart;
386
    }
387
388
    /**
389
     * @param $dtStamp
390
     *
391
     * @return $this
392
     */
393
    public function setDtStamp($dtStamp)
394
    {
395
        $this->dtStamp = $dtStamp;
396
397
        return $this;
398
    }
399
400
    /**
401
     * @param $duration
402
     *
403
     * @return $this
404
     */
405
    public function setDuration($duration)
406
    {
407
        $this->duration = $duration;
408
409
        return $this;
410
    }
411
412
    /**
413
     * @param        $location
414
     * @param string $title
415
     * @param null   $geo
416
     *
417
     * @return $this
418
     */
419
    public function setLocation($location, $title = '', $geo = null)
420
    {
421
        $this->location      = $location;
422
        $this->locationTitle = $title;
423
        $this->locationGeo   = $geo;
424
425
        return $this;
426
    }
427
428
    /**
429
     * @param $noTime
430
     *
431
     * @return $this
432
     */
433
    public function setNoTime($noTime)
434
    {
435
        $this->noTime = $noTime;
436
437
        return $this;
438
    }
439
440
    /**
441
     * @param int $sequence
442
     *
443
     * @return $this
444
     */
445
    public function setSequence($sequence)
446
    {
447
        $this->sequence = $sequence;
448
449
        return $this;
450
    }
451
452
    /**
453
     * @return int
454
     */
455
    public function getSequence()
456
    {
457
        return $this->sequence;
458
    }
459
460
    /**
461
     * @param Organizer $organizer
462
     *
463
     * @return $this
464
     */
465 2
    public function setOrganizer(Organizer $organizer)
466
    {
467 2
        $this->organizer = $organizer;
468
469 2
        return $this;
470
    }
471
472
    /**
473
     * @param $summary
474
     *
475
     * @return $this
476
     */
477
    public function setSummary($summary)
478
    {
479
        $this->summary = $summary;
480
481
        return $this;
482
    }
483
484
    /**
485
     * @param $uniqueId
486
     *
487
     * @return $this
488
     */
489
    public function setUniqueId($uniqueId)
490
    {
491
        $this->uniqueId = $uniqueId;
492
493
        return $this;
494
    }
495
496
    /**
497
     * @return string
498
     */
499
    public function getUniqueId()
500
    {
501
        return $this->uniqueId;
502
    }
503
504
    /**
505
     * @param $url
506
     *
507
     * @return $this
508
     */
509
    public function setUrl($url)
510
    {
511
        $this->url = $url;
512
513
        return $this;
514
    }
515
516
    /**
517
     * @param $useTimezone
518
     *
519
     * @return $this
520
     */
521
    public function setUseTimezone($useTimezone)
522
    {
523
        $this->useTimezone = $useTimezone;
524
525
        return $this;
526
    }
527
528
    /**
529
     * @return bool
530
     */
531
    public function getUseTimezone()
532
    {
533
        return $this->useTimezone;
534
    }
535
536
    /**
537
     * @param Attendees $attendees
538
     *
539
     * @return $this
540
     */
541
    public function setAttendees(Attendees $attendees)
542
    {
543
        $this->attendees = $attendees;
544
545
        return $this;
546
    }
547
548
    /**
549
     * @param string $attendee
550
     * @param array  $params
551
     *
552
     * @return $this
553
     */
554
    public function addAttendee($attendee, $params = array())
555
    {
556
        if (!isset($this->attendees)) {
557
            $this->attendees = new Attendees();
558
        }
559
        $this->attendees->add($attendee, $params);
560
561
        return $this;
562
    }
563
564
    /**
565
     * @return Attendees
566
     */
567
    public function getAttendees()
568
    {
569
        return $this->attendees;
570
    }
571
572
    /**
573
     * @param $description
574
     *
575
     * @return $this
576
     */
577 2
    public function setDescription($description)
578
    {
579 2
        $this->description = $description;
580
581 2
        return $this;
582
    }
583
584
    /**
585
     * @param $descriptionHTML
586
     *
587
     * @return $this
588
     */
589
    public function setDescriptionHTML($descriptionHTML)
590
    {
591
        $this->descriptionHTML = $descriptionHTML;
592
593
        return $this;
594
    }
595
596
    /**
597
     * @param bool $useUtc
598
     *
599
     * @return $this
600
     */
601
    public function setUseUtc($useUtc = true)
602
    {
603
        $this->useUtc = $useUtc;
604
605
        return $this;
606
    }
607
608
    /**
609
     * @return string
610
     */
611
    public function getDescription()
612
    {
613
        return $this->description;
614
    }
615
616
    /**
617
     * @return string
618
     */
619
    public function getDescriptionHTML()
620
    {
621
        return $this->descriptionHTML;
622
    }
623
624
    /**
625
     * @param $status
626
     *
627
     * @return $this
628
     */
629
    public function setCancelled($status)
630
    {
631
        $this->cancelled = (bool) $status;
632
633
        return $this;
634
    }
635
636
    /**
637
     * @param $transparency
638
     *
639
     * @return $this
640
     *
641
     * @throws \InvalidArgumentException
642
     */
643 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...
644
    {
645
        $transparency = strtoupper($transparency);
646
        if ($transparency === self::TIME_TRANSPARENCY_OPAQUE
647
            || $transparency === self::TIME_TRANSPARENCY_TRANSPARENT
648
        ) {
649
            $this->transparency = $transparency;
650
        } else {
651
            throw new \InvalidArgumentException('Invalid value for transparancy');
652
        }
653
654
        return $this;
655
    }
656
657
    /**
658
     * @param $status
659
     *
660
     * @return $this
661
     *
662
     * @throws \InvalidArgumentException
663
     */
664
    public function setStatus($status)
665
    {
666
        $status = strtoupper($status);
667
        if ($status == self::STATUS_CANCELLED
668
            || $status == self::STATUS_CONFIRMED
669
            || $status == self::STATUS_TENTATIVE
670
        ) {
671
            $this->status = $status;
672
        } else {
673
            throw new \InvalidArgumentException('Invalid value for status');
674
        }
675
676
        return $this;
677
    }
678
679
    /**
680
     * @deprecated Deprecated since version 0.11.0, to be removed in 1.0. Use addRecurrenceRule instead.
681
     *
682
     * @param RecurrenceRule $recurrenceRule
683
     *
684
     * @return $this
685
     */
686
    public function setRecurrenceRule(RecurrenceRule $recurrenceRule)
687
    {
688
        @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...
689
690
        $this->recurrenceRule = $recurrenceRule;
691
692
        return $this;
693
    }
694
695
    /**
696
     * @deprecated Deprecated since version 0.11.0, to be removed in 1.0. Use getRecurrenceRules instead.
697
     *
698
     * @return RecurrenceRule
699
     */
700
    public function getRecurrenceRule()
701
    {
702
        @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...
703
704
        return $this->recurrenceRule;
705
    }
706
707
    /**
708
     * @param RecurrenceRule $recurrenceRule
709
     *
710
     * @return $this
711
     */
712
    public function addRecurrenceRule(RecurrenceRule $recurrenceRule)
713
    {
714
        $this->recurrenceRules[] = $recurrenceRule;
715
716
        return $this;
717
    }
718
719
    /**
720
     * @return array
721
     */
722
    public function getRecurrenceRules()
723
    {
724
        return $this->recurrenceRules;
725
    }
726
727
    /**
728
     * @param $dtStamp
729
     *
730
     * @return $this
731
     */
732
    public function setCreated($dtStamp)
733
    {
734
        $this->created = $dtStamp;
735
736
        return $this;
737
    }
738
739
    /**
740
     * @param $dtStamp
741
     *
742
     * @return $this
743
     */
744
    public function setModified($dtStamp)
745
    {
746
        $this->modified = $dtStamp;
747
748
        return $this;
749
    }
750
751
    /**
752
     * @param $categories
753
     *
754
     * @return $this
755
     */
756
    public function setCategories($categories)
757
    {
758
        $this->categories = $categories;
759
760
        return $this;
761
    }
762
763
    /**
764
     * Sets the event privacy.
765
     *
766
     * @param bool $flag
767
     *
768
     * @return $this
769
     */
770
    public function setIsPrivate($flag)
771
    {
772
        $this->isPrivate = (bool) $flag;
773
774
        return $this;
775
    }
776
777
    /**
778
     * @param \DateTime $dateTime
779
     *
780
     * @return \Eluceo\iCal\Component\Event
781
     */
782
    public function addExDate(\DateTime $dateTime)
783
    {
784
        $this->exDates[] = $dateTime;
785
786
        return $this;
787
    }
788
789
    /**
790
     * @return \DateTime[]
791
     */
792
    public function getExDates()
793
    {
794
        return $this->exDates;
795
    }
796
797
    /**
798
     * @param \DateTime[]
799
     *
800
     * @return \Eluceo\iCal\Component\Event
801
     */
802
    public function setExDates(array $exDates)
803
    {
804
        $this->exDates = $exDates;
805
806
        return $this;
807
    }
808
809
    /**
810
     * @return \Eluceo\iCal\Property\Event\RecurrenceId
811
     */
812
    public function getRecurrenceId()
813
    {
814
        return $this->recurrenceId;
815
    }
816
817
    /**
818
     * @param RecurrenceId $recurrenceId
819
     *
820
     * @return \Eluceo\iCal\Component\Event
821
     */
822
    public function setRecurrenceId(RecurrenceId $recurrenceId)
823
    {
824
        $this->recurrenceId = $recurrenceId;
825
826
        return $this;
827
    }
828
}
829