/** * Creates a new component. * * By default this object will iterate over its own children, but this can * be overridden with the iterator argument * * @param string $name * @param Sabre\VObject\ElementList $iterator */ public function __construct() { parent::__construct(); $tz = new \DateTimeZone(\GO::user() ? \GO::user()->timezone : date_default_timezone_get()); //$tz = new \DateTimeZone("Europe/Amsterdam"); $transitions = $tz->getTransitions(); $start_of_year = mktime(0, 0, 0, 1, 1); $to = \GO\Base\Util\Date::get_timezone_offset(time()); if ($to < 0) { if (strlen($to) == 2) { $to = '-0' . $to * -1; } } else { if (strlen($to) == 1) { $to = '0' . $to; } $to = '+' . $to; } $STANDARD_TZOFFSETFROM = $STANDARD_TZOFFSETTO = $DAYLIGHT_TZOFFSETFROM = $DAYLIGHT_TZOFFSETTO = $to; $STANDARD_RRULE = ''; $DAYLIGHT_RRULE = ''; for ($i = 0, $max = count($transitions); $i < $max; $i++) { if ($transitions[$i]['ts'] > $start_of_year) { $weekday1 = $this->_getDay($transitions[$i]['time']); $weekday2 = $this->_getDay($transitions[$i + 1]['time']); if ($transitions[$i]['isdst']) { $dst_start = $transitions[$i]; $dst_end = $transitions[$i + 1]; } else { $dst_end = $transitions[$i]; $dst_start = $transitions[$i + 1]; } $STANDARD_TZOFFSETFROM = $this->_formatVtimezoneTransitionHour($dst_start['offset'] / 3600); $STANDARD_TZOFFSETTO = $this->_formatVtimezoneTransitionHour($dst_end['offset'] / 3600); $DAYLIGHT_TZOFFSETFROM = $this->_formatVtimezoneTransitionHour($dst_end['offset'] / 3600); $DAYLIGHT_TZOFFSETTO = $this->_formatVtimezoneTransitionHour($dst_start['offset'] / 3600); $DAYLIGHT_RRULE = "FREQ=YEARLY;BYDAY={$weekday1};BYMONTH=" . date('n', $dst_start['ts']); $STANDARD_RRULE = "FREQ=YEARLY;BYDAY={$weekday2};BYMONTH=" . date('n', $dst_end['ts']); break; } } $this->tzid = $tz->getName(); // $this->add("last-modified", "19870101T000000Z"); $rrule = new \Sabre\VObject\Recur\RRuleIterator($STANDARD_RRULE, new \DateTime('1970-01-01 ' . substr($STANDARD_TZOFFSETFROM, 1) . ':00')); $rrule->next(); $rrule->next(); $this->add($this->createComponent("standard", array('dtstart' => $rrule->current()->format('Ymd\\THis'), 'rrule' => $STANDARD_RRULE, 'tzoffsetfrom' => $STANDARD_TZOFFSETFROM . "00", 'tzoffsetto' => $STANDARD_TZOFFSETTO . "00"))); $rrule = new \Sabre\VObject\Recur\RRuleIterator($DAYLIGHT_RRULE, new \DateTime('1970-01-01 ' . substr($DAYLIGHT_TZOFFSETFROM, 1) . ':00')); $rrule->next(); $rrule->next(); $this->add($this->createComponent("daylight", array('dtstart' => $rrule->current()->format('Ymd\\THis'), 'rrule' => $DAYLIGHT_RRULE, 'tzoffsetfrom' => $DAYLIGHT_TZOFFSETFROM . "00", 'tzoffsetto' => $DAYLIGHT_TZOFFSETTO . "00"))); }
/** * Returns the default class for a property name. * * @param string $propertyName * @return string */ public function getClassNameForPropertyName($propertyName) { $className = parent::getClassNameForPropertyName($propertyName); // In vCard 4, BINARY no longer exists, and we need URI instead. if ($className == 'Sabre\\VObject\\Property\\Binary' && $this->getDocumentType() === self::VCARD40) { return 'Sabre\\VObject\\Property\\Uri'; } return $className; }
/** * Validates the node for correctness. * * The following options are supported: * Node::REPAIR - May attempt to automatically repair the problem. * Node::PROFILE_CARDDAV - Validate the vCard for CardDAV purposes. * Node::PROFILE_CALDAV - Validate the iCalendar for CalDAV purposes. * * This method returns an array with detected problems. * Every element has the following properties: * * * level - problem level. * * message - A human-readable string describing the issue. * * node - A reference to the problematic node. * * The level means: * 1 - The issue was repaired (only happens if REPAIR was turned on). * 2 - A warning. * 3 - An error. * * @param int $options * @return array */ 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; }
/** * Validates the node for correctness. * An array is returned with warnings. * * Every item in the array has the following properties: * * level - (number between 1 and 3 with severity information) * * message - (human readable message) * * node - (reference to the offending node) * * @return array */ public 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; foreach ($this->children as $child) { if ($child instanceof Component) { $componentsFound++; if (!in_array($child->name, array('VEVENT', 'VTODO', 'VJOURNAL'))) { continue; } $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); } return $warnings; }
protected function assertIsNotValid(VObject\Document $document) { $this->assertNotEmpty($document->validate()); }
/** * Validates the node for correctness. * An array is returned with warnings. * * Every item in the array has the following properties: * * level - (number between 1 and 3 with severity information) * * message - (human readable message) * * node - (reference to the offending node) * * @return array */ public function validate($options = 0) { $warnings = array(); $version = $this->select('VERSION'); if (count($version) !== 1) { $warnings[] = array('level' => 1, 'message' => 'The VERSION property must appear in the VCALENDAR component exactly 1 time', 'node' => $this); } else { if ((string) $this->VERSION !== '2.0') { $warnings[] = array('level' => 1, 'message' => 'Only iCalendar version 2.0 as defined in rfc5545 is supported.', 'node' => $this); } } $version = $this->select('PRODID'); if (count($version) !== 1) { $warnings[] = array('level' => 2, 'message' => 'The PRODID property must appear in the VCALENDAR component exactly 1 time', 'node' => $this); } if (count($this->CALSCALE) > 1) { $warnings[] = array('level' => 2, 'message' => 'The CALSCALE property must not be specified more than once.', 'node' => $this); } if (count($this->METHOD) > 1) { $warnings[] = array('level' => 2, 'message' => 'The METHOD property must not be specified more than once.', 'node' => $this); } $componentsFound = 0; foreach ($this->children as $child) { if ($child instanceof Component) { $componentsFound++; } } if ($componentsFound === 0) { $warnings[] = array('level' => 1, 'message' => 'An iCalendar object must have at least 1 component.', 'node' => $this); } return array_merge($warnings, parent::validate()); }
/** * Validates the node for correctness. * * The following options are supported: * - Node::REPAIR - If something is broken, and automatic repair may * be attempted. * * An array is returned with warnings. * * Every item in the array has the following properties: * * level - (number between 1 and 3 with severity information) * * message - (human readable message) * * node - (reference to the offending node) * * @param int $options * @return array */ public function validate($options = 0) { $warnings = array(); $versionMap = array(self::VCARD21 => '2.1', self::VCARD30 => '3.0', self::VCARD40 => '4.0'); $version = $this->select('VERSION'); if (count($version) !== 1) { $warnings[] = array('level' => 1, 'message' => 'The VERSION property must appear in the VCARD component exactly 1 time', 'node' => $this); if ($options & self::REPAIR) { $this->VERSION = $versionMap[self::DEFAULT_VERSION]; } } else { $version = (string) $this->VERSION; if ($version !== '2.1' && $version !== '3.0' && $version !== '4.0') { $warnings[] = array('level' => 1, 'message' => 'Only vcard version 4.0 (RFC6350), version 3.0 (RFC2426) or version 2.1 (icm-vcard-2.1) are supported.', 'node' => $this); if ($options & self::REPAIR) { $this->VERSION = $versionMap[self::DEFAULT_VERSION]; } } } $fn = $this->select('FN'); if (count($fn) !== 1) { $warnings[] = array('level' => 1, 'message' => 'The FN property must appear in the VCARD component exactly 1 time', 'node' => $this); if ($options & self::REPAIR && count($fn) === 0) { // We're going to try to see if we can use the contents of the // N property. if (isset($this->N)) { $value = explode(';', (string) $this->N); if (isset($value[1]) && $value[1]) { $this->FN = $value[1] . ' ' . $value[0]; } else { $this->FN = $value[0]; } // Otherwise, the ORG property may work } elseif (isset($this->ORG)) { $this->FN = (string) $this->ORG; } } } return array_merge(parent::validate($options), $warnings); }