1<?php 2 3namespace Sabre\VObject\Component; 4 5use DateTimeImmutable; 6use DateTimeInterface; 7use Sabre\VObject; 8use Sabre\VObject\InvalidDataException; 9 10/** 11 * VAlarm component. 12 * 13 * This component contains some additional functionality specific for VALARMs. 14 * 15 * @copyright Copyright (C) fruux GmbH (https://fruux.com/) 16 * @author Evert Pot (http://evertpot.com/) 17 * @license http://sabre.io/license/ Modified BSD License 18 */ 19class VAlarm extends VObject\Component { 20 21 /** 22 * Returns a DateTime object when this alarm is going to trigger. 23 * 24 * This ignores repeated alarm, only the first trigger is returned. 25 * 26 * @return DateTimeImmutable 27 */ 28 function getEffectiveTriggerTime() { 29 30 $trigger = $this->TRIGGER; 31 if (!isset($trigger['VALUE']) || strtoupper($trigger['VALUE']) === 'DURATION') { 32 $triggerDuration = VObject\DateTimeParser::parseDuration($this->TRIGGER); 33 $related = (isset($trigger['RELATED']) && strtoupper($trigger['RELATED']) == 'END') ? 'END' : 'START'; 34 35 $parentComponent = $this->parent; 36 if ($related === 'START') { 37 38 if ($parentComponent->name === 'VTODO') { 39 $propName = 'DUE'; 40 } else { 41 $propName = 'DTSTART'; 42 } 43 44 $effectiveTrigger = $parentComponent->$propName->getDateTime(); 45 $effectiveTrigger = $effectiveTrigger->add($triggerDuration); 46 } else { 47 if ($parentComponent->name === 'VTODO') { 48 $endProp = 'DUE'; 49 } elseif ($parentComponent->name === 'VEVENT') { 50 $endProp = 'DTEND'; 51 } else { 52 throw new InvalidDataException('time-range filters on VALARM components are only supported when they are a child of VTODO or VEVENT'); 53 } 54 55 if (isset($parentComponent->$endProp)) { 56 $effectiveTrigger = $parentComponent->$endProp->getDateTime(); 57 $effectiveTrigger = $effectiveTrigger->add($triggerDuration); 58 } elseif (isset($parentComponent->DURATION)) { 59 $effectiveTrigger = $parentComponent->DTSTART->getDateTime(); 60 $duration = VObject\DateTimeParser::parseDuration($parentComponent->DURATION); 61 $effectiveTrigger = $effectiveTrigger->add($duration); 62 $effectiveTrigger = $effectiveTrigger->add($triggerDuration); 63 } else { 64 $effectiveTrigger = $parentComponent->DTSTART->getDateTime(); 65 $effectiveTrigger = $effectiveTrigger->add($triggerDuration); 66 } 67 } 68 } else { 69 $effectiveTrigger = $trigger->getDateTime(); 70 } 71 return $effectiveTrigger; 72 73 } 74 75 /** 76 * Returns true or false depending on if the event falls in the specified 77 * time-range. This is used for filtering purposes. 78 * 79 * The rules used to determine if an event falls within the specified 80 * time-range is based on the CalDAV specification. 81 * 82 * @param DateTime $start 83 * @param DateTime $end 84 * 85 * @return bool 86 */ 87 function isInTimeRange(DateTimeInterface $start, DateTimeInterface $end) { 88 89 $effectiveTrigger = $this->getEffectiveTriggerTime(); 90 91 if (isset($this->DURATION)) { 92 $duration = VObject\DateTimeParser::parseDuration($this->DURATION); 93 $repeat = (string)$this->REPEAT; 94 if (!$repeat) { 95 $repeat = 1; 96 } 97 98 $period = new \DatePeriod($effectiveTrigger, $duration, (int)$repeat); 99 100 foreach ($period as $occurrence) { 101 102 if ($start <= $occurrence && $end > $occurrence) { 103 return true; 104 } 105 } 106 return false; 107 } else { 108 return ($start <= $effectiveTrigger && $end > $effectiveTrigger); 109 } 110 111 } 112 113 /** 114 * A simple list of validation rules. 115 * 116 * This is simply a list of properties, and how many times they either 117 * must or must not appear. 118 * 119 * Possible values per property: 120 * * 0 - Must not appear. 121 * * 1 - Must appear exactly once. 122 * * + - Must appear at least once. 123 * * * - Can appear any number of times. 124 * * ? - May appear, but not more than once. 125 * 126 * @var array 127 */ 128 function getValidationRules() { 129 130 return [ 131 'ACTION' => 1, 132 'TRIGGER' => 1, 133 134 'DURATION' => '?', 135 'REPEAT' => '?', 136 137 'ATTACH' => '?', 138 ]; 139 140 } 141 142} 143