123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526 |
- <?php
- namespace Sabre\VObject\Component;
- use DateTime;
- use DateTimeZone;
- use Sabre\VObject;
- use Sabre\VObject\Component;
- use Sabre\VObject\Recur\EventIterator;
- use Sabre\VObject\Recur\NoInstancesException;
- class VCalendar extends VObject\Document {
-
- static $defaultName = 'VCALENDAR';
-
- static $componentMap = array(
- 'VALARM' => 'Sabre\\VObject\\Component\\VAlarm',
- 'VEVENT' => 'Sabre\\VObject\\Component\\VEvent',
- 'VFREEBUSY' => 'Sabre\\VObject\\Component\\VFreeBusy',
- 'VAVAILABILITY' => 'Sabre\\VObject\\Component\\VAvailability',
- 'AVAILABLE' => 'Sabre\\VObject\\Component\\Available',
- 'VJOURNAL' => 'Sabre\\VObject\\Component\\VJournal',
- 'VTIMEZONE' => 'Sabre\\VObject\\Component\\VTimeZone',
- 'VTODO' => 'Sabre\\VObject\\Component\\VTodo',
- );
-
- static $valueMap = array(
- 'BINARY' => 'Sabre\\VObject\\Property\\Binary',
- 'BOOLEAN' => 'Sabre\\VObject\\Property\\Boolean',
- 'CAL-ADDRESS' => 'Sabre\\VObject\\Property\\ICalendar\\CalAddress',
- 'DATE' => 'Sabre\\VObject\\Property\\ICalendar\\Date',
- 'DATE-TIME' => 'Sabre\\VObject\\Property\\ICalendar\\DateTime',
- 'DURATION' => 'Sabre\\VObject\\Property\\ICalendar\\Duration',
- 'FLOAT' => 'Sabre\\VObject\\Property\\FloatValue',
- 'INTEGER' => 'Sabre\\VObject\\Property\\IntegerValue',
- 'PERIOD' => 'Sabre\\VObject\\Property\\ICalendar\\Period',
- 'RECUR' => 'Sabre\\VObject\\Property\\ICalendar\\Recur',
- 'TEXT' => 'Sabre\\VObject\\Property\\Text',
- 'TIME' => 'Sabre\\VObject\\Property\\Time',
- 'UNKNOWN' => 'Sabre\\VObject\\Property\\Unknown',
- 'URI' => 'Sabre\\VObject\\Property\\Uri',
- 'UTC-OFFSET' => 'Sabre\\VObject\\Property\\UtcOffset',
- );
-
- static $propertyMap = array(
-
- 'CALSCALE' => 'Sabre\\VObject\\Property\\FlatText',
- 'METHOD' => 'Sabre\\VObject\\Property\\FlatText',
- 'PRODID' => 'Sabre\\VObject\\Property\\FlatText',
- 'VERSION' => 'Sabre\\VObject\\Property\\FlatText',
-
- 'ATTACH' => 'Sabre\\VObject\\Property\\Uri',
- 'CATEGORIES' => 'Sabre\\VObject\\Property\\Text',
- 'CLASS' => 'Sabre\\VObject\\Property\\FlatText',
- 'COMMENT' => 'Sabre\\VObject\\Property\\FlatText',
- 'DESCRIPTION' => 'Sabre\\VObject\\Property\\FlatText',
- 'GEO' => 'Sabre\\VObject\\Property\\FloatValue',
- 'LOCATION' => 'Sabre\\VObject\\Property\\FlatText',
- 'PERCENT-COMPLETE' => 'Sabre\\VObject\\Property\\IntegerValue',
- 'PRIORITY' => 'Sabre\\VObject\\Property\\IntegerValue',
- 'RESOURCES' => 'Sabre\\VObject\\Property\\Text',
- 'STATUS' => 'Sabre\\VObject\\Property\\FlatText',
- 'SUMMARY' => 'Sabre\\VObject\\Property\\FlatText',
-
- 'COMPLETED' => 'Sabre\\VObject\\Property\\ICalendar\\DateTime',
- 'DTEND' => 'Sabre\\VObject\\Property\\ICalendar\\DateTime',
- 'DUE' => 'Sabre\\VObject\\Property\\ICalendar\\DateTime',
- 'DTSTART' => 'Sabre\\VObject\\Property\\ICalendar\\DateTime',
- 'DURATION' => 'Sabre\\VObject\\Property\\ICalendar\\Duration',
- 'FREEBUSY' => 'Sabre\\VObject\\Property\\ICalendar\\Period',
- 'TRANSP' => 'Sabre\\VObject\\Property\\FlatText',
-
- 'TZID' => 'Sabre\\VObject\\Property\\FlatText',
- 'TZNAME' => 'Sabre\\VObject\\Property\\FlatText',
- 'TZOFFSETFROM' => 'Sabre\\VObject\\Property\\UtcOffset',
- 'TZOFFSETTO' => 'Sabre\\VObject\\Property\\UtcOffset',
- 'TZURL' => 'Sabre\\VObject\\Property\\Uri',
-
- 'ATTENDEE' => 'Sabre\\VObject\\Property\\ICalendar\\CalAddress',
- 'CONTACT' => 'Sabre\\VObject\\Property\\FlatText',
- 'ORGANIZER' => 'Sabre\\VObject\\Property\\ICalendar\\CalAddress',
- 'RECURRENCE-ID' => 'Sabre\\VObject\\Property\\ICalendar\\DateTime',
- 'RELATED-TO' => 'Sabre\\VObject\\Property\\FlatText',
- 'URL' => 'Sabre\\VObject\\Property\\Uri',
- 'UID' => 'Sabre\\VObject\\Property\\FlatText',
-
- 'EXDATE' => 'Sabre\\VObject\\Property\\ICalendar\\DateTime',
- 'RDATE' => 'Sabre\\VObject\\Property\\ICalendar\\DateTime',
- 'RRULE' => 'Sabre\\VObject\\Property\\ICalendar\\Recur',
- 'EXRULE' => 'Sabre\\VObject\\Property\\ICalendar\\Recur',
-
- 'ACTION' => 'Sabre\\VObject\\Property\\FlatText',
- 'REPEAT' => 'Sabre\\VObject\\Property\\IntegerValue',
- 'TRIGGER' => 'Sabre\\VObject\\Property\\ICalendar\\Duration',
-
- 'CREATED' => 'Sabre\\VObject\\Property\\ICalendar\\DateTime',
- 'DTSTAMP' => 'Sabre\\VObject\\Property\\ICalendar\\DateTime',
- 'LAST-MODIFIED' => 'Sabre\\VObject\\Property\\ICalendar\\DateTime',
- 'SEQUENCE' => 'Sabre\\VObject\\Property\\IntegerValue',
-
- 'REQUEST-STATUS' => 'Sabre\\VObject\\Property\\Text',
-
- 'ALARM-AGENT' => 'Sabre\\VObject\\Property\\Text',
- 'ACKNOWLEDGED' => 'Sabre\\VObject\\Property\\ICalendar\\DateTime',
- 'PROXIMITY' => 'Sabre\\VObject\\Property\\Text',
- 'DEFAULT-ALARM' => 'Sabre\\VObject\\Property\\Boolean',
-
- 'BUSYTYPE' => 'Sabre\\VObject\\Property\\Text',
- );
-
- function getDocumentType() {
- return self::ICALENDAR20;
- }
-
- function getBaseComponents($componentName = null) {
- $components = array();
- foreach($this->children as $component) {
- if (!$component instanceof VObject\Component)
- continue;
- if (isset($component->{'RECURRENCE-ID'}))
- continue;
- if ($componentName && $component->name !== strtoupper($componentName))
- continue;
- if ($component->name === 'VTIMEZONE')
- continue;
- $components[] = $component;
- }
- return $components;
- }
-
- function getBaseComponent($componentName = null) {
- foreach($this->children as $component) {
- if (!$component instanceof VObject\Component)
- continue;
- if (isset($component->{'RECURRENCE-ID'}))
- continue;
- if ($componentName && $component->name !== strtoupper($componentName))
- continue;
- if ($component->name === 'VTIMEZONE')
- continue;
- return $component;
- }
- }
-
- function expand(DateTime $start, DateTime $end, DateTimeZone $timeZone = null) {
- $newEvents = array();
- if (!$timeZone) {
- $timeZone = new DateTimeZone('UTC');
- }
-
-
- $recurringEvents = array();
- foreach($this->select('VEVENT') as $key=>$vevent) {
- $uid = (string)$vevent->UID;
- if (!$uid) {
- throw new \LogicException('Event did not have a UID!');
- }
- if (isset($vevent->{'RECURRENCE-ID'}) || isset($vevent->RRULE)) {
- if (isset($recurringEvents[$uid])) {
- $recurringEvents[$uid][] = $vevent;
- } else {
- $recurringEvents[$uid] = array($vevent);
- }
- continue;
- }
- if (!isset($vevent->RRULE)) {
- if ($vevent->isInTimeRange($start, $end)) {
- $newEvents[] = $vevent;
- }
- continue;
- }
- }
- foreach($recurringEvents as $events) {
- try {
- $it = new EventIterator($events, $timeZone);
- } catch (NoInstancesException $e) {
-
-
-
- continue;
- }
- $it->fastForward($start);
- while($it->valid() && $it->getDTStart() < $end) {
- if ($it->getDTEnd() > $start) {
- $newEvents[] = $it->getEventObject();
- }
- $it->next();
- }
- }
-
- unset($this->VEVENT);
-
- foreach($newEvents as $newEvent) {
- foreach($newEvent->children as $child) {
- if ($child instanceof VObject\Property\ICalendar\DateTime && $child->hasTime()) {
- $dt = $child->getDateTimes($timeZone);
-
-
-
- $dt[0]->setTimeZone(new DateTimeZone('UTC'));
- $child->setDateTimes($dt);
- }
- }
- $this->add($newEvent);
- }
-
- unset($this->VTIMEZONE);
- }
-
- protected function getDefaults() {
- return array(
- 'VERSION' => '2.0',
- 'PRODID' => '-//Sabre//Sabre VObject ' . VObject\Version::VERSION . '//EN',
- 'CALSCALE' => 'GREGORIAN',
- );
- }
-
- function getValidationRules() {
- return array(
- 'PRODID' => 1,
- 'VERSION' => 1,
- 'CALSCALE' => '?',
- 'METHOD' => '?',
- );
- }
-
- function validate($options = 0) {
- $warnings = parent::validate($options);
- if ($ver = $this->VERSION) {
- if ((string)$ver !== '2.0') {
- $warnings[] = array(
- 'level' => 3,
- 'message' => 'Only iCalendar version 2.0 as defined in rfc5545 is supported.',
- 'node' => $this,
- );
- }
- }
- $uidList = array();
- $componentsFound = 0;
- $componentTypes = array();
- foreach($this->children as $child) {
- if($child instanceof Component) {
- $componentsFound++;
- if (!in_array($child->name, array('VEVENT', 'VTODO', 'VJOURNAL'))) {
- continue;
- }
- $componentTypes[] = $child->name;
- $uid = (string)$child->UID;
- $isMaster = isset($child->{'RECURRENCE-ID'})?0:1;
- if (isset($uidList[$uid])) {
- $uidList[$uid]['count']++;
- if ($isMaster && $uidList[$uid]['hasMaster']) {
- $warnings[] = array(
- 'level' => 3,
- 'message' => 'More than one master object was found for the object with UID ' . $uid,
- 'node' => $this,
- );
- }
- $uidList[$uid]['hasMaster']+=$isMaster;
- } else {
- $uidList[$uid] = array(
- 'count' => 1,
- 'hasMaster' => $isMaster,
- );
- }
- }
- }
- if ($componentsFound===0) {
- $warnings[] = array(
- 'level' => 3,
- 'message' => 'An iCalendar object must have at least 1 component.',
- 'node' => $this,
- );
- }
- if ($options & self::PROFILE_CALDAV) {
- if (count($uidList)>1) {
- $warnings[] = array(
- 'level' => 3,
- 'message' => 'A calendar object on a CalDAV server may only have components with the same UID.',
- 'node' => $this,
- );
- }
- if (count(array_unique($componentTypes))===0) {
- $warnings[] = array(
- 'level' => 3,
- 'message' => 'A calendar object on a CalDAV server must have at least 1 component (VTODO, VEVENT, VJOURNAL).',
- 'node' => $this,
- );
- }
- if (count(array_unique($componentTypes))>1) {
- $warnings[] = array(
- 'level' => 3,
- 'message' => 'A calendar object on a CalDAV server may only have 1 type of component (VEVENT, VTODO or VJOURNAL).',
- 'node' => $this,
- );
- }
- if (isset($this->METHOD)) {
- $warnings[] = array(
- 'level' => 3,
- 'message' => 'A calendar object on a CalDAV server MUST NOT have a METHOD property.',
- 'node' => $this,
- );
- }
- }
- return $warnings;
- }
-
- function getByUID($uid) {
- return array_filter($this->children, function($item) use ($uid) {
- if (!$item instanceof Component) {
- return false;
- }
- if (!$itemUid = $item->select('UID')) {
- return false;
- }
- $itemUid = current($itemUid)->getValue();
- return $uid === $itemUid;
- });
- }
- }
|