40 'VCALENDAR' =>
'Sabre\\VObject\\Component\\VCalendar',
41 'VALARM' =>
'Sabre\\VObject\\Component\\VAlarm',
42 'VEVENT' =>
'Sabre\\VObject\\Component\\VEvent',
43 'VFREEBUSY' =>
'Sabre\\VObject\\Component\\VFreeBusy',
44 'VAVAILABILITY' =>
'Sabre\\VObject\\Component\\VAvailability',
45 'AVAILABLE' =>
'Sabre\\VObject\\Component\\Available',
46 'VJOURNAL' =>
'Sabre\\VObject\\Component\\VJournal',
47 'VTIMEZONE' =>
'Sabre\\VObject\\Component\\VTimeZone',
48 'VTODO' =>
'Sabre\\VObject\\Component\\VTodo',
57 'BINARY' =>
'Sabre\\VObject\\Property\\Binary',
58 'BOOLEAN' =>
'Sabre\\VObject\\Property\\Boolean',
59 'CAL-ADDRESS' =>
'Sabre\\VObject\\Property\\ICalendar\\CalAddress',
60 'DATE' =>
'Sabre\\VObject\\Property\\ICalendar\\Date',
61 'DATE-TIME' =>
'Sabre\\VObject\\Property\\ICalendar\\DateTime',
62 'DURATION' =>
'Sabre\\VObject\\Property\\ICalendar\\Duration',
63 'FLOAT' =>
'Sabre\\VObject\\Property\\FloatValue',
64 'INTEGER' =>
'Sabre\\VObject\\Property\\IntegerValue',
65 'PERIOD' =>
'Sabre\\VObject\\Property\\ICalendar\\Period',
66 'RECUR' =>
'Sabre\\VObject\\Property\\ICalendar\\Recur',
67 'TEXT' =>
'Sabre\\VObject\\Property\\Text',
68 'TIME' =>
'Sabre\\VObject\\Property\\Time',
69 'UNKNOWN' =>
'Sabre\\VObject\\Property\\Unknown',
70 'URI' =>
'Sabre\\VObject\\Property\\Uri',
71 'UTC-OFFSET' =>
'Sabre\\VObject\\Property\\UtcOffset',
81 'CALSCALE' =>
'Sabre\\VObject\\Property\\FlatText',
82 'METHOD' =>
'Sabre\\VObject\\Property\\FlatText',
83 'PRODID' =>
'Sabre\\VObject\\Property\\FlatText',
84 'VERSION' =>
'Sabre\\VObject\\Property\\FlatText',
87 'ATTACH' =>
'Sabre\\VObject\\Property\\Uri',
88 'CATEGORIES' =>
'Sabre\\VObject\\Property\\Text',
89 'CLASS' =>
'Sabre\\VObject\\Property\\FlatText',
90 'COMMENT' =>
'Sabre\\VObject\\Property\\FlatText',
91 'DESCRIPTION' =>
'Sabre\\VObject\\Property\\FlatText',
92 'GEO' =>
'Sabre\\VObject\\Property\\FloatValue',
93 'LOCATION' =>
'Sabre\\VObject\\Property\\FlatText',
94 'PERCENT-COMPLETE' =>
'Sabre\\VObject\\Property\\IntegerValue',
95 'PRIORITY' =>
'Sabre\\VObject\\Property\\IntegerValue',
96 'RESOURCES' =>
'Sabre\\VObject\\Property\\Text',
97 'STATUS' =>
'Sabre\\VObject\\Property\\FlatText',
98 'SUMMARY' =>
'Sabre\\VObject\\Property\\FlatText',
101 'COMPLETED' =>
'Sabre\\VObject\\Property\\ICalendar\\DateTime',
102 'DTEND' =>
'Sabre\\VObject\\Property\\ICalendar\\DateTime',
103 'DUE' =>
'Sabre\\VObject\\Property\\ICalendar\\DateTime',
104 'DTSTART' =>
'Sabre\\VObject\\Property\\ICalendar\\DateTime',
105 'DURATION' =>
'Sabre\\VObject\\Property\\ICalendar\\Duration',
106 'FREEBUSY' =>
'Sabre\\VObject\\Property\\ICalendar\\Period',
107 'TRANSP' =>
'Sabre\\VObject\\Property\\FlatText',
110 'TZID' =>
'Sabre\\VObject\\Property\\FlatText',
111 'TZNAME' =>
'Sabre\\VObject\\Property\\FlatText',
112 'TZOFFSETFROM' =>
'Sabre\\VObject\\Property\\UtcOffset',
113 'TZOFFSETTO' =>
'Sabre\\VObject\\Property\\UtcOffset',
114 'TZURL' =>
'Sabre\\VObject\\Property\\Uri',
117 'ATTENDEE' =>
'Sabre\\VObject\\Property\\ICalendar\\CalAddress',
118 'CONTACT' =>
'Sabre\\VObject\\Property\\FlatText',
119 'ORGANIZER' =>
'Sabre\\VObject\\Property\\ICalendar\\CalAddress',
120 'RECURRENCE-ID' =>
'Sabre\\VObject\\Property\\ICalendar\\DateTime',
121 'RELATED-TO' =>
'Sabre\\VObject\\Property\\FlatText',
122 'URL' =>
'Sabre\\VObject\\Property\\Uri',
123 'UID' =>
'Sabre\\VObject\\Property\\FlatText',
126 'EXDATE' =>
'Sabre\\VObject\\Property\\ICalendar\\DateTime',
127 'RDATE' =>
'Sabre\\VObject\\Property\\ICalendar\\DateTime',
128 'RRULE' =>
'Sabre\\VObject\\Property\\ICalendar\\Recur',
129 'EXRULE' =>
'Sabre\\VObject\\Property\\ICalendar\\Recur',
132 'ACTION' =>
'Sabre\\VObject\\Property\\FlatText',
133 'REPEAT' =>
'Sabre\\VObject\\Property\\IntegerValue',
134 'TRIGGER' =>
'Sabre\\VObject\\Property\\ICalendar\\Duration',
137 'CREATED' =>
'Sabre\\VObject\\Property\\ICalendar\\DateTime',
138 'DTSTAMP' =>
'Sabre\\VObject\\Property\\ICalendar\\DateTime',
139 'LAST-MODIFIED' =>
'Sabre\\VObject\\Property\\ICalendar\\DateTime',
140 'SEQUENCE' =>
'Sabre\\VObject\\Property\\IntegerValue',
143 'REQUEST-STATUS' =>
'Sabre\\VObject\\Property\\Text',
146 'ALARM-AGENT' =>
'Sabre\\VObject\\Property\\Text',
147 'ACKNOWLEDGED' =>
'Sabre\\VObject\\Property\\ICalendar\\DateTime',
148 'PROXIMITY' =>
'Sabre\\VObject\\Property\\Text',
149 'DEFAULT-ALARM' =>
'Sabre\\VObject\\Property\\Boolean',
152 'BUSYTYPE' =>
'Sabre\\VObject\\Property\\Text',
163 return self::ICALENDAR20;
180 $isBaseComponent =
function($component) {
182 if (!$component instanceof VObject\
Component) {
185 if ($component->name ===
'VTIMEZONE') {
188 if (isset($component->{
'RECURRENCE-ID'})) {
195 if ($componentName) {
198 $this->
select($componentName),
204 foreach ($this->
children as $childGroup) {
206 foreach ($childGroup as $child) {
213 if ($isBaseComponent($child)) {
214 $components[] = $child;
236 $isBaseComponent =
function($component) {
238 if (!$component instanceof VObject\
Component) {
241 if ($component->name ===
'VTIMEZONE') {
244 if (isset($component->{
'RECURRENCE-ID'})) {
251 if ($componentName) {
252 foreach ($this->
select($componentName) as $child) {
253 if ($isBaseComponent($child)) {
261 foreach ($this->
children as $childGroup) {
262 foreach ($childGroup as $child) {
263 if ($isBaseComponent($child)) {
296 $recurringEvents = [];
304 foreach ($component->children() as $componentChild) {
305 if ($componentChild instanceof
Property\ICalendar\
DateTime && $componentChild->hasTime()) {
307 $dt = $componentChild->getDateTimes(
$timeZone);
312 $componentChild->setDateTimes($dt);
313 } elseif ($componentChild instanceof
Component) {
314 $stripTimezones($componentChild);
322 foreach ($this->
children() as $child) {
324 if ($child instanceof
Property && $child->name !==
'PRODID') {
327 $newChildren[] = clone $child;
328 } elseif ($child instanceof
Component && $child->name !==
'VTIMEZONE') {
332 if ($child->name ===
'VEVENT' && (isset($child->{
'RECURRENCE-ID'}) || isset($child->RRULE) || isset($child->RDATE))) {
334 $uid = (string)$child->UID;
338 if (isset($recurringEvents[$uid])) {
339 $recurringEvents[$uid][] = clone $child;
341 $recurringEvents[$uid] = [clone $child];
343 } elseif ($child->name ===
'VEVENT' && $child->isInTimeRange($start, $end)) {
344 $newChildren[] = $stripTimezones(clone $child);
351 foreach ($recurringEvents as
$events) {
364 while ($it->valid() && $it->getDTStart() <
$end) {
366 if ($it->getDTEnd() >
$start) {
368 $newChildren[] = $stripTimezones($it->getEventObject());
377 return new self($newChildren);
391 'CALSCALE' =>
'GREGORIAN',
451 if ($ver = $this->VERSION) {
452 if ((
string)$ver !==
'2.0') {
455 'message' =>
'Only iCalendar version 2.0 as defined in rfc5545 is supported.',
463 $componentsFound = 0;
464 $componentTypes = [];
466 foreach ($this->
children() as $child) {
470 if (!in_array($child->name, [
'VEVENT',
'VTODO',
'VJOURNAL'])) {
473 $componentTypes[] = $child->name;
475 $uid = (string)$child->UID;
476 $isMaster = isset($child->{
'RECURRENCE-ID'}) ? 0 : 1;
477 if (isset($uidList[$uid])) {
478 $uidList[$uid][
'count']++;
479 if ($isMaster && $uidList[$uid][
'hasMaster']) {
482 'message' =>
'More than one master object was found for the object with UID ' . $uid,
486 $uidList[$uid][
'hasMaster'] += $isMaster;
490 'hasMaster' => $isMaster,
497 if ($componentsFound === 0) {
500 'message' =>
'An iCalendar object must have at least 1 component.',
505 if (
$options & self::PROFILE_CALDAV) {
506 if (
count($uidList) > 1) {
509 'message' =>
'A calendar object on a CalDAV server may only have components with the same UID.',
513 if (
count($componentTypes) === 0) {
516 'message' =>
'A calendar object on a CalDAV server must have at least 1 component (VTODO, VEVENT, VJOURNAL).',
520 if (
count(array_unique($componentTypes)) > 1) {
523 'message' =>
'A calendar object on a CalDAV server may only have 1 type of component (VEVENT, VTODO or VJOURNAL).',
528 if (isset($this->METHOD)) {
531 'message' =>
'A calendar object on a CalDAV server MUST NOT have a METHOD property.',
548 return array_filter($this->
getComponents(),
function($item) use ($uid) {
550 if (!$itemUid = $item->select(
'UID')) {
553 $itemUid = current($itemUid)->getValue();
554 return $uid === $itemUid;
select($name)
Returns an array with elements that match the specified name.
getComponents()
This method only returns a list of sub-components.
foreach($paths as $path) if(!class_exists( 'Sabre\\VObject\\Version'))
const VERSION
Full version number.
static getDocumentType()
Returns the current document type.
getDefaults()
This method should return a list of default property values.
This class is used to determine new for a recurring event, when the next events occur.
This exception gets thrown when a recurrence iterator produces 0 instances.
getByUID($uid)
Returns all components with a specific UID value.
validate($options=0)
Validates the node for correctness.
expand(DateTimeInterface $start, DateTimeInterface $end, DateTimeZone $timeZone=null)
Expand all events in this VCalendar object and return a new VCalendar with the expanded events...
getBaseComponents($componentName=null)
Returns a list of all 'base components'.
getBaseComponent($componentName=null)
Returns the first component that is not a VTIMEZONE, and does not have an RECURRENCE-ID.
count()
Returns the number of elements.
children()
Returns a flat list of all the properties and components in this component.
This exception is thrown whenever an invalid value is found anywhere in a iCalendar or vCard object...