Completed
Push — 0.11.x ( bc0e2a...a7b95f )
by Markus
101:21 queued 78:44
created

Event::setUseUtc()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 3
Bugs 1 Features 0
Metric Value
dl 0
loc 6
ccs 0
cts 3
cp 0
rs 9.4285
c 3
b 1
f 0
nc 1
cc 1
eloc 3
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\Geo;
19
use Eluceo\iCal\Property\Event\Organizer;
20
use Eluceo\iCal\Property\Event\RecurrenceRule;
21
use Eluceo\iCal\Property\Event\Description;
22
use Eluceo\iCal\Property\RawStringValue;
23
use Eluceo\iCal\PropertyBag;
24
use Eluceo\iCal\Property\Event\RecurrenceId;
25
use Eluceo\iCal\Property\DateTimesProperty;
26
27
/**
28
 * Implementation of the EVENT component.
29
 */
30
class Event extends Component
31
{
32
    const TIME_TRANSPARENCY_OPAQUE      = 'OPAQUE';
33
    const TIME_TRANSPARENCY_TRANSPARENT = 'TRANSPARENT';
34
35
    const STATUS_TENTATIVE = 'TENTATIVE';
36
    const STATUS_CONFIRMED = 'CONFIRMED';
37
    const STATUS_CANCELLED = 'CANCELLED';
38
39
    /**
40
     * @var string
41
     */
42
    protected $uniqueId;
43
44
    /**
45
     * The property indicates the date/time that the instance of
46
     * the iCalendar object was created.
47
     *
48
     * The value MUST be specified in the UTC time format.
49
     *
50
     * @var \DateTime
51
     */
52
    protected $dtStamp;
53
54
    /**
55
     * @var \DateTime
56
     */
57
    protected $dtStart;
58
59
    /**
60
     * Preferentially chosen over the duration if both are set.
61
     *
62
     * @var \DateTime
63
     */
64
    protected $dtEnd;
65
66
    /**
67
     * @var \DateInterval
68
     */
69
    protected $duration;
70
71
    /**
72
     * @var bool
73
     */
74
    protected $noTime = false;
75
76
    /**
77
     * @var string
78
     */
79
    protected $url;
80
81
    /**
82
     * @var string
83
     */
84
    protected $location;
85
86
    /**
87
     * @var string
88
     */
89
    protected $locationTitle;
90
91
    /**
92
     * @var Geo
93
     */
94
    protected $locationGeo;
95
96
    /**
97
     * @var string
98
     */
99
    protected $summary;
100
101
    /**
102
     * @var Organizer
103
     */
104
    protected $organizer;
105
106
    /**
107
     * @see http://www.ietf.org/rfc/rfc2445.txt 4.8.2.7 Time Transparency
108
     *
109
     * @var string
110
     */
111
    protected $transparency = self::TIME_TRANSPARENCY_OPAQUE;
112
113
    /**
114
     * If set to true the timezone will be added to the event.
115
     *
116
     * @var bool
117
     */
118
    protected $useTimezone = false;
119
120
    /**
121
     * @var int
122
     */
123
    protected $sequence = 0;
124
125
    /**
126
     * @var Attendees
127
     */
128
    protected $attendees;
129
130
    /**
131
     * @var string
132
     */
133
    protected $description;
134
135
    /**
136
     * @var string
137
     */
138
    protected $descriptionHTML;
139
140
    /**
141
     * @var string
142
     */
143
    protected $status;
144
145
    /**
146
     * @var RecurrenceRule
147
     */
148
    protected $recurrenceRule;
149
150
    /**
151
     * @var array
152
     */
153
    protected $recurrenceRules = array();
154
155
    /**
156
     * This property specifies the date and time that the calendar
157
     * information was created.
158
     *
159
     * The value MUST be specified in the UTC time format.
160
     *
161
     * @var \DateTime
162
     */
163
    protected $created;
164
165
    /**
166
     * The property specifies the date and time that the information
167
     * associated with the calendar component was last revised.
168
     *
169
     * The value MUST be specified in the UTC time format.
170
     *
171
     * @var \DateTime
172
     */
173
    protected $modified;
174
175
    /**
176
     * Indicates if the UTC time should be used or not.
177
     *
178
     * @var bool
179
     */
180
    protected $useUtc = true;
181
182
    /**
183
     * @var bool
184
     */
185
    protected $cancelled;
186
187
    /**
188
     * This property is used to specify categories or subtypes
189
     * of the calendar component.  The categories are useful in searching
190
     * for a calendar component of a particular type and category.
191
     *
192
     * @see https://tools.ietf.org/html/rfc5545#section-3.8.1.2
193
     *
194
     * @var array
195
     */
196
    protected $categories;
197
198
    /**
199
     * https://tools.ietf.org/html/rfc5545#section-3.8.1.3.
200
     *
201
     * @var bool
202
     */
203
    protected $isPrivate = false;
204
205
    /**
206
     * Dates to be excluded from a series of events.
207
     *
208
     * @var \DateTime[]
209
     */
210
    protected $exDates = array();
211
212
    /**
213
     * @var RecurrenceId
214
     */
215
    protected $recurrenceId;
216
217 4
    public function __construct($uniqueId = null)
218
    {
219 4
        if (null == $uniqueId) {
220 2
            $uniqueId = uniqid();
221 2
        }
222
223 4
        $this->uniqueId = $uniqueId;
224 4
    }
225
226
    /**
227
     * {@inheritdoc}
228
     */
229 4
    public function getType()
230
    {
231 4
        return 'VEVENT';
232
    }
233
234
    /**
235
     * {@inheritdoc}
236
     */
237 4
    public function buildPropertyBag()
238
    {
239 4
        $propertyBag = new PropertyBag();
240
241
        // mandatory information
242 4
        $propertyBag->set('UID', $this->uniqueId);
243
244 4
        $propertyBag->add(new DateTimeProperty('DTSTART', $this->dtStart, $this->noTime, $this->useTimezone, $this->useUtc));
245 4
        $propertyBag->set('SEQUENCE', $this->sequence);
246 4
        $propertyBag->set('TRANSP', $this->transparency);
247
248 4
        if ($this->status) {
249
            $propertyBag->set('STATUS', $this->status);
250
        }
251
252
        // An event can have a 'dtend' or 'duration', but not both.
253 4
        if (null != $this->dtEnd) {
254 2
            if($this->noTime === true) {
255
                $this->dtEnd->add(new \DateInterval('P1D'));
256
            }
257 2
            $propertyBag->add(new DateTimeProperty('DTEND', $this->dtEnd, $this->noTime, $this->useTimezone, $this->useUtc));
258 4
        } elseif (null != $this->duration) {
259
            $propertyBag->set('DURATION', $this->duration->format('P%dDT%hH%iM%sS'));
260
        }
261
262
        // optional information
263 4
        if (null != $this->url) {
264
            $propertyBag->set('URL', $this->url);
265
        }
266
267 4
        if (null != $this->location) {
268
            $propertyBag->set('LOCATION', $this->location);
269
270
            if (null != $this->locationGeo) {
271
                $propertyBag->add(
272
                    new Property(
273
                        'X-APPLE-STRUCTURED-LOCATION',
274
                        new RawStringValue('geo:' . $this->locationGeo->getGeoLocationAsString(',')),
275
                        array(
276
                            'VALUE'          => 'URI',
277
                            'X-ADDRESS'      => $this->location,
278
                            'X-APPLE-RADIUS' => 49,
279
                            'X-TITLE'        => $this->locationTitle,
280
                        )
281
                    )
282
                );
283
            }
284
        }
285
286 4
        if (null != $this->locationGeo) {
287
            $propertyBag->add($this->locationGeo);
288
        }
289
290 4
        if (null != $this->summary) {
291
            $propertyBag->set('SUMMARY', $this->summary);
292
        }
293
294 4
        if (null != $this->attendees) {
295
            $propertyBag->add($this->attendees);
296
        }
297
298 4
        $propertyBag->set('CLASS', $this->isPrivate ? 'PRIVATE' : 'PUBLIC');
299
300 4
        if (null != $this->description) {
301 2
            $propertyBag->set('DESCRIPTION', new Description($this->description));
302 2
        }
303
304 4
        if (null != $this->descriptionHTML) {
305
            $propertyBag->add(
306
                new Property(
307
                    'X-ALT-DESC',
308
                    $this->descriptionHTML,
309
                    array(
310
                        'FMTTYPE' => 'text/html',
311
                    )
312
                )
313
            );
314
        }
315
316 4
        if (null != $this->recurrenceRule) {
317
            $propertyBag->set('RRULE', $this->recurrenceRule);
318
        }
319
320 4
        foreach ($this->recurrenceRules as $recurrenceRule) {
321
            $propertyBag->set('RRULE', $recurrenceRule);
322 4
        }
323
324 4
        if (null != $this->recurrenceId) {
325
            $this->recurrenceId->applyTimeSettings($this->noTime, $this->useTimezone, $this->useUtc);
326
            $propertyBag->add($this->recurrenceId);
327
        }
328
329 4
        if (!empty($this->exDates)) {
330
            $propertyBag->add(new DateTimesProperty('EXDATE', $this->exDates, $this->noTime, $this->useTimezone, $this->useUtc));
331
        }
332
333 4
        if ($this->cancelled) {
334
            $propertyBag->set('STATUS', 'CANCELLED');
335
        }
336
337 4
        if (null != $this->organizer) {
338 2
            $propertyBag->add($this->organizer);
339 2
        }
340
341 4
        if ($this->noTime) {
342
            $propertyBag->set('X-MICROSOFT-CDO-ALLDAYEVENT', 'TRUE');
343
        }
344
345 4
        if (null != $this->categories) {
346
            $propertyBag->set('CATEGORIES', $this->categories);
347
        }
348
349 4
        $propertyBag->add(
350 4
            new DateTimeProperty('DTSTAMP', $this->dtStamp ?: new \DateTime(), false, false, true)
351 4
        );
352
353 4
        if ($this->created) {
354
            $propertyBag->add(new DateTimeProperty('CREATED', $this->created, false, false, true));
355
        }
356
357 4
        if ($this->modified) {
358
            $propertyBag->add(new DateTimeProperty('LAST-MODIFIED', $this->modified, false, false, true));
359
        }
360
361 4
        return $propertyBag;
362
    }
363
364
    /**
365
     * @param $dtEnd
366
     *
367
     * @return $this
368
     */
369 2
    public function setDtEnd($dtEnd)
370
    {
371 2
        $this->dtEnd = $dtEnd;
372
373 2
        return $this;
374
    }
375
376
    public function getDtEnd()
377
    {
378
        return $this->dtEnd;
379
    }
380
381 2
    public function setDtStart($dtStart)
382
    {
383 2
        $this->dtStart = $dtStart;
384
385 2
        return $this;
386
    }
387
388
    public function getDtStart()
389
    {
390
        return $this->dtStart;
391
    }
392
393
    /**
394
     * @param $dtStamp
395
     *
396
     * @return $this
397
     */
398
    public function setDtStamp($dtStamp)
399
    {
400
        $this->dtStamp = $dtStamp;
401
402
        return $this;
403
    }
404
405
    /**
406
     * @param $duration
407
     *
408
     * @return $this
409
     */
410
    public function setDuration($duration)
411
    {
412
        $this->duration = $duration;
413
414
        return $this;
415
    }
416
417
    /**
418
     * @param string       $location
419
     * @param string $title
420
     * @param Geo|string $geo
421
     *
422
     * @return $this
423
     */
424
    public function setLocation($location, $title = '', $geo = null)
425
    {
426
        if (is_scalar($geo)) {
427
            $geo = Geo::fromString($geo);
0 ignored issues
show
Deprecated Code introduced by
The method Eluceo\iCal\Property\Event\Geo::fromString() has been deprecated with message: This method is used to allow backwards compatibility for Event::setLocation

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
428
        } else if (!$geo instanceof Geo) {
429
            $className = get_class($geo);
430
            throw new \InvalidArgumentException(
431
                "The parameter 'geo' must be a string or an instance of \\Eluceo\\iCal\\Property\\Event\\Geo"
432
                . " but an instance of {$className} was given."
433
            );
434
        }
435
436
        $this->location      = $location;
437
        $this->locationTitle = $title;
438
        $this->locationGeo   = $geo;
439
440
        return $this;
441
    }
442
443
    /**
444
     * @param Geo $geoProperty
445
     * @return $this
446
     */
447
    public function setGeoLocation(Geo $geoProperty)
448
    {
449
        $this->locationGeo = $geoProperty;
450
451
        return $this;
452
    }
453
454
    /**
455
     * @param $noTime
456
     *
457
     * @return $this
458
     */
459
    public function setNoTime($noTime)
460
    {
461
        $this->noTime = $noTime;
462
463
        return $this;
464
    }
465
466
    /**
467
     * @param int $sequence
468
     *
469
     * @return $this
470
     */
471
    public function setSequence($sequence)
472
    {
473
        $this->sequence = $sequence;
474
475
        return $this;
476
    }
477
478
    /**
479
     * @return int
480
     */
481
    public function getSequence()
482
    {
483
        return $this->sequence;
484
    }
485
486
    /**
487
     * @param Organizer $organizer
488
     *
489
     * @return $this
490
     */
491 2
    public function setOrganizer(Organizer $organizer)
492
    {
493 2
        $this->organizer = $organizer;
494
495 2
        return $this;
496
    }
497
498
    /**
499
     * @param $summary
500
     *
501
     * @return $this
502
     */
503
    public function setSummary($summary)
504
    {
505
        $this->summary = $summary;
506
507
        return $this;
508
    }
509
510
    /**
511
     * @param $uniqueId
512
     *
513
     * @return $this
514
     */
515
    public function setUniqueId($uniqueId)
516
    {
517
        $this->uniqueId = $uniqueId;
518
519
        return $this;
520
    }
521
522
    /**
523
     * @return string
524
     */
525
    public function getUniqueId()
526
    {
527
        return $this->uniqueId;
528
    }
529
530
    /**
531
     * @param $url
532
     *
533
     * @return $this
534
     */
535
    public function setUrl($url)
536
    {
537
        $this->url = $url;
538
539
        return $this;
540
    }
541
542
    /**
543
     * @param $useTimezone
544
     *
545
     * @return $this
546
     */
547
    public function setUseTimezone($useTimezone)
548
    {
549
        $this->useTimezone = $useTimezone;
550
551
        return $this;
552
    }
553
554
    /**
555
     * @return bool
556
     */
557
    public function getUseTimezone()
558
    {
559
        return $this->useTimezone;
560
    }
561
562
    /**
563
     * @param Attendees $attendees
564
     *
565
     * @return $this
566
     */
567
    public function setAttendees(Attendees $attendees)
568
    {
569
        $this->attendees = $attendees;
570
571
        return $this;
572
    }
573
574
    /**
575
     * @param string $attendee
576
     * @param array $params
577
     *
578
     * @return $this
579
     */
580
    public function addAttendee($attendee, $params = array())
581
    {
582
        if (!isset($this->attendees)) {
583
            $this->attendees = new Attendees();
584
        }
585
        $this->attendees->add($attendee, $params);
586
587
        return $this;
588
    }
589
590
    /**
591
     * @return Attendees
592
     */
593
    public function getAttendees()
594
    {
595
        return $this->attendees;
596
    }
597
598
    /**
599
     * @param $description
600
     *
601
     * @return $this
602
     */
603 2
    public function setDescription($description)
604
    {
605 2
        $this->description = $description;
606
607 2
        return $this;
608
    }
609
610
    /**
611
     * @param $descriptionHTML
612
     *
613
     * @return $this
614
     */
615
    public function setDescriptionHTML($descriptionHTML)
616
    {
617
        $this->descriptionHTML = $descriptionHTML;
618
619
        return $this;
620
    }
621
622
    /**
623
     * @param bool $useUtc
624
     *
625
     * @return $this
626
     */
627
    public function setUseUtc($useUtc = true)
628
    {
629
        $this->useUtc = $useUtc;
630
631
        return $this;
632
    }
633
634
    /**
635
     * @return string
636
     */
637
    public function getDescription()
638
    {
639
        return $this->description;
640
    }
641
642
    /**
643
     * @return string
644
     */
645
    public function getDescriptionHTML()
646
    {
647
        return $this->descriptionHTML;
648
    }
649
650
    /**
651
     * @param $status
652
     *
653
     * @return $this
654
     */
655
    public function setCancelled($status)
656
    {
657
        $this->cancelled = (bool)$status;
658
659
        return $this;
660
    }
661
662
    /**
663
     * @param $transparency
664
     *
665
     * @return $this
666
     *
667
     * @throws \InvalidArgumentException
668
     */
669 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...
670
    {
671
        $transparency = strtoupper($transparency);
672
        if ($transparency === self::TIME_TRANSPARENCY_OPAQUE
673
            || $transparency === self::TIME_TRANSPARENCY_TRANSPARENT
674
        ) {
675
            $this->transparency = $transparency;
676
        } else {
677
            throw new \InvalidArgumentException('Invalid value for transparancy');
678
        }
679
680
        return $this;
681
    }
682
683
    /**
684
     * @param $status
685
     *
686
     * @return $this
687
     *
688
     * @throws \InvalidArgumentException
689
     */
690
    public function setStatus($status)
691
    {
692
        $status = strtoupper($status);
693
        if ($status == self::STATUS_CANCELLED
694
            || $status == self::STATUS_CONFIRMED
695
            || $status == self::STATUS_TENTATIVE
696
        ) {
697
            $this->status = $status;
698
        } else {
699
            throw new \InvalidArgumentException('Invalid value for status');
700
        }
701
702
        return $this;
703
    }
704
705
    /**
706
     * @deprecated Deprecated since version 0.11.0, to be removed in 1.0. Use addRecurrenceRule instead.
707
     *
708
     * @param RecurrenceRule $recurrenceRule
709
     *
710
     * @return $this
711
     */
712
    public function setRecurrenceRule(RecurrenceRule $recurrenceRule)
713
    {
714
        @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...
715
716
        $this->recurrenceRule = $recurrenceRule;
717
718
        return $this;
719
    }
720
721
    /**
722
     * @deprecated Deprecated since version 0.11.0, to be removed in 1.0. Use getRecurrenceRules instead.
723
     *
724
     * @return RecurrenceRule
725
     */
726
    public function getRecurrenceRule()
727
    {
728
        @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...
729
730
        return $this->recurrenceRule;
731
    }
732
733
    /**
734
     * @param RecurrenceRule $recurrenceRule
735
     *
736
     * @return $this
737
     */
738
    public function addRecurrenceRule(RecurrenceRule $recurrenceRule)
739
    {
740
        $this->recurrenceRules[] = $recurrenceRule;
741
742
        return $this;
743
    }
744
745
    /**
746
     * @return array
747
     */
748
    public function getRecurrenceRules()
749
    {
750
        return $this->recurrenceRules;
751
    }
752
753
    /**
754
     * @param $dtStamp
755
     *
756
     * @return $this
757
     */
758
    public function setCreated($dtStamp)
759
    {
760
        $this->created = $dtStamp;
761
762
        return $this;
763
    }
764
765
    /**
766
     * @param $dtStamp
767
     *
768
     * @return $this
769
     */
770
    public function setModified($dtStamp)
771
    {
772
        $this->modified = $dtStamp;
773
774
        return $this;
775
    }
776
777
    /**
778
     * @param $categories
779
     *
780
     * @return $this
781
     */
782
    public function setCategories($categories)
783
    {
784
        $this->categories = $categories;
785
786
        return $this;
787
    }
788
789
    /**
790
     * Sets the event privacy.
791
     *
792
     * @param bool $flag
793
     *
794
     * @return $this
795
     */
796
    public function setIsPrivate($flag)
797
    {
798
        $this->isPrivate = (bool)$flag;
799
800
        return $this;
801
    }
802
803
    /**
804
     * @param \DateTime $dateTime
805
     *
806
     * @return \Eluceo\iCal\Component\Event
807
     */
808
    public function addExDate(\DateTime $dateTime)
809
    {
810
        $this->exDates[] = $dateTime;
811
812
        return $this;
813
    }
814
815
    /**
816
     * @return \DateTime[]
817
     */
818
    public function getExDates()
819
    {
820
        return $this->exDates;
821
    }
822
823
    /**
824
     * @param \DateTime[]
825
     *
826
     * @return \Eluceo\iCal\Component\Event
827
     */
828
    public function setExDates(array $exDates)
829
    {
830
        $this->exDates = $exDates;
831
832
        return $this;
833
    }
834
835
    /**
836
     * @return \Eluceo\iCal\Property\Event\RecurrenceId
837
     */
838
    public function getRecurrenceId()
839
    {
840
        return $this->recurrenceId;
841
    }
842
843
    /**
844
     * @param RecurrenceId $recurrenceId
845
     *
846
     * @return \Eluceo\iCal\Component\Event
847
     */
848
    public function setRecurrenceId(RecurrenceId $recurrenceId)
849
    {
850
        $this->recurrenceId = $recurrenceId;
851
852
        return $this;
853
    }
854
}
855