Mercurial > hg > rc1
comparison plugins/libcalendaring/lib/Sabre/VObject/Component/VCalendar.php @ 4:888e774ee983
libcalendar plugin as distributed
| author | Charlie Root |
|---|---|
| date | Sat, 13 Jan 2018 08:57:56 -0500 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 3:f6fe4b6ae66a | 4:888e774ee983 |
|---|---|
| 1 <?php | |
| 2 | |
| 3 namespace Sabre\VObject\Component; | |
| 4 | |
| 5 use Sabre\VObject; | |
| 6 | |
| 7 /** | |
| 8 * The VCalendar component | |
| 9 * | |
| 10 * This component adds functionality to a component, specific for a VCALENDAR. | |
| 11 * | |
| 12 * @copyright Copyright (C) 2007-2013 fruux GmbH (https://fruux.com/). | |
| 13 * @author Evert Pot (http://evertpot.com/) | |
| 14 * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License | |
| 15 */ | |
| 16 class VCalendar extends VObject\Document { | |
| 17 | |
| 18 static $defaultName = 'VCALENDAR'; | |
| 19 | |
| 20 /** | |
| 21 * Returns a list of all 'base components'. For instance, if an Event has | |
| 22 * a recurrence rule, and one instance is overridden, the overridden event | |
| 23 * will have the same UID, but will be excluded from this list. | |
| 24 * | |
| 25 * VTIMEZONE components will always be excluded. | |
| 26 * | |
| 27 * @param string $componentName filter by component name | |
| 28 * @return array | |
| 29 */ | |
| 30 public function getBaseComponents($componentName = null) { | |
| 31 | |
| 32 $components = array(); | |
| 33 foreach($this->children as $component) { | |
| 34 | |
| 35 if (!$component instanceof VObject\Component) | |
| 36 continue; | |
| 37 | |
| 38 if (isset($component->{'RECURRENCE-ID'})) | |
| 39 continue; | |
| 40 | |
| 41 if ($componentName && $component->name !== strtoupper($componentName)) | |
| 42 continue; | |
| 43 | |
| 44 if ($component->name === 'VTIMEZONE') | |
| 45 continue; | |
| 46 | |
| 47 $components[] = $component; | |
| 48 | |
| 49 } | |
| 50 | |
| 51 return $components; | |
| 52 | |
| 53 } | |
| 54 | |
| 55 /** | |
| 56 * If this calendar object, has events with recurrence rules, this method | |
| 57 * can be used to expand the event into multiple sub-events. | |
| 58 * | |
| 59 * Each event will be stripped from it's recurrence information, and only | |
| 60 * the instances of the event in the specified timerange will be left | |
| 61 * alone. | |
| 62 * | |
| 63 * In addition, this method will cause timezone information to be stripped, | |
| 64 * and normalized to UTC. | |
| 65 * | |
| 66 * This method will alter the VCalendar. This cannot be reversed. | |
| 67 * | |
| 68 * This functionality is specifically used by the CalDAV standard. It is | |
| 69 * possible for clients to request expand events, if they are rather simple | |
| 70 * clients and do not have the possibility to calculate recurrences. | |
| 71 * | |
| 72 * @param DateTime $start | |
| 73 * @param DateTime $end | |
| 74 * @return void | |
| 75 */ | |
| 76 public function expand(\DateTime $start, \DateTime $end) { | |
| 77 | |
| 78 $newEvents = array(); | |
| 79 | |
| 80 foreach($this->select('VEVENT') as $key=>$vevent) { | |
| 81 | |
| 82 if (isset($vevent->{'RECURRENCE-ID'})) { | |
| 83 unset($this->children[$key]); | |
| 84 continue; | |
| 85 } | |
| 86 | |
| 87 | |
| 88 if (!$vevent->rrule) { | |
| 89 unset($this->children[$key]); | |
| 90 if ($vevent->isInTimeRange($start, $end)) { | |
| 91 $newEvents[] = $vevent; | |
| 92 } | |
| 93 continue; | |
| 94 } | |
| 95 | |
| 96 $uid = (string)$vevent->uid; | |
| 97 if (!$uid) { | |
| 98 throw new \LogicException('Event did not have a UID!'); | |
| 99 } | |
| 100 | |
| 101 $it = new VObject\RecurrenceIterator($this, $vevent->uid); | |
| 102 $it->fastForward($start); | |
| 103 | |
| 104 while($it->valid() && $it->getDTStart() < $end) { | |
| 105 | |
| 106 if ($it->getDTEnd() > $start) { | |
| 107 | |
| 108 $newEvents[] = $it->getEventObject(); | |
| 109 | |
| 110 } | |
| 111 $it->next(); | |
| 112 | |
| 113 } | |
| 114 unset($this->children[$key]); | |
| 115 | |
| 116 } | |
| 117 | |
| 118 foreach($newEvents as $newEvent) { | |
| 119 | |
| 120 foreach($newEvent->children as $child) { | |
| 121 if ($child instanceof VObject\Property\DateTime && | |
| 122 $child->getDateType() == VObject\Property\DateTime::LOCALTZ) { | |
| 123 $child->setDateTime($child->getDateTime(),VObject\Property\DateTime::UTC); | |
| 124 } | |
| 125 } | |
| 126 | |
| 127 $this->add($newEvent); | |
| 128 | |
| 129 } | |
| 130 | |
| 131 // Removing all VTIMEZONE components | |
| 132 unset($this->VTIMEZONE); | |
| 133 | |
| 134 } | |
| 135 | |
| 136 /** | |
| 137 * Validates the node for correctness. | |
| 138 * An array is returned with warnings. | |
| 139 * | |
| 140 * Every item in the array has the following properties: | |
| 141 * * level - (number between 1 and 3 with severity information) | |
| 142 * * message - (human readable message) | |
| 143 * * node - (reference to the offending node) | |
| 144 * | |
| 145 * @return array | |
| 146 */ | |
| 147 /* | |
| 148 public function validate() { | |
| 149 | |
| 150 $warnings = array(); | |
| 151 | |
| 152 $version = $this->select('VERSION'); | |
| 153 if (count($version)!==1) { | |
| 154 $warnings[] = array( | |
| 155 'level' => 1, | |
| 156 'message' => 'The VERSION property must appear in the VCALENDAR component exactly 1 time', | |
| 157 'node' => $this, | |
| 158 ); | |
| 159 } else { | |
| 160 if ((string)$this->VERSION !== '2.0') { | |
| 161 $warnings[] = array( | |
| 162 'level' => 1, | |
| 163 'message' => 'Only iCalendar version 2.0 as defined in rfc5545 is supported.', | |
| 164 'node' => $this, | |
| 165 ); | |
| 166 } | |
| 167 } | |
| 168 $version = $this->select('PRODID'); | |
| 169 if (count($version)!==1) { | |
| 170 $warnings[] = array( | |
| 171 'level' => 2, | |
| 172 'message' => 'The PRODID property must appear in the VCALENDAR component exactly 1 time', | |
| 173 'node' => $this, | |
| 174 ); | |
| 175 } | |
| 176 if (count($this->CALSCALE) > 1) { | |
| 177 $warnings[] = array( | |
| 178 'level' => 2, | |
| 179 'message' => 'The CALSCALE property must not be specified more than once.', | |
| 180 'node' => $this, | |
| 181 ); | |
| 182 } | |
| 183 if (count($this->METHOD) > 1) { | |
| 184 $warnings[] = array( | |
| 185 'level' => 2, | |
| 186 'message' => 'The METHOD property must not be specified more than once.', | |
| 187 'node' => $this, | |
| 188 ); | |
| 189 } | |
| 190 | |
| 191 $allowedComponents = array( | |
| 192 'VEVENT', | |
| 193 'VTODO', | |
| 194 'VJOURNAL', | |
| 195 'VFREEBUSY', | |
| 196 'VTIMEZONE', | |
| 197 ); | |
| 198 $allowedProperties = array( | |
| 199 'PRODID', | |
| 200 'VERSION', | |
| 201 'CALSCALE', | |
| 202 'METHOD', | |
| 203 ); | |
| 204 $componentsFound = 0; | |
| 205 foreach($this->children as $child) { | |
| 206 if($child instanceof Component) { | |
| 207 $componentsFound++; | |
| 208 if (!in_array($child->name, $allowedComponents)) { | |
| 209 $warnings[] = array( | |
| 210 'level' => 1, | |
| 211 'message' => 'The ' . $child->name . " component is not allowed in the VCALENDAR component", | |
| 212 'node' => $this, | |
| 213 ); | |
| 214 } | |
| 215 } | |
| 216 if ($child instanceof Property) { | |
| 217 if (!in_array($child->name, $allowedProperties)) { | |
| 218 $warnings[] = array( | |
| 219 'level' => 2, | |
| 220 'message' => 'The ' . $child->name . " property is not allowed in the VCALENDAR component", | |
| 221 'node' => $this, | |
| 222 ); | |
| 223 } | |
| 224 } | |
| 225 } | |
| 226 | |
| 227 if ($componentsFound===0) { | |
| 228 $warnings[] = array( | |
| 229 'level' => 1, | |
| 230 'message' => 'An iCalendar object must have at least 1 component.', | |
| 231 'node' => $this, | |
| 232 ); | |
| 233 } | |
| 234 | |
| 235 return array_merge( | |
| 236 $warnings, | |
| 237 parent::validate() | |
| 238 ); | |
| 239 | |
| 240 } | |
| 241 */ | |
| 242 | |
| 243 } | |
| 244 |
