Second part of refactoring; should be runnable again, yet not thoroughly tested

This commit is contained in:
Tobias Hößl 2012-08-11 08:07:19 +00:00
parent b8234a1cb8
commit 6186153f68
88 changed files with 2135 additions and 1186 deletions

View file

@ -1,5 +1,7 @@
<?php
use Sabre\VObject;
/**
* Abstract Calendaring backend. Extend this class to create your own backends.
*
@ -140,7 +142,7 @@ abstract class Sabre_CalDAV_Backend_Abstract implements Sabre_CalDAV_Backend_Bac
$object = $this->getCalendarObject($object['calendarid'], $object['uri']);
}
$vObject = Sabre_VObject_Reader::read($object['calendardata']);
$vObject = VObject\Reader::read($object['calendardata']);
$validator = new Sabre_CalDAV_CalendarQueryValidator();
return $validator->validate($vObject, $filters);

View file

@ -1,5 +1,7 @@
<?php
use Sabre\VObject;
/**
* PDO CalDAV backend
*
@ -462,7 +464,7 @@ class Sabre_CalDAV_Backend_PDO extends Sabre_CalDAV_Backend_Abstract {
*/
protected function getDenormalizedData($calendarData) {
$vObject = Sabre_VObject_Reader::read($calendarData);
$vObject = VObject\Reader::read($calendarData);
$componentType = null;
$component = null;
$firstOccurence = null;
@ -484,9 +486,9 @@ class Sabre_CalDAV_Backend_PDO extends Sabre_CalDAV_Backend_Abstract {
$lastOccurence = $component->DTEND->getDateTime()->getTimeStamp();
} elseif (isset($component->DURATION)) {
$endDate = clone $component->DTSTART->getDateTime();
$endDate->add(Sabre_VObject_DateTimeParser::parse($component->DURATION->value));
$endDate->add(VObject\DateTimeParser::parse($component->DURATION->value));
$lastOccurence = $endDate->getTimeStamp();
} elseif ($component->DTSTART->getDateType()===Sabre_VObject_Property_DateTime::DATE) {
} elseif ($component->DTSTART->getDateType()===VObject\Property\DateTime::DATE) {
$endDate = clone $component->DTSTART->getDateTime();
$endDate->modify('+1 day');
$lastOccurence = $endDate->getTimeStamp();
@ -494,7 +496,7 @@ class Sabre_CalDAV_Backend_PDO extends Sabre_CalDAV_Backend_Abstract {
$lastOccurence = $firstOccurence;
}
} else {
$it = new Sabre_VObject_RecurrenceIterator($vObject, (string)$component->UID);
$it = new VObject\RecurrenceIterator($vObject, (string)$component->UID);
$maxDate = new DateTime(self::MAX_DATE);
if ($it->isInfinite()) {
$lastOccurence = $maxDate->getTimeStamp();

View file

@ -1,5 +1,7 @@
<?php
use Sabre\VObject;
/**
* Parses the calendar-query report request body.
*
@ -241,12 +243,12 @@ class Sabre_CalDAV_CalendarQueryParser {
$timeRangeNode = $timeRangeNodes->item(0);
if ($start = $timeRangeNode->getAttribute('start')) {
$start = Sabre_VObject_DateTimeParser::parseDateTime($start);
$start = VObject\DateTimeParser::parseDateTime($start);
} else {
$start = null;
}
if ($end = $timeRangeNode->getAttribute('end')) {
$end = Sabre_VObject_DateTimeParser::parseDateTime($end);
$end = VObject\DateTimeParser::parseDateTime($end);
} else {
$end = null;
}
@ -274,13 +276,13 @@ class Sabre_CalDAV_CalendarQueryParser {
if(!$start) {
throw new Sabre_DAV_Exception_BadRequest('The "start" attribute is required for the CALDAV:expand element');
}
$start = Sabre_VObject_DateTimeParser::parseDateTime($start);
$start = VObject\DateTimeParser::parseDateTime($start);
$end = $parentNode->getAttribute('end');
if(!$end) {
throw new Sabre_DAV_Exception_BadRequest('The "end" attribute is required for the CALDAV:expand element');
}
$end = Sabre_VObject_DateTimeParser::parseDateTime($end);
$end = VObject\DateTimeParser::parseDateTime($end);
if ($end <= $start) {
throw new Sabre_DAV_Exception_BadRequest('The end-date must be larger than the start-date in the expand element.');

View file

@ -1,5 +1,7 @@
<?php
use Sabre\VObject;
/**
* CalendarQuery Validator
*
@ -22,11 +24,11 @@ class Sabre_CalDAV_CalendarQueryValidator {
*
* The list of filters must be formatted as parsed by Sabre_CalDAV_CalendarQueryParser
*
* @param Sabre_VObject_Component $vObject
* @param VObject\Component $vObject
* @param array $filters
* @return bool
*/
public function validate(Sabre_VObject_Component $vObject,array $filters) {
public function validate(VObject\Component $vObject,array $filters) {
// The top level object is always a component filter.
// We'll parse it manually, as it's pretty simple.
@ -48,11 +50,11 @@ class Sabre_CalDAV_CalendarQueryValidator {
* component we're checking should be specified, not the component to check
* itself.
*
* @param Sabre_VObject_Component $parent
* @param VObject\Component $parent
* @param array $filters
* @return bool
*/
protected function validateCompFilters(Sabre_VObject_Component $parent, array $filters) {
protected function validateCompFilters(VObject\Component $parent, array $filters) {
foreach($filters as $filter) {
@ -117,11 +119,11 @@ class Sabre_CalDAV_CalendarQueryValidator {
* property we're checking should be specified, not the property to check
* itself.
*
* @param Sabre_VObject_Component $parent
* @param VObject\Component $parent
* @param array $filters
* @return bool
*/
protected function validatePropFilters(Sabre_VObject_Component $parent, array $filters) {
protected function validatePropFilters(VObject\Component $parent, array $filters) {
foreach($filters as $filter) {
@ -187,11 +189,11 @@ class Sabre_CalDAV_CalendarQueryValidator {
* parameter we're checking should be specified, not the parameter to check
* itself.
*
* @param Sabre_VObject_Property $parent
* @param VObject\Property $parent
* @param array $filters
* @return bool
*/
protected function validateParamFilters(Sabre_VObject_Property $parent, array $filters) {
protected function validateParamFilters(VObject\Property $parent, array $filters) {
foreach($filters as $filter) {
@ -243,11 +245,11 @@ class Sabre_CalDAV_CalendarQueryValidator {
* A single text-match should be specified as well as the specific property
* or parameter we need to validate.
*
* @param Sabre_VObject_Node $parent
* @param VObject\Node $parent
* @param array $textMatch
* @return bool
*/
protected function validateTextMatch(Sabre_VObject_Node $parent, array $textMatch) {
protected function validateTextMatch(VObject\Node $parent, array $textMatch) {
$value = (string)$parent;
@ -263,12 +265,12 @@ class Sabre_CalDAV_CalendarQueryValidator {
* This is all based on the rules specified in rfc4791, which are quite
* complex.
*
* @param Sabre_VObject_Node $component
* @param VObject\Node $component
* @param DateTime $start
* @param DateTime $end
* @return bool
*/
protected function validateTimeRange(Sabre_VObject_Node $component, $start, $end) {
protected function validateTimeRange(VObject\Node $component, $start, $end) {
if (is_null($start)) {
$start = new DateTime('1900-01-01');
@ -296,7 +298,7 @@ class Sabre_CalDAV_CalendarQueryValidator {
if ($component->parent->name === 'VEVENT' && $component->parent->RRULE) {
// Fire up the iterator!
$it = new Sabre_VObject_RecurrenceIterator($component->parent->parent, (string)$component->parent->UID);
$it = new VObject\RecurrenceIterator($component->parent->parent, (string)$component->parent->UID);
while($it->valid()) {
$expandedEvent = $it->getEventObject();

View file

@ -1,5 +1,7 @@
<?php
use Sabre\VObject;
/**
* ICS Exporter
*
@ -82,7 +84,7 @@ class Sabre_CalDAV_ICSExportPlugin extends Sabre_DAV_ServerPlugin {
*/
public function generateICS(array $nodes) {
$calendar = new Sabre_VObject_Component('vcalendar');
$calendar = new VObject\Component('vcalendar');
$calendar->version = '2.0';
if (Sabre_DAV_Server::$exposeVersion) {
$calendar->prodid = '-//SabreDAV//SabreDAV ' . Sabre_DAV_Version::VERSION . '//EN';
@ -103,7 +105,7 @@ class Sabre_CalDAV_ICSExportPlugin extends Sabre_DAV_ServerPlugin {
}
$nodeData = $node[200]['{' . Sabre_CalDAV_Plugin::NS_CALDAV . '}calendar-data'];
$nodeComp = Sabre_VObject_Reader::read($nodeData);
$nodeComp = VObject\Reader::read($nodeData);
foreach($nodeComp->children() as $child) {

View file

@ -1,5 +1,7 @@
<?php
use Sabre\VObject;
/**
* CalDAV plugin
*
@ -456,8 +458,8 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin {
if(!$start || !$end) {
throw new Sabre_DAV_Exception_BadRequest('The "start" and "end" attributes are required for the CALDAV:expand element');
}
$start = Sabre_VObject_DateTimeParser::parseDateTime($start);
$end = Sabre_VObject_DateTimeParser::parseDateTime($end);
$start = VObject\DateTimeParser::parseDateTime($start);
$end = VObject\DateTimeParser::parseDateTime($end);
if ($end <= $start) {
throw new Sabre_DAV_Exception_BadRequest('The end-date must be larger than the start-date in the expand element.');
@ -476,7 +478,7 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin {
list($objProps) = $this->server->getPropertiesForPath($uri,$properties);
if ($expand && isset($objProps[200]['{' . self::NS_CALDAV . '}calendar-data'])) {
$vObject = Sabre_VObject_Reader::read($objProps[200]['{' . self::NS_CALDAV . '}calendar-data']);
$vObject = VObject\Reader::read($objProps[200]['{' . self::NS_CALDAV . '}calendar-data']);
$vObject->expand($start, $end);
$objProps[200]['{' . self::NS_CALDAV . '}calendar-data'] = $vObject->serialize();
}
@ -543,7 +545,7 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin {
if (isset($properties[200]['{urn:ietf:params:xml:ns:caldav}calendar-data'])) {
$validator = new Sabre_CalDAV_CalendarQueryValidator();
$vObject = Sabre_VObject_Reader::read($properties[200]['{urn:ietf:params:xml:ns:caldav}calendar-data']);
$vObject = VObject\Reader::read($properties[200]['{urn:ietf:params:xml:ns:caldav}calendar-data']);
if ($validator->validate($vObject,$parser->filters)) {
// If the client didn't require the calendar-data property,
@ -577,7 +579,7 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin {
if ($parser->expand) {
// We need to do some post-processing
$vObject = Sabre_VObject_Reader::read($properties[200]['{urn:ietf:params:xml:ns:caldav}calendar-data']);
$vObject = VObject\Reader::read($properties[200]['{urn:ietf:params:xml:ns:caldav}calendar-data']);
$vObject->expand($parser->expand['start'], $parser->expand['end']);
$properties[200]['{' . self::NS_CALDAV . '}calendar-data'] = $vObject->serialize();
}
@ -617,10 +619,10 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin {
}
if ($start) {
$start = Sabre_VObject_DateTimeParser::parseDateTime($start);
$start = VObject\DateTimeParser::parseDateTime($start);
}
if ($end) {
$end = Sabre_VObject_DateTimeParser::parseDateTime($end);
$end = VObject\DateTimeParser::parseDateTime($end);
}
if (!$start && !$end) {
@ -647,7 +649,7 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin {
return $obj;
}, $calendar->getChildren());
$generator = new Sabre_VObject_FreeBusyGenerator();
$generator = new VObject\FreeBusyGenerator();
$generator->setObjects($objects);
$generator->setTimeRange($start, $end);
$result = $generator->getResult();
@ -763,9 +765,9 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin {
try {
$vobj = Sabre_VObject_Reader::read($data);
$vobj = VObject\Reader::read($data);
} catch (Sabre_VObject_ParseException $e) {
} catch (VObject\ParseException $e) {
throw new Sabre_DAV_Exception_UnsupportedMediaType('This resource only supports valid iCalendar 2.0 data. Parse error: ' . $e->getMessage());
@ -868,8 +870,8 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin {
}
try {
$vObject = Sabre_VObject_Reader::read($this->server->httpRequest->getBody(true));
} catch (Sabre_VObject_ParseException $e) {
$vObject = VObject\Reader::read($this->server->httpRequest->getBody(true));
} catch (VObject\ParseException $e) {
throw new Sabre_DAV_Exception_BadRequest('The request body must be a valid iCalendar object. Parse error: ' . $e->getMessage());
}
@ -920,10 +922,10 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin {
*
* @param string $originator
* @param array $recipients
* @param Sabre_VObject_Component $vObject
* @param Sabre\VObject\Component $vObject
* @return array
*/
protected function iMIPMessage($originator, array $recipients, Sabre_VObject_Component $vObject, $principal) {
protected function iMIPMessage($originator, array $recipients, VObject\Component $vObject, $principal) {
if (!$this->imipHandler) {
$resultStatus = '5.2;This server does not support this operation';

View file

@ -1,5 +1,7 @@
<?php
use Sabre\VObject;
/**
* iMIP handler.
*
@ -44,11 +46,11 @@ class Sabre_CalDAV_Schedule_IMip {
*
* @param string $originator Originator Email
* @param array $recipients Array of email addresses
* @param Sabre_VObject_Component $vObject
* @param Sabre\VObject\Component $vObject
* @param string $principal Principal Url of the originator
* @return void
*/
public function sendMessage($originator, array $recipients, Sabre_VObject_Component $vObject, $principal) {
public function sendMessage($originator, array $recipients, VObject\Component $vObject, $principal) {
foreach($recipients as $recipient) {

View file

@ -1,5 +1,7 @@
<?php
use Sabre\VObject;
/**
* CardDAV plugin
*
@ -345,9 +347,9 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin {
try {
$vobj = Sabre_VObject_Reader::read($data);
$vobj = VObject\Reader::read($data);
} catch (Sabre_VObject_ParseException $e) {
} catch (VObject\ParseException $e) {
throw new Sabre_DAV_Exception_UnsupportedMediaType('This resource only supports valid vcard data. Parse error: ' . $e->getMessage());
@ -441,7 +443,7 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin {
*/
public function validateFilters($vcardData, array $filters, $test) {
$vcard = Sabre_VObject_Reader::read($vcardData);
$vcard = VObject\Reader::read($vcardData);
if (!$filters) return true;

View file

@ -1,400 +0,0 @@
<?php
/**
* VObject Component
*
* This class represents a VCALENDAR/VCARD component. A component is for example
* VEVENT, VTODO and also VCALENDAR. It starts with BEGIN:COMPONENTNAME and
* ends with END:COMPONENTNAME
*
* @package Sabre
* @subpackage VObject
* @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
* @author Evert Pot (http://www.rooftopsolutions.nl/)
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
*/
class Sabre_VObject_Component extends Sabre_VObject_Element {
/**
* Name, for example VEVENT
*
* @var string
*/
public $name;
/**
* Children properties and components
*
* @var array
*/
public $children = array();
/**
* If components are added to this map, they will be automatically mapped
* to their respective classes, if parsed by the reader or constructed with
* the 'create' method.
*
* @var array
*/
static public $classMap = array(
'VCALENDAR' => 'Sabre_VObject_Component_VCalendar',
'VEVENT' => 'Sabre_VObject_Component_VEvent',
'VTODO' => 'Sabre_VObject_Component_VTodo',
'VJOURNAL' => 'Sabre_VObject_Component_VJournal',
'VALARM' => 'Sabre_VObject_Component_VAlarm',
);
/**
* Creates the new component by name, but in addition will also see if
* there's a class mapped to the property name.
*
* @param string $name
* @param string $value
* @return Sabre_VObject_Component
*/
static public function create($name, $value = null) {
$name = strtoupper($name);
if (isset(self::$classMap[$name])) {
return new self::$classMap[$name]($name, $value);
} else {
return new self($name, $value);
}
}
/**
* 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($name, Sabre_VObject_ElementList $iterator = null) {
$this->name = strtoupper($name);
if (!is_null($iterator)) $this->iterator = $iterator;
}
/**
* Turns the object back into a serialized blob.
*
* @return string
*/
public function serialize() {
$str = "BEGIN:" . $this->name . "\r\n";
/**
* Gives a component a 'score' for sorting purposes.
*
* This is solely used by the childrenSort method.
*
* A higher score means the item will be lower in the list.
* To avoid score collisions, each "score category" has a reasonable
* space to accomodate elements. The $key is added to the $score to
* preserve the original relative order of elements.
*
* @param int $key
* @param Sabre_VObject $array
* @return int
*/
$sortScore = function($key, $array) {
if ($array[$key] instanceof Sabre_VObject_Component) {
// We want to encode VTIMEZONE first, this is a personal
// preference.
if ($array[$key]->name === 'VTIMEZONE') {
$score=300000000;
return $score+$key;
} else {
$score=400000000;
return $score+$key;
}
} else {
// Properties get encoded first
// VCARD version 4.0 wants the VERSION property to appear first
if ($array[$key] instanceof Sabre_VObject_Property) {
if ($array[$key]->name === 'VERSION') {
$score=100000000;
return $score+$key;
} else {
// All other properties
$score=200000000;
return $score+$key;
}
}
}
next($children);
};
$tmp = $this->children;
uksort($this->children, function($a, $b) use ($sortScore, $tmp) {
$sA = $sortScore($a, $tmp);
$sB = $sortScore($b, $tmp);
if ($sA === $sB) return 0;
return ($sA < $sB) ? -1 : 1;
});
foreach($this->children as $child) $str.=$child->serialize();
$str.= "END:" . $this->name . "\r\n";
return $str;
}
/**
* Adds a new component or element
*
* You can call this method with the following syntaxes:
*
* add(Sabre_VObject_Element $element)
* add(string $name, $value)
*
* The first version adds an Element
* The second adds a property as a string.
*
* @param mixed $item
* @param mixed $itemValue
* @return void
*/
public function add($item, $itemValue = null) {
if ($item instanceof Sabre_VObject_Element) {
if (!is_null($itemValue)) {
throw new InvalidArgumentException('The second argument must not be specified, when passing a VObject');
}
$item->parent = $this;
$this->children[] = $item;
} elseif(is_string($item)) {
if (!is_scalar($itemValue)) {
throw new InvalidArgumentException('The second argument must be scalar');
}
$item = Sabre_VObject_Property::create($item,$itemValue);
$item->parent = $this;
$this->children[] = $item;
} else {
throw new InvalidArgumentException('The first argument must either be a Sabre_VObject_Element or a string');
}
}
/**
* Returns an iterable list of children
*
* @return Sabre_VObject_ElementList
*/
public function children() {
return new Sabre_VObject_ElementList($this->children);
}
/**
* Returns an array with elements that match the specified name.
*
* This function is also aware of MIME-Directory groups (as they appear in
* vcards). This means that if a property is grouped as "HOME.EMAIL", it
* will also be returned when searching for just "EMAIL". If you want to
* search for a property in a specific group, you can select on the entire
* string ("HOME.EMAIL"). If you want to search on a specific property that
* has not been assigned a group, specify ".EMAIL".
*
* Keys are retained from the 'children' array, which may be confusing in
* certain cases.
*
* @param string $name
* @return array
*/
public function select($name) {
$group = null;
$name = strtoupper($name);
if (strpos($name,'.')!==false) {
list($group,$name) = explode('.', $name, 2);
}
$result = array();
foreach($this->children as $key=>$child) {
if (
strtoupper($child->name) === $name &&
(is_null($group) || ( $child instanceof Sabre_VObject_Property && strtoupper($child->group) === $group))
) {
$result[$key] = $child;
}
}
reset($result);
return $result;
}
/**
* This method only returns a list of sub-components. Properties are
* ignored.
*
* @return array
*/
public function getComponents() {
$result = array();
foreach($this->children as $child) {
if ($child instanceof Sabre_VObject_Component) {
$result[] = $child;
}
}
return $result;
}
/**
* 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() {
$result = array();
foreach($this->children as $child) {
$result = array_merge($result, $child->validate());
}
return $result;
}
/* Magic property accessors {{{ */
/**
* Using 'get' you will either get a property or component,
*
* If there were no child-elements found with the specified name,
* null is returned.
*
* @param string $name
* @return Sabre_VObject_Property
*/
public function __get($name) {
$matches = $this->select($name);
if (count($matches)===0) {
return null;
} else {
$firstMatch = current($matches);
/** @var $firstMatch Sabre_VObject_Property */
$firstMatch->setIterator(new Sabre_VObject_ElementList(array_values($matches)));
return $firstMatch;
}
}
/**
* This method checks if a sub-element with the specified name exists.
*
* @param string $name
* @return bool
*/
public function __isset($name) {
$matches = $this->select($name);
return count($matches)>0;
}
/**
* Using the setter method you can add properties or subcomponents
*
* You can either pass a Sabre_VObject_Component, Sabre_VObject_Property
* object, or a string to automatically create a Property.
*
* If the item already exists, it will be removed. If you want to add
* a new item with the same name, always use the add() method.
*
* @param string $name
* @param mixed $value
* @return void
*/
public function __set($name, $value) {
$matches = $this->select($name);
$overWrite = count($matches)?key($matches):null;
if ($value instanceof Sabre_VObject_Component || $value instanceof Sabre_VObject_Property) {
$value->parent = $this;
if (!is_null($overWrite)) {
$this->children[$overWrite] = $value;
} else {
$this->children[] = $value;
}
} elseif (is_scalar($value)) {
$property = Sabre_VObject_Property::create($name,$value);
$property->parent = $this;
if (!is_null($overWrite)) {
$this->children[$overWrite] = $property;
} else {
$this->children[] = $property;
}
} else {
throw new InvalidArgumentException('You must pass a Sabre_VObject_Component, Sabre_VObject_Property or scalar type');
}
}
/**
* Removes all properties and components within this component.
*
* @param string $name
* @return void
*/
public function __unset($name) {
$matches = $this->select($name);
foreach($matches as $k=>$child) {
unset($this->children[$k]);
$child->parent = null;
}
}
/* }}} */
/**
* This method is automatically called when the object is cloned.
* Specifically, this will ensure all child elements are also cloned.
*
* @return void
*/
public function __clone() {
foreach($this->children as $key=>$child) {
$this->children[$key] = clone $child;
$this->children[$key]->parent = $this;
}
}
}

View file

@ -1,100 +0,0 @@
<?php
/**
* VAlarm component
*
* This component contains some additional functionality specific for VALARMs.
*
* @package Sabre
* @subpackage VObject
* @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
* @author Evert Pot (http://www.rooftopsolutions.nl/)
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
*/
class Sabre_VObject_Component_VAlarm extends Sabre_VObject_Component {
/**
* Returns a DateTime object when this alarm is going to trigger.
*
* This ignores repeated alarm, only the first trigger is returned.
*
* @return DateTime
*/
public function getEffectiveTriggerTime() {
$trigger = $this->TRIGGER;
if(!isset($trigger['VALUE']) || strtoupper($trigger['VALUE']) === 'DURATION') {
$triggerDuration = Sabre_VObject_DateTimeParser::parseDuration($this->TRIGGER);
$related = (isset($trigger['RELATED']) && strtoupper($trigger['RELATED']) == 'END') ? 'END' : 'START';
$parentComponent = $this->parent;
if ($related === 'START') {
$effectiveTrigger = clone $parentComponent->DTSTART->getDateTime();
$effectiveTrigger->add($triggerDuration);
} else {
if ($parentComponent->name === 'VTODO') {
$endProp = 'DUE';
} elseif ($parentComponent->name === 'VEVENT') {
$endProp = 'DTEND';
} else {
throw new Sabre_DAV_Exception('time-range filters on VALARM components are only supported when they are a child of VTODO or VEVENT');
}
if (isset($parentComponent->$endProp)) {
$effectiveTrigger = clone $parentComponent->$endProp->getDateTime();
$effectiveTrigger->add($triggerDuration);
} elseif (isset($parentComponent->DURATION)) {
$effectiveTrigger = clone $parentComponent->DTSTART->getDateTime();
$duration = Sabre_VObject_DateTimeParser::parseDuration($parentComponent->DURATION);
$effectiveTrigger->add($duration);
$effectiveTrigger->add($triggerDuration);
} else {
$effectiveTrigger = clone $parentComponent->DTSTART->getDateTime();
$effectiveTrigger->add($triggerDuration);
}
}
} else {
$effectiveTrigger = $trigger->getDateTime();
}
return $effectiveTrigger;
}
/**
* Returns true or false depending on if the event falls in the specified
* time-range. This is used for filtering purposes.
*
* The rules used to determine if an event falls within the specified
* time-range is based on the CalDAV specification.
*
* @param DateTime $start
* @param DateTime $end
* @return bool
*/
public function isInTimeRange(DateTime $start, DateTime $end) {
$effectiveTrigger = $this->getEffectiveTriggerTime();
if (isset($this->DURATION)) {
$duration = Sabre_VObject_DateTimeParser::parseDuration($this->DURATION);
$repeat = (string)$this->repeat;
if (!$repeat) {
$repeat = 1;
}
$period = new DatePeriod($effectiveTrigger, $duration, (int)$repeat);
foreach($period as $occurrence) {
if ($start <= $occurrence && $end > $occurrence) {
return true;
}
}
return false;
} else {
return ($start <= $effectiveTrigger && $end > $effectiveTrigger);
}
}
}

View file

@ -1,238 +0,0 @@
<?php
/**
* The VCalendar component
*
* This component adds functionality to a component, specific for a VCALENDAR.
*
* @package Sabre
* @subpackage VObject
* @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
* @author Evert Pot (http://www.rooftopsolutions.nl/)
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
*/
class Sabre_VObject_Component_VCalendar extends Sabre_VObject_Component {
/**
* Returns a list of all 'base components'. For instance, if an Event has
* a recurrence rule, and one instance is overridden, the overridden event
* will have the same UID, but will be excluded from this list.
*
* VTIMEZONE components will always be excluded.
*
* @param string $componentName filter by component name
* @return array
*/
public function getBaseComponents($componentName = null) {
$components = array();
foreach($this->children as $component) {
if (!$component instanceof Sabre_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;
}
/**
* If this calendar object, has events with recurrence rules, this method
* can be used to expand the event into multiple sub-events.
*
* Each event will be stripped from it's recurrence information, and only
* the instances of the event in the specified timerange will be left
* alone.
*
* In addition, this method will cause timezone information to be stripped,
* and normalized to UTC.
*
* This method will alter the VCalendar. This cannot be reversed.
*
* This functionality is specifically used by the CalDAV standard. It is
* possible for clients to request expand events, if they are rather simple
* clients and do not have the possibility to calculate recurrences.
*
* @param DateTime $start
* @param DateTime $end
* @return void
*/
public function expand(DateTime $start, DateTime $end) {
$newEvents = array();
foreach($this->select('VEVENT') as $key=>$vevent) {
if (isset($vevent->{'RECURRENCE-ID'})) {
unset($this->children[$key]);
continue;
}
if (!$vevent->rrule) {
unset($this->children[$key]);
if ($vevent->isInTimeRange($start, $end)) {
$newEvents[] = $vevent;
}
continue;
}
$uid = (string)$vevent->uid;
if (!$uid) {
throw new LogicException('Event did not have a UID!');
}
$it = new Sabre_VObject_RecurrenceIterator($this, $vevent->uid);
$it->fastForward($start);
while($it->valid() && $it->getDTStart() < $end) {
if ($it->getDTEnd() > $start) {
$newEvents[] = $it->getEventObject();
}
$it->next();
}
unset($this->children[$key]);
}
foreach($newEvents as $newEvent) {
foreach($newEvent->children as $child) {
if ($child instanceof Sabre_VObject_Property_DateTime &&
$child->getDateType() == Sabre_VObject_Property_DateTime::LOCALTZ) {
$child->setDateTime($child->getDateTime(),Sabre_VObject_Property_DateTime::UTC);
}
}
$this->add($newEvent);
}
// Removing all VTIMEZONE components
unset($this->VTIMEZONE);
}
/**
* 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() {
$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,
);
}
$allowedComponents = array(
'VEVENT',
'VTODO',
'VJOURNAL',
'VFREEBUSY',
'VTIMEZONE',
);
$allowedProperties = array(
'PRODID',
'VERSION',
'CALSCALE',
'METHOD',
);
$componentsFound = 0;
foreach($this->children as $child) {
if($child instanceof Sabre_VObject_Component) {
$componentsFound++;
if (!in_array($child->name, $allowedComponents)) {
$warnings[] = array(
'level' => 1,
'message' => 'The ' . $child->name . " component is not allowed in the VCALENDAR component",
'node' => $this,
);
}
}
if ($child instanceof Sabre_VObject_Property) {
if (!in_array($child->name, $allowedProperties)) {
$warnings[] = array(
'level' => 2,
'message' => 'The ' . $child->name . " property is not allowed in the VCALENDAR component",
'node' => $this,
);
}
}
}
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()
);
}
}

View file

@ -1,68 +0,0 @@
<?php
/**
* VEvent component
*
* This component contains some additional functionality specific for VEVENT's.
*
* @package Sabre
* @subpackage VObject
* @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
* @author Evert Pot (http://www.rooftopsolutions.nl/)
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
*/
class Sabre_VObject_Component_VEvent extends Sabre_VObject_Component {
/**
* Returns true or false depending on if the event falls in the specified
* time-range. This is used for filtering purposes.
*
* The rules used to determine if an event falls within the specified
* time-range is based on the CalDAV specification.
*
* @param DateTime $start
* @param DateTime $end
* @return bool
*/
public function isInTimeRange(DateTime $start, DateTime $end) {
if ($this->RRULE) {
$it = new Sabre_VObject_RecurrenceIterator($this);
$it->fastForward($start);
// We fast-forwarded to a spot where the end-time of the
// recurrence instance exceeded the start of the requested
// time-range.
//
// If the starttime of the recurrence did not exceed the
// end of the time range as well, we have a match.
return ($it->getDTStart() < $end && $it->getDTEnd() > $start);
}
$effectiveStart = $this->DTSTART->getDateTime();
if (isset($this->DTEND)) {
$effectiveEnd = $this->DTEND->getDateTime();
// If this was an all-day event, we should just increase the
// end-date by 1. Otherwise the event will last until the second
// the date changed, by increasing this by 1 day the event lasts
// all of the last day as well.
if ($this->DTSTART->getDateType() == Sabre_VObject_Property_DateTime::DATE) {
$effectiveEnd->modify('+1 day');
}
} elseif (isset($this->DURATION)) {
$effectiveEnd = clone $effectiveStart;
$effectiveEnd->add( Sabre_VObject_DateTimeParser::parseDuration($this->DURATION) );
} elseif ($this->DTSTART->getDateType() == Sabre_VObject_Property_DateTime::DATE) {
$effectiveEnd = clone $effectiveStart;
$effectiveEnd->modify('+1 day');
} else {
$effectiveEnd = clone $effectiveStart;
}
return (
($start <= $effectiveEnd) && ($end > $effectiveStart)
);
}
}

View file

@ -1,44 +0,0 @@
<?php
/**
* VJournal component
*
* This component contains some additional functionality specific for VJOURNALs.
*
* @package Sabre
* @subpackage VObject
* @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
* @author Evert Pot (http://www.rooftopsolutions.nl/)
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
*/
class Sabre_VObject_Component_VJournal extends Sabre_VObject_Component {
/**
* Returns true or false depending on if the event falls in the specified
* time-range. This is used for filtering purposes.
*
* The rules used to determine if an event falls within the specified
* time-range is based on the CalDAV specification.
*
* @param DateTime $start
* @param DateTime $end
* @return bool
*/
public function isInTimeRange(DateTime $start, DateTime $end) {
$dtstart = isset($this->DTSTART)?$this->DTSTART->getDateTime():null;
if ($dtstart) {
$effectiveEnd = clone $dtstart;
if ($this->DTSTART->getDateType() == Sabre_VObject_Property_DateTime::DATE) {
$effectiveEnd->modify('+1 day');
}
return ($start <= $effectiveEnd && $end > $dtstart);
}
return false;
}
}

View file

@ -1,66 +0,0 @@
<?php
/**
* VTodo component
*
* This component contains some additional functionality specific for VTODOs.
*
* @package Sabre
* @subpackage VObject
* @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
* @author Evert Pot (http://www.rooftopsolutions.nl/)
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
*/
class Sabre_VObject_Component_VTodo extends Sabre_VObject_Component {
/**
* Returns true or false depending on if the event falls in the specified
* time-range. This is used for filtering purposes.
*
* The rules used to determine if an event falls within the specified
* time-range is based on the CalDAV specification.
*
* @param DateTime $start
* @param DateTime $end
* @return bool
*/
public function isInTimeRange(DateTime $start, DateTime $end) {
$dtstart = isset($this->DTSTART)?$this->DTSTART->getDateTime():null;
$duration = isset($this->DURATION)?Sabre_VObject_DateTimeParser::parseDuration($this->DURATION):null;
$due = isset($this->DUE)?$this->DUE->getDateTime():null;
$completed = isset($this->COMPLETED)?$this->COMPLETED->getDateTime():null;
$created = isset($this->CREATED)?$this->CREATED->getDateTime():null;
if ($dtstart) {
if ($duration) {
$effectiveEnd = clone $dtstart;
$effectiveEnd->add($duration);
return $start <= $effectiveEnd && $end > $dtstart;
} elseif ($due) {
return
($start < $due || $start <= $dtstart) &&
($end > $dtstart || $end >= $due);
} else {
return $start <= $dtstart && $end > $dtstart;
}
}
if ($due) {
return ($start < $due && $end >= $due);
}
if ($completed && $created) {
return
($start <= $created || $start <= $completed) &&
($end >= $created || $end >= $completed);
}
if ($completed) {
return ($start <= $completed && $end >= $completed);
}
if ($created) {
return ($end > $created);
}
return true;
}
}

View file

@ -1,181 +0,0 @@
<?php
/**
* DateTimeParser
*
* This class is responsible for parsing the several different date and time
* formats iCalendar and vCards have.
*
* @package Sabre
* @subpackage VObject
* @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
* @author Evert Pot (http://www.rooftopsolutions.nl/)
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
*/
class Sabre_VObject_DateTimeParser {
/**
* Parses an iCalendar (rfc5545) formatted datetime and returns a DateTime object
*
* Specifying a reference timezone is optional. It will only be used
* if the non-UTC format is used. The argument is used as a reference, the
* returned DateTime object will still be in the UTC timezone.
*
* @param string $dt
* @param DateTimeZone $tz
* @return DateTime
*/
static public function parseDateTime($dt,DateTimeZone $tz = null) {
// Format is YYYYMMDD + "T" + hhmmss
$result = preg_match('/^([1-3][0-9]{3})([0-1][0-9])([0-3][0-9])T([0-2][0-9])([0-5][0-9])([0-5][0-9])([Z]?)$/',$dt,$matches);
if (!$result) {
throw new Sabre_DAV_Exception_BadRequest('The supplied iCalendar datetime value is incorrect: ' . $dt);
}
if ($matches[7]==='Z' || is_null($tz)) {
$tz = new DateTimeZone('UTC');
}
$date = new DateTime($matches[1] . '-' . $matches[2] . '-' . $matches[3] . ' ' . $matches[4] . ':' . $matches[5] .':' . $matches[6], $tz);
// Still resetting the timezone, to normalize everything to UTC
$date->setTimeZone(new DateTimeZone('UTC'));
return $date;
}
/**
* Parses an iCalendar (rfc5545) formatted date and returns a DateTime object
*
* @param string $date
* @return DateTime
*/
static public function parseDate($date) {
// Format is YYYYMMDD
$result = preg_match('/^([1-3][0-9]{3})([0-1][0-9])([0-3][0-9])$/',$date,$matches);
if (!$result) {
throw new Sabre_DAV_Exception_BadRequest('The supplied iCalendar date value is incorrect: ' . $date);
}
$date = new DateTime($matches[1] . '-' . $matches[2] . '-' . $matches[3], new DateTimeZone('UTC'));
return $date;
}
/**
* Parses an iCalendar (RFC5545) formatted duration value.
*
* This method will either return a DateTimeInterval object, or a string
* suitable for strtotime or DateTime::modify.
*
* @param string $duration
* @param bool $asString
* @return DateInterval|string
*/
static public function parseDuration($duration, $asString = false) {
$result = preg_match('/^(?P<plusminus>\+|-)?P((?P<week>\d+)W)?((?P<day>\d+)D)?(T((?P<hour>\d+)H)?((?P<minute>\d+)M)?((?P<second>\d+)S)?)?$/', $duration, $matches);
if (!$result) {
throw new Sabre_DAV_Exception_BadRequest('The supplied iCalendar duration value is incorrect: ' . $duration);
}
if (!$asString) {
$invert = false;
if ($matches['plusminus']==='-') {
$invert = true;
}
$parts = array(
'week',
'day',
'hour',
'minute',
'second',
);
foreach($parts as $part) {
$matches[$part] = isset($matches[$part])&&$matches[$part]?(int)$matches[$part]:0;
}
// We need to re-construct the $duration string, because weeks and
// days are not supported by DateInterval in the same string.
$duration = 'P';
$days = $matches['day'];
if ($matches['week']) {
$days+=$matches['week']*7;
}
if ($days)
$duration.=$days . 'D';
if ($matches['minute'] || $matches['second'] || $matches['hour']) {
$duration.='T';
if ($matches['hour'])
$duration.=$matches['hour'].'H';
if ($matches['minute'])
$duration.=$matches['minute'].'M';
if ($matches['second'])
$duration.=$matches['second'].'S';
}
if ($duration==='P') {
$duration = 'PT0S';
}
$iv = new DateInterval($duration);
if ($invert) $iv->invert = true;
return $iv;
}
$parts = array(
'week',
'day',
'hour',
'minute',
'second',
);
$newDur = '';
foreach($parts as $part) {
if (isset($matches[$part]) && $matches[$part]) {
$newDur.=' '.$matches[$part] . ' ' . $part . 's';
}
}
$newDur = ($matches['plusminus']==='-'?'-':'+') . trim($newDur);
if ($newDur === '+') { $newDur = '+0 seconds'; };
return $newDur;
}
/**
* Parses either a Date or DateTime, or Duration value.
*
* @param string $date
* @param DateTimeZone|string $referenceTZ
* @return DateTime|DateInterval
*/
static public function parse($date, $referenceTZ = null) {
if ($date[0]==='P' || ($date[0]==='-' && $date[1]==='P')) {
return self::parseDuration($date);
} elseif (strlen($date)===8) {
return self::parseDate($date);
} else {
return self::parseDateTime($date, $referenceTZ);
}
}
}

View file

@ -1,16 +0,0 @@
<?php
/**
* Base class for all elements
*
* @package Sabre
* @subpackage VObject
* @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
* @author Evert Pot (http://www.rooftopsolutions.nl/)
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
*/
abstract class Sabre_VObject_Element extends Sabre_VObject_Node {
public $parent = null;
}

View file

@ -1,172 +0,0 @@
<?php
/**
* VObject ElementList
*
* This class represents a list of elements. Lists are the result of queries,
* such as doing $vcalendar->vevent where there's multiple VEVENT objects.
*
* @package Sabre
* @subpackage VObject
* @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
* @author Evert Pot (http://www.rooftopsolutions.nl/)
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
*/
class Sabre_VObject_ElementList implements Iterator, Countable, ArrayAccess {
/**
* Inner elements
*
* @var array
*/
protected $elements = array();
/**
* Creates the element list.
*
* @param array $elements
*/
public function __construct(array $elements) {
$this->elements = $elements;
}
/* {{{ Iterator interface */
/**
* Current position
*
* @var int
*/
private $key = 0;
/**
* Returns current item in iteration
*
* @return Sabre_VObject_Element
*/
public function current() {
return $this->elements[$this->key];
}
/**
* To the next item in the iterator
*
* @return void
*/
public function next() {
$this->key++;
}
/**
* Returns the current iterator key
*
* @return int
*/
public function key() {
return $this->key;
}
/**
* Returns true if the current position in the iterator is a valid one
*
* @return bool
*/
public function valid() {
return isset($this->elements[$this->key]);
}
/**
* Rewinds the iterator
*
* @return void
*/
public function rewind() {
$this->key = 0;
}
/* }}} */
/* {{{ Countable interface */
/**
* Returns the number of elements
*
* @return int
*/
public function count() {
return count($this->elements);
}
/* }}} */
/* {{{ ArrayAccess Interface */
/**
* Checks if an item exists through ArrayAccess.
*
* @param int $offset
* @return bool
*/
public function offsetExists($offset) {
return isset($this->elements[$offset]);
}
/**
* Gets an item through ArrayAccess.
*
* @param int $offset
* @return mixed
*/
public function offsetGet($offset) {
return $this->elements[$offset];
}
/**
* Sets an item through ArrayAccess.
*
* @param int $offset
* @param mixed $value
* @return void
*/
public function offsetSet($offset,$value) {
throw new LogicException('You can not add new objects to an ElementList');
}
/**
* Sets an item through ArrayAccess.
*
* This method just forwards the request to the inner iterator
*
* @param int $offset
* @return void
*/
public function offsetUnset($offset) {
throw new LogicException('You can not remove objects from an ElementList');
}
/* }}} */
}

View file

@ -1,297 +0,0 @@
<?php
/**
* This class helps with generating FREEBUSY reports based on existing sets of
* objects.
*
* It only looks at VEVENT and VFREEBUSY objects from the sourcedata, and
* generates a single VFREEBUSY object.
*
* VFREEBUSY components are described in RFC5545, The rules for what should
* go in a single freebusy report is taken from RFC4791, section 7.10.
*
* @package Sabre
* @subpackage VObject
* @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
* @author Evert Pot (http://www.rooftopsolutions.nl/)
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
*/
class Sabre_VObject_FreeBusyGenerator {
/**
* Input objects
*
* @var array
*/
protected $objects;
/**
* Start of range
*
* @var DateTime|null
*/
protected $start;
/**
* End of range
*
* @var DateTime|null
*/
protected $end;
/**
* VCALENDAR object
*
* @var Sabre_VObject_Component
*/
protected $baseObject;
/**
* Sets the VCALENDAR object.
*
* If this is set, it will not be generated for you. You are responsible
* for setting things like the METHOD, CALSCALE, VERSION, etc..
*
* The VFREEBUSY object will be automatically added though.
*
* @param Sabre_VObject_Component $vcalendar
* @return void
*/
public function setBaseObject(Sabre_VObject_Component $vcalendar) {
$this->baseObject = $vcalendar;
}
/**
* Sets the input objects
*
* Every object must either be a string or a Sabre_VObject_Component.
*
* @param array $objects
* @return void
*/
public function setObjects(array $objects) {
$this->objects = array();
foreach($objects as $object) {
if (is_string($object)) {
$this->objects[] = Sabre_VObject_Reader::read($object);
} elseif ($object instanceof Sabre_VObject_Component) {
$this->objects[] = $object;
} else {
throw new InvalidArgumentException('You can only pass strings or Sabre_VObject_Component arguments to setObjects');
}
}
}
/**
* Sets the time range
*
* Any freebusy object falling outside of this time range will be ignored.
*
* @param DateTime $start
* @param DateTime $end
* @return void
*/
public function setTimeRange(DateTime $start = null, DateTime $end = null) {
$this->start = $start;
$this->end = $end;
}
/**
* Parses the input data and returns a correct VFREEBUSY object, wrapped in
* a VCALENDAR.
*
* @return Sabre_VObject_Component
*/
public function getResult() {
$busyTimes = array();
foreach($this->objects as $object) {
foreach($object->getBaseComponents() as $component) {
switch($component->name) {
case 'VEVENT' :
$FBTYPE = 'BUSY';
if (isset($component->TRANSP) && (strtoupper($component->TRANSP) === 'TRANSPARENT')) {
break;
}
if (isset($component->STATUS)) {
$status = strtoupper($component->STATUS);
if ($status==='CANCELLED') {
break;
}
if ($status==='TENTATIVE') {
$FBTYPE = 'BUSY-TENTATIVE';
}
}
$times = array();
if ($component->RRULE) {
$iterator = new Sabre_VObject_RecurrenceIterator($object, (string)$component->uid);
if ($this->start) {
$iterator->fastForward($this->start);
}
$maxRecurrences = 200;
while($iterator->valid() && --$maxRecurrences) {
$startTime = $iterator->getDTStart();
if ($this->end && $startTime > $this->end) {
break;
}
$times[] = array(
$iterator->getDTStart(),
$iterator->getDTEnd(),
);
$iterator->next();
}
} else {
$startTime = $component->DTSTART->getDateTime();
if ($this->end && $startTime > $this->end) {
break;
}
$endTime = null;
if (isset($component->DTEND)) {
$endTime = $component->DTEND->getDateTime();
} elseif (isset($component->DURATION)) {
$duration = Sabre_VObject_DateTimeParser::parseDuration((string)$component->DURATION);
$endTime = clone $startTime;
$endTime->add($duration);
} elseif ($component->DTSTART->getDateType() === Sabre_VObject_Property_DateTime::DATE) {
$endTime = clone $startTime;
$endTime->modify('+1 day');
} else {
// The event had no duration (0 seconds)
break;
}
$times[] = array($startTime, $endTime);
}
foreach($times as $time) {
if ($this->end && $time[0] > $this->end) break;
if ($this->start && $time[1] < $this->start) break;
$busyTimes[] = array(
$time[0],
$time[1],
$FBTYPE,
);
}
break;
case 'VFREEBUSY' :
foreach($component->FREEBUSY as $freebusy) {
$fbType = isset($freebusy['FBTYPE'])?strtoupper($freebusy['FBTYPE']):'BUSY';
// Skipping intervals marked as 'free'
if ($fbType==='FREE')
continue;
$values = explode(',', $freebusy);
foreach($values as $value) {
list($startTime, $endTime) = explode('/', $value);
$startTime = Sabre_VObject_DateTimeParser::parseDateTime($startTime);
if (substr($endTime,0,1)==='P' || substr($endTime,0,2)==='-P') {
$duration = Sabre_VObject_DateTimeParser::parseDuration($endTime);
$endTime = clone $startTime;
$endTime->add($duration);
} else {
$endTime = Sabre_VObject_DateTimeParser::parseDateTime($endTime);
}
if($this->start && $this->start > $endTime) continue;
if($this->end && $this->end < $startTime) continue;
$busyTimes[] = array(
$startTime,
$endTime,
$fbType
);
}
}
break;
}
}
}
if ($this->baseObject) {
$calendar = $this->baseObject;
} else {
$calendar = new Sabre_VObject_Component('VCALENDAR');
$calendar->version = '2.0';
if (Sabre_DAV_Server::$exposeVersion) {
$calendar->prodid = '-//SabreDAV//Sabre VObject ' . Sabre_VObject_Version::VERSION . '//EN';
} else {
$calendar->prodid = '-//SabreDAV//Sabre VObject//EN';
}
$calendar->calscale = 'GREGORIAN';
}
$vfreebusy = new Sabre_VObject_Component('VFREEBUSY');
$calendar->add($vfreebusy);
if ($this->start) {
$dtstart = new Sabre_VObject_Property_DateTime('DTSTART');
$dtstart->setDateTime($this->start,Sabre_VObject_Property_DateTime::UTC);
$vfreebusy->add($dtstart);
}
if ($this->end) {
$dtend = new Sabre_VObject_Property_DateTime('DTEND');
$dtend->setDateTime($this->start,Sabre_VObject_Property_DateTime::UTC);
$vfreebusy->add($dtend);
}
$dtstamp = new Sabre_VObject_Property_DateTime('DTSTAMP');
$dtstamp->setDateTime(new DateTime('now'), Sabre_VObject_Property_DateTime::UTC);
$vfreebusy->add($dtstamp);
foreach($busyTimes as $busyTime) {
$busyTime[0]->setTimeZone(new DateTimeZone('UTC'));
$busyTime[1]->setTimeZone(new DateTimeZone('UTC'));
$prop = new Sabre_VObject_Property(
'FREEBUSY',
$busyTime[0]->format('Ymd\\THis\\Z') . '/' . $busyTime[1]->format('Ymd\\THis\\Z')
);
$prop['FBTYPE'] = $busyTime[2];
$vfreebusy->add($prop);
}
return $calendar;
}
}

View file

@ -1,166 +0,0 @@
<?php
/**
* Base class for all nodes
*
* @package Sabre
* @subpackage VObject
* @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
* @author Evert Pot (http://www.rooftopsolutions.nl/)
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
*/
abstract class Sabre_VObject_Node implements IteratorAggregate, ArrayAccess, Countable {
/**
* Turns the object back into a serialized blob.
*
* @return string
*/
abstract function serialize();
/**
* Iterator override
*
* @var Sabre_VObject_ElementList
*/
protected $iterator = null;
/**
* A link to the parent node
*
* @var Sabre_VObject_Node
*/
public $parent = null;
/**
* 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() {
return array();
}
/* {{{ IteratorAggregator interface */
/**
* Returns the iterator for this object
*
* @return Sabre_VObject_ElementList
*/
public function getIterator() {
if (!is_null($this->iterator))
return $this->iterator;
return new Sabre_VObject_ElementList(array($this));
}
/**
* Sets the overridden iterator
*
* Note that this is not actually part of the iterator interface
*
* @param Sabre_VObject_ElementList $iterator
* @return void
*/
public function setIterator(Sabre_VObject_ElementList $iterator) {
$this->iterator = $iterator;
}
/* }}} */
/* {{{ Countable interface */
/**
* Returns the number of elements
*
* @return int
*/
public function count() {
$it = $this->getIterator();
return $it->count();
}
/* }}} */
/* {{{ ArrayAccess Interface */
/**
* Checks if an item exists through ArrayAccess.
*
* This method just forwards the request to the inner iterator
*
* @param int $offset
* @return bool
*/
public function offsetExists($offset) {
$iterator = $this->getIterator();
return $iterator->offsetExists($offset);
}
/**
* Gets an item through ArrayAccess.
*
* This method just forwards the request to the inner iterator
*
* @param int $offset
* @return mixed
*/
public function offsetGet($offset) {
$iterator = $this->getIterator();
return $iterator->offsetGet($offset);
}
/**
* Sets an item through ArrayAccess.
*
* This method just forwards the request to the inner iterator
*
* @param int $offset
* @param mixed $value
* @return void
*/
public function offsetSet($offset,$value) {
$iterator = $this->getIterator();
$iterator->offsetSet($offset,$value);
}
/**
* Sets an item through ArrayAccess.
*
* This method just forwards the request to the inner iterator
*
* @param int $offset
* @return void
*/
public function offsetUnset($offset) {
$iterator = $this->getIterator();
$iterator->offsetUnset($offset);
}
/* }}} */
}

View file

@ -1,84 +0,0 @@
<?php
/**
* VObject Parameter
*
* This class represents a parameter. A parameter is always tied to a property.
* In the case of:
* DTSTART;VALUE=DATE:20101108
* VALUE=DATE would be the parameter name and value.
*
* @package Sabre
* @subpackage VObject
* @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
* @author Evert Pot (http://www.rooftopsolutions.nl/)
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
*/
class Sabre_VObject_Parameter extends Sabre_VObject_Node {
/**
* Parameter name
*
* @var string
*/
public $name;
/**
* Parameter value
*
* @var string
*/
public $value;
/**
* Sets up the object
*
* @param string $name
* @param string $value
*/
public function __construct($name, $value = null) {
$this->name = strtoupper($name);
$this->value = $value;
}
/**
* Turns the object back into a serialized blob.
*
* @return string
*/
public function serialize() {
if (is_null($this->value)) {
return $this->name;
}
$src = array(
'\\',
"\n",
';',
',',
);
$out = array(
'\\\\',
'\n',
'\;',
'\,',
);
return $this->name . '=' . str_replace($src, $out, $this->value);
}
/**
* Called when this object is being cast to a string
*
* @return string
*/
public function __toString() {
return $this->value;
}
}

View file

@ -1,12 +0,0 @@
<?php
/**
* Exception thrown by Sabre_VObject_Reader if an invalid object was attempted to be parsed.
*
* @package Sabre
* @subpackage VObject
* @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
* @author Evert Pot (http://www.rooftopsolutions.nl/)
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
*/
class Sabre_VObject_ParseException extends Exception { }

View file

@ -1,348 +0,0 @@
<?php
/**
* VObject Property
*
* A property in VObject is usually in the form PARAMNAME:paramValue.
* An example is : SUMMARY:Weekly meeting
*
* Properties can also have parameters:
* SUMMARY;LANG=en:Weekly meeting.
*
* Parameters can be accessed using the ArrayAccess interface.
*
* @package Sabre
* @subpackage VObject
* @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
* @author Evert Pot (http://www.rooftopsolutions.nl/)
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
*/
class Sabre_VObject_Property extends Sabre_VObject_Element {
/**
* Propertyname
*
* @var string
*/
public $name;
/**
* Group name
*
* This may be something like 'HOME' for vcards.
*
* @var string
*/
public $group;
/**
* Property parameters
*
* @var array
*/
public $parameters = array();
/**
* Property value
*
* @var string
*/
public $value;
/**
* If properties are added to this map, they will be automatically mapped
* to their respective classes, if parsed by the reader or constructed with
* the 'create' method.
*
* @var array
*/
static public $classMap = array(
'COMPLETED' => 'Sabre_VObject_Property_DateTime',
'CREATED' => 'Sabre_VObject_Property_DateTime',
'DTEND' => 'Sabre_VObject_Property_DateTime',
'DTSTAMP' => 'Sabre_VObject_Property_DateTime',
'DTSTART' => 'Sabre_VObject_Property_DateTime',
'DUE' => 'Sabre_VObject_Property_DateTime',
'EXDATE' => 'Sabre_VObject_Property_MultiDateTime',
'LAST-MODIFIED' => 'Sabre_VObject_Property_DateTime',
'RECURRENCE-ID' => 'Sabre_VObject_Property_DateTime',
'TRIGGER' => 'Sabre_VObject_Property_DateTime',
);
/**
* Creates the new property by name, but in addition will also see if
* there's a class mapped to the property name.
*
* @param string $name
* @param string $value
* @return Sabre_VObject_Property
*/
static public function create($name, $value = null) {
$name = strtoupper($name);
$shortName = $name;
$group = null;
if (strpos($shortName,'.')!==false) {
list($group, $shortName) = explode('.', $shortName);
}
if (isset(self::$classMap[$shortName])) {
return new self::$classMap[$shortName]($name, $value);
} else {
return new self($name, $value);
}
}
/**
* Creates a new property object
*
* By default this object will iterate over its own children, but this can
* be overridden with the iterator argument
*
* @param string $name
* @param string $value
* @param Sabre_VObject_ElementList $iterator
*/
public function __construct($name, $value = null, $iterator = null) {
$name = strtoupper($name);
$group = null;
if (strpos($name,'.')!==false) {
list($group, $name) = explode('.', $name);
}
$this->name = $name;
$this->group = $group;
if (!is_null($iterator)) $this->iterator = $iterator;
$this->setValue($value);
}
/**
* Updates the internal value
*
* @param string $value
* @return void
*/
public function setValue($value) {
$this->value = $value;
}
/**
* Turns the object back into a serialized blob.
*
* @return string
*/
public function serialize() {
$str = $this->name;
if ($this->group) $str = $this->group . '.' . $this->name;
if (count($this->parameters)) {
foreach($this->parameters as $param) {
$str.=';' . $param->serialize();
}
}
$src = array(
'\\',
"\n",
);
$out = array(
'\\\\',
'\n',
);
$str.=':' . str_replace($src, $out, $this->value);
$out = '';
while(strlen($str)>0) {
if (strlen($str)>75) {
$out.= mb_strcut($str,0,75,'utf-8') . "\r\n";
$str = ' ' . mb_strcut($str,75,strlen($str),'utf-8');
} else {
$out.=$str . "\r\n";
$str='';
break;
}
}
return $out;
}
/**
* Adds a new componenten or element
*
* You can call this method with the following syntaxes:
*
* add(Sabre_VObject_Parameter $element)
* add(string $name, $value)
*
* The first version adds an Parameter
* The second adds a property as a string.
*
* @param mixed $item
* @param mixed $itemValue
* @return void
*/
public function add($item, $itemValue = null) {
if ($item instanceof Sabre_VObject_Parameter) {
if (!is_null($itemValue)) {
throw new InvalidArgumentException('The second argument must not be specified, when passing a VObject');
}
$item->parent = $this;
$this->parameters[] = $item;
} elseif(is_string($item)) {
if (!is_scalar($itemValue) && !is_null($itemValue)) {
throw new InvalidArgumentException('The second argument must be scalar');
}
$parameter = new Sabre_VObject_Parameter($item,$itemValue);
$parameter->parent = $this;
$this->parameters[] = $parameter;
} else {
throw new InvalidArgumentException('The first argument must either be a Sabre_VObject_Element or a string');
}
}
/* ArrayAccess interface {{{ */
/**
* Checks if an array element exists
*
* @param mixed $name
* @return bool
*/
public function offsetExists($name) {
if (is_int($name)) return parent::offsetExists($name);
$name = strtoupper($name);
foreach($this->parameters as $parameter) {
if ($parameter->name == $name) return true;
}
return false;
}
/**
* Returns a parameter, or parameter list.
*
* @param string $name
* @return Sabre_VObject_Element
*/
public function offsetGet($name) {
if (is_int($name)) return parent::offsetGet($name);
$name = strtoupper($name);
$result = array();
foreach($this->parameters as $parameter) {
if ($parameter->name == $name)
$result[] = $parameter;
}
if (count($result)===0) {
return null;
} elseif (count($result)===1) {
return $result[0];
} else {
$result[0]->setIterator(new Sabre_VObject_ElementList($result));
return $result[0];
}
}
/**
* Creates a new parameter
*
* @param string $name
* @param mixed $value
* @return void
*/
public function offsetSet($name, $value) {
if (is_int($name)) parent::offsetSet($name, $value);
if (is_scalar($value)) {
if (!is_string($name))
throw new InvalidArgumentException('A parameter name must be specified. This means you cannot use the $array[]="string" to add parameters.');
$this->offsetUnset($name);
$parameter = new Sabre_VObject_Parameter($name, $value);
$parameter->parent = $this;
$this->parameters[] = $parameter;
} elseif ($value instanceof Sabre_VObject_Parameter) {
if (!is_null($name))
throw new InvalidArgumentException('Don\'t specify a parameter name if you\'re passing a Sabre_VObject_Parameter. Add using $array[]=$parameterObject.');
$value->parent = $this;
$this->parameters[] = $value;
} else {
throw new InvalidArgumentException('You can only add parameters to the property object');
}
}
/**
* Removes one or more parameters with the specified name
*
* @param string $name
* @return void
*/
public function offsetUnset($name) {
if (is_int($name)) parent::offsetUnset($name);
$name = strtoupper($name);
foreach($this->parameters as $key=>$parameter) {
if ($parameter->name == $name) {
$parameter->parent = null;
unset($this->parameters[$key]);
}
}
}
/* }}} */
/**
* Called when this object is being cast to a string
*
* @return string
*/
public function __toString() {
return (string)$this->value;
}
/**
* This method is automatically called when the object is cloned.
* Specifically, this will ensure all child elements are also cloned.
*
* @return void
*/
public function __clone() {
foreach($this->parameters as $key=>$child) {
$this->parameters[$key] = clone $child;
$this->parameters[$key]->parent = $this;
}
}
}

View file

@ -1,228 +0,0 @@
<?php
/**
* DateTime property
*
* This element is used for iCalendar properties such as the DTSTART property.
* It basically provides a few helper functions that make it easier to deal
* with these. It supports both DATE-TIME and DATE values.
*
* In order to use this correctly, you must call setDateTime and getDateTime to
* retrieve and modify dates respectively.
*
* If you use the 'value' or properties directly, this object does not keep
* reference and results might appear incorrectly.
*
* @package Sabre
* @subpackage VObject
* @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
* @author Evert Pot (http://www.rooftopsolutions.nl/)
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
*/
class Sabre_VObject_Property_DateTime extends Sabre_VObject_Property {
/**
* Local 'floating' time
*/
const LOCAL = 1;
/**
* UTC-based time
*/
const UTC = 2;
/**
* Local time plus timezone
*/
const LOCALTZ = 3;
/**
* Only a date, time is ignored
*/
const DATE = 4;
/**
* DateTime representation
*
* @var DateTime
*/
protected $dateTime;
/**
* dateType
*
* @var int
*/
protected $dateType;
/**
* Updates the Date and Time.
*
* @param DateTime $dt
* @param int $dateType
* @return void
*/
public function setDateTime(DateTime $dt, $dateType = self::LOCALTZ) {
switch($dateType) {
case self::LOCAL :
$this->setValue($dt->format('Ymd\\THis'));
$this->offsetUnset('VALUE');
$this->offsetUnset('TZID');
$this->offsetSet('VALUE','DATE-TIME');
break;
case self::UTC :
$dt->setTimeZone(new DateTimeZone('UTC'));
$this->setValue($dt->format('Ymd\\THis\\Z'));
$this->offsetUnset('VALUE');
$this->offsetUnset('TZID');
$this->offsetSet('VALUE','DATE-TIME');
break;
case self::LOCALTZ :
$this->setValue($dt->format('Ymd\\THis'));
$this->offsetUnset('VALUE');
$this->offsetUnset('TZID');
$this->offsetSet('VALUE','DATE-TIME');
$this->offsetSet('TZID', $dt->getTimeZone()->getName());
break;
case self::DATE :
$this->setValue($dt->format('Ymd'));
$this->offsetUnset('VALUE');
$this->offsetUnset('TZID');
$this->offsetSet('VALUE','DATE');
break;
default :
throw new InvalidArgumentException('You must pass a valid dateType constant');
}
$this->dateTime = $dt;
$this->dateType = $dateType;
}
/**
* Returns the current DateTime value.
*
* If no value was set, this method returns null.
*
* @return DateTime|null
*/
public function getDateTime() {
if ($this->dateTime)
return $this->dateTime;
list(
$this->dateType,
$this->dateTime
) = self::parseData($this->value, $this);
return $this->dateTime;
}
/**
* Returns the type of Date format.
*
* This method returns one of the format constants. If no date was set,
* this method will return null.
*
* @return int|null
*/
public function getDateType() {
if ($this->dateType)
return $this->dateType;
list(
$this->dateType,
$this->dateTime,
) = self::parseData($this->value, $this);
return $this->dateType;
}
/**
* Parses the internal data structure to figure out what the current date
* and time is.
*
* The returned array contains two elements:
* 1. A 'DateType' constant (as defined on this class), or null.
* 2. A DateTime object (or null)
*
* @param string|null $propertyValue The string to parse (yymmdd or
* ymmddThhmmss, etc..)
* @param Sabre_VObject_Property|null $property The instance of the
* property we're parsing.
* @return array
*/
static public function parseData($propertyValue, Sabre_VObject_Property $property = null) {
if (is_null($propertyValue)) {
return array(null, null);
}
$date = '(?P<year>[1-2][0-9]{3})(?P<month>[0-1][0-9])(?P<date>[0-3][0-9])';
$time = '(?P<hour>[0-2][0-9])(?P<minute>[0-5][0-9])(?P<second>[0-5][0-9])';
$regex = "/^$date(T$time(?P<isutc>Z)?)?$/";
if (!preg_match($regex, $propertyValue, $matches)) {
throw new InvalidArgumentException($propertyValue . ' is not a valid DateTime or Date string');
}
if (!isset($matches['hour'])) {
// Date-only
return array(
self::DATE,
new DateTime($matches['year'] . '-' . $matches['month'] . '-' . $matches['date'] . ' 00:00:00'),
);
}
$dateStr =
$matches['year'] .'-' .
$matches['month'] . '-' .
$matches['date'] . ' ' .
$matches['hour'] . ':' .
$matches['minute'] . ':' .
$matches['second'];
if (isset($matches['isutc'])) {
$dt = new DateTime($dateStr,new DateTimeZone('UTC'));
$dt->setTimeZone(new DateTimeZone('UTC'));
return array(
self::UTC,
$dt
);
}
// Finding the timezone.
$tzid = $property['TZID'];
if (!$tzid) {
return array(
self::LOCAL,
new DateTime($dateStr)
);
}
// To look up the timezone, we must first find the VCALENDAR component.
$root = $property;
while($root->parent) {
$root = $root->parent;
}
if ($root->name === 'VCALENDAR') {
$tz = Sabre_VObject_TimeZoneUtil::getTimeZone((string)$tzid, $root);
} else {
$tz = Sabre_VObject_TimeZoneUtil::getTimeZone((string)$tzid);
}
$dt = new DateTime($dateStr, $tz);
$dt->setTimeZone($tz);
return array(
self::LOCALTZ,
$dt
);
}
}

View file

@ -1,166 +0,0 @@
<?php
/**
* Multi-DateTime property
*
* This element is used for iCalendar properties such as the EXDATE property.
* It basically provides a few helper functions that make it easier to deal
* with these. It supports both DATE-TIME and DATE values.
*
* In order to use this correctly, you must call setDateTimes and getDateTimes
* to retrieve and modify dates respectively.
*
* If you use the 'value' or properties directly, this object does not keep
* reference and results might appear incorrectly.
*
* @package Sabre
* @subpackage VObject
* @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
* @author Evert Pot (http://www.rooftopsolutions.nl/)
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
*/
class Sabre_VObject_Property_MultiDateTime extends Sabre_VObject_Property {
/**
* DateTime representation
*
* @var DateTime[]
*/
protected $dateTimes;
/**
* dateType
*
* This is one of the Sabre_VObject_Property_DateTime constants.
*
* @var int
*/
protected $dateType;
/**
* Updates the value
*
* @param array $dt Must be an array of DateTime objects.
* @param int $dateType
* @return void
*/
public function setDateTimes(array $dt, $dateType = Sabre_VObject_Property_DateTime::LOCALTZ) {
foreach($dt as $i)
if (!$i instanceof DateTime)
throw new InvalidArgumentException('You must pass an array of DateTime objects');
$this->offsetUnset('VALUE');
$this->offsetUnset('TZID');
switch($dateType) {
case Sabre_VObject_Property_DateTime::LOCAL :
$val = array();
foreach($dt as $i) {
$val[] = $i->format('Ymd\\THis');
}
$this->setValue(implode(',',$val));
$this->offsetSet('VALUE','DATE-TIME');
break;
case Sabre_VObject_Property_DateTime::UTC :
$val = array();
foreach($dt as $i) {
$i->setTimeZone(new DateTimeZone('UTC'));
$val[] = $i->format('Ymd\\THis\\Z');
}
$this->setValue(implode(',',$val));
$this->offsetSet('VALUE','DATE-TIME');
break;
case Sabre_VObject_Property_DateTime::LOCALTZ :
$val = array();
foreach($dt as $i) {
$val[] = $i->format('Ymd\\THis');
}
$this->setValue(implode(',',$val));
$this->offsetSet('VALUE','DATE-TIME');
$this->offsetSet('TZID', $dt[0]->getTimeZone()->getName());
break;
case Sabre_VObject_Property_DateTime::DATE :
$val = array();
foreach($dt as $i) {
$val[] = $i->format('Ymd');
}
$this->setValue(implode(',',$val));
$this->offsetSet('VALUE','DATE');
break;
default :
throw new InvalidArgumentException('You must pass a valid dateType constant');
}
$this->dateTimes = $dt;
$this->dateType = $dateType;
}
/**
* Returns the current DateTime value.
*
* If no value was set, this method returns null.
*
* @return array|null
*/
public function getDateTimes() {
if ($this->dateTimes)
return $this->dateTimes;
$dts = array();
if (!$this->value) {
$this->dateTimes = null;
$this->dateType = null;
return null;
}
foreach(explode(',',$this->value) as $val) {
list(
$type,
$dt
) = Sabre_VObject_Property_DateTime::parseData($val, $this);
$dts[] = $dt;
$this->dateType = $type;
}
$this->dateTimes = $dts;
return $this->dateTimes;
}
/**
* Returns the type of Date format.
*
* This method returns one of the format constants. If no date was set,
* this method will return null.
*
* @return int|null
*/
public function getDateType() {
if ($this->dateType)
return $this->dateType;
if (!$this->value) {
$this->dateTimes = null;
$this->dateType = null;
return null;
}
$dts = array();
foreach(explode(',',$this->value) as $val) {
list(
$type,
$dt
) = Sabre_VObject_Property_DateTime::parseData($val, $this);
$dts[] = $dt;
$this->dateType = $type;
}
$this->dateTimes = $dts;
return $this->dateType;
}
}

View file

@ -1,183 +0,0 @@
<?php
/**
* VCALENDAR/VCARD reader
*
* This class reads the vobject file, and returns a full element tree.
*
* TODO: this class currently completely works 'statically'. This is pointless,
* and defeats OOP principals. Needs refactoring in a future version.
*
* @package Sabre
* @subpackage VObject
* @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
* @author Evert Pot (http://www.rooftopsolutions.nl/)
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
*/
class Sabre_VObject_Reader {
/**
* Parses the file and returns the top component
*
* @param string $data
* @return Sabre_VObject_Element
*/
static function read($data) {
// Normalizing newlines
$data = str_replace(array("\r","\n\n"), array("\n","\n"), $data);
$lines = explode("\n", $data);
// Unfolding lines
$lines2 = array();
foreach($lines as $line) {
// Skipping empty lines
if (!$line) continue;
if ($line[0]===" " || $line[0]==="\t") {
$lines2[count($lines2)-1].=substr($line,1);
} else {
$lines2[] = $line;
}
}
unset($lines);
reset($lines2);
return self::readLine($lines2);
}
/**
* Reads and parses a single line.
*
* This method receives the full array of lines. The array pointer is used
* to traverse.
*
* @param array $lines
* @return Sabre_VObject_Element
*/
static private function readLine(&$lines) {
$line = current($lines);
$lineNr = key($lines);
next($lines);
// Components
if (stripos($line,"BEGIN:")===0) {
$componentName = strtoupper(substr($line,6));
$obj = Sabre_VObject_Component::create($componentName);
$nextLine = current($lines);
while(stripos($nextLine,"END:")!==0) {
$obj->add(self::readLine($lines));
$nextLine = current($lines);
if ($nextLine===false)
throw new Sabre_VObject_ParseException('Invalid VObject. Document ended prematurely.');
}
// Checking component name of the 'END:' line.
if (substr($nextLine,4)!==$obj->name) {
throw new Sabre_VObject_ParseException('Invalid VObject, expected: "END:' . $obj->name . '" got: "' . $nextLine . '"');
}
next($lines);
return $obj;
}
// Properties
//$result = preg_match('/(?P<name>[A-Z0-9-]+)(?:;(?P<parameters>^(?<!:):))(.*)$/',$line,$matches);
$token = '[A-Z0-9-\.]+';
$parameters = "(?:;(?P<parameters>([^:^\"]|\"([^\"]*)\")*))?";
$regex = "/^(?P<name>$token)$parameters:(?P<value>.*)$/i";
$result = preg_match($regex,$line,$matches);
if (!$result) {
throw new Sabre_VObject_ParseException('Invalid VObject, line ' . ($lineNr+1) . ' did not follow the icalendar/vcard format');
}
$propertyName = strtoupper($matches['name']);
$propertyValue = preg_replace_callback('#(\\\\(\\\\|N|n|;|,))#',function($matches) {
if ($matches[2]==='n' || $matches[2]==='N') {
return "\n";
} else {
return $matches[2];
}
}, $matches['value']);
$obj = Sabre_VObject_Property::create($propertyName, $propertyValue);
if ($matches['parameters']) {
foreach(self::readParameters($matches['parameters']) as $param) {
$obj->add($param);
}
}
return $obj;
}
/**
* Reads a parameter list from a property
*
* This method returns an array of Sabre_VObject_Parameter
*
* @param string $parameters
* @return array
*/
static private function readParameters($parameters) {
$token = '[A-Z0-9-]+';
$paramValue = '(?P<paramValue>[^\"^;]*|"[^"]*")';
$regex = "/(?<=^|;)(?P<paramName>$token)(=$paramValue(?=$|;))?/i";
preg_match_all($regex, $parameters, $matches, PREG_SET_ORDER);
$params = array();
foreach($matches as $match) {
$value = isset($match['paramValue'])?$match['paramValue']:null;
if (isset($value[0])) {
// Stripping quotes, if needed
if ($value[0] === '"') $value = substr($value,1,strlen($value)-2);
} else {
$value = '';
}
$value = preg_replace_callback('#(\\\\(\\\\|N|n|;|,))#',function($matches) {
if ($matches[2]==='n' || $matches[2]==='N') {
return "\n";
} else {
return $matches[2];
}
}, $value);
$params[] = new Sabre_VObject_Parameter($match['paramName'], $value);
}
return $params;
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,351 +0,0 @@
<?php
/**
* Time zone name translation
*
* This file translates well-known time zone names into "Olson database" time zone names.
*
* @package Sabre
* @subpackage VObject
* @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
* @author Frank Edelhaeuser (fedel@users.sourceforge.net)
* @author Evert Pot (http://www.rooftopsolutions.nl/)
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
*/
class Sabre_VObject_TimeZoneUtil {
public static $map = array(
// from http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/zone_tzid.html
// snapshot taken on 2012/01/16
// windows
'AUS Central Standard Time'=>'Australia/Darwin',
'AUS Eastern Standard Time'=>'Australia/Sydney',
'Afghanistan Standard Time'=>'Asia/Kabul',
'Alaskan Standard Time'=>'America/Anchorage',
'Arab Standard Time'=>'Asia/Riyadh',
'Arabian Standard Time'=>'Asia/Dubai',
'Arabic Standard Time'=>'Asia/Baghdad',
'Argentina Standard Time'=>'America/Buenos_Aires',
'Armenian Standard Time'=>'Asia/Yerevan',
'Atlantic Standard Time'=>'America/Halifax',
'Azerbaijan Standard Time'=>'Asia/Baku',
'Azores Standard Time'=>'Atlantic/Azores',
'Bangladesh Standard Time'=>'Asia/Dhaka',
'Canada Central Standard Time'=>'America/Regina',
'Cape Verde Standard Time'=>'Atlantic/Cape_Verde',
'Caucasus Standard Time'=>'Asia/Yerevan',
'Cen. Australia Standard Time'=>'Australia/Adelaide',
'Central America Standard Time'=>'America/Guatemala',
'Central Asia Standard Time'=>'Asia/Almaty',
'Central Brazilian Standard Time'=>'America/Cuiaba',
'Central Europe Standard Time'=>'Europe/Budapest',
'Central European Standard Time'=>'Europe/Warsaw',
'Central Pacific Standard Time'=>'Pacific/Guadalcanal',
'Central Standard Time'=>'America/Chicago',
'Central Standard Time (Mexico)'=>'America/Mexico_City',
'China Standard Time'=>'Asia/Shanghai',
'Dateline Standard Time'=>'Etc/GMT+12',
'E. Africa Standard Time'=>'Africa/Nairobi',
'E. Australia Standard Time'=>'Australia/Brisbane',
'E. Europe Standard Time'=>'Europe/Minsk',
'E. South America Standard Time'=>'America/Sao_Paulo',
'Eastern Standard Time'=>'America/New_York',
'Egypt Standard Time'=>'Africa/Cairo',
'Ekaterinburg Standard Time'=>'Asia/Yekaterinburg',
'FLE Standard Time'=>'Europe/Kiev',
'Fiji Standard Time'=>'Pacific/Fiji',
'GMT Standard Time'=>'Europe/London',
'GTB Standard Time'=>'Europe/Istanbul',
'Georgian Standard Time'=>'Asia/Tbilisi',
'Greenland Standard Time'=>'America/Godthab',
'Greenwich Standard Time'=>'Atlantic/Reykjavik',
'Hawaiian Standard Time'=>'Pacific/Honolulu',
'India Standard Time'=>'Asia/Calcutta',
'Iran Standard Time'=>'Asia/Tehran',
'Israel Standard Time'=>'Asia/Jerusalem',
'Jordan Standard Time'=>'Asia/Amman',
'Kamchatka Standard Time'=>'Asia/Kamchatka',
'Korea Standard Time'=>'Asia/Seoul',
'Magadan Standard Time'=>'Asia/Magadan',
'Mauritius Standard Time'=>'Indian/Mauritius',
'Mexico Standard Time'=>'America/Mexico_City',
'Mexico Standard Time 2'=>'America/Chihuahua',
'Mid-Atlantic Standard Time'=>'Etc/GMT+2',
'Middle East Standard Time'=>'Asia/Beirut',
'Montevideo Standard Time'=>'America/Montevideo',
'Morocco Standard Time'=>'Africa/Casablanca',
'Mountain Standard Time'=>'America/Denver',
'Mountain Standard Time (Mexico)'=>'America/Chihuahua',
'Myanmar Standard Time'=>'Asia/Rangoon',
'N. Central Asia Standard Time'=>'Asia/Novosibirsk',
'Namibia Standard Time'=>'Africa/Windhoek',
'Nepal Standard Time'=>'Asia/Katmandu',
'New Zealand Standard Time'=>'Pacific/Auckland',
'Newfoundland Standard Time'=>'America/St_Johns',
'North Asia East Standard Time'=>'Asia/Irkutsk',
'North Asia Standard Time'=>'Asia/Krasnoyarsk',
'Pacific SA Standard Time'=>'America/Santiago',
'Pacific Standard Time'=>'America/Los_Angeles',
'Pacific Standard Time (Mexico)'=>'America/Santa_Isabel',
'Pakistan Standard Time'=>'Asia/Karachi',
'Paraguay Standard Time'=>'America/Asuncion',
'Romance Standard Time'=>'Europe/Paris',
'Russian Standard Time'=>'Europe/Moscow',
'SA Eastern Standard Time'=>'America/Cayenne',
'SA Pacific Standard Time'=>'America/Bogota',
'SA Western Standard Time'=>'America/La_Paz',
'SE Asia Standard Time'=>'Asia/Bangkok',
'Samoa Standard Time'=>'Pacific/Apia',
'Singapore Standard Time'=>'Asia/Singapore',
'South Africa Standard Time'=>'Africa/Johannesburg',
'Sri Lanka Standard Time'=>'Asia/Colombo',
'Syria Standard Time'=>'Asia/Damascus',
'Taipei Standard Time'=>'Asia/Taipei',
'Tasmania Standard Time'=>'Australia/Hobart',
'Tokyo Standard Time'=>'Asia/Tokyo',
'Tonga Standard Time'=>'Pacific/Tongatapu',
'US Eastern Standard Time'=>'America/Indianapolis',
'US Mountain Standard Time'=>'America/Phoenix',
'UTC'=>'Etc/GMT',
'UTC+12'=>'Etc/GMT-12',
'UTC-02'=>'Etc/GMT+2',
'UTC-11'=>'Etc/GMT+11',
'Ulaanbaatar Standard Time'=>'Asia/Ulaanbaatar',
'Venezuela Standard Time'=>'America/Caracas',
'Vladivostok Standard Time'=>'Asia/Vladivostok',
'W. Australia Standard Time'=>'Australia/Perth',
'W. Central Africa Standard Time'=>'Africa/Lagos',
'W. Europe Standard Time'=>'Europe/Berlin',
'West Asia Standard Time'=>'Asia/Tashkent',
'West Pacific Standard Time'=>'Pacific/Port_Moresby',
'Yakutsk Standard Time'=>'Asia/Yakutsk',
// Microsoft exchange timezones
// Source:
// http://msdn.microsoft.com/en-us/library/ms988620%28v=exchg.65%29.aspx
//
// Correct timezones deduced with help from:
// http://en.wikipedia.org/wiki/List_of_tz_database_time_zones
'Universal Coordinated Time' => 'UTC',
'Casablanca, Monrovia' => 'Africa/Casablanca',
'Greenwich Mean Time: Dublin, Edinburgh, Lisbon, London' => 'Europe/Lisbon',
'Greenwich Mean Time; Dublin, Edinburgh, London' => 'Europe/London',
'Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna' => 'Europe/Berlin',
'Belgrade, Pozsony, Budapest, Ljubljana, Prague' => 'Europe/Prague',
'Brussels, Copenhagen, Madrid, Paris' => 'Europe/Paris',
'Paris, Madrid, Brussels, Copenhagen' => 'Europe/Paris',
'Prague, Central Europe' => 'Europe/Prague',
'Sarajevo, Skopje, Sofija, Vilnius, Warsaw, Zagreb' => 'Europe/Sarajevo',
'West Central Africa' => 'Africa/Luanda', // This was a best guess
'Athens, Istanbul, Minsk' => 'Europe/Athens',
'Bucharest' => 'Europe/Bucharest',
'Cairo' => 'Africa/Cairo',
'Harare, Pretoria' => 'Africa/Harare',
'Helsinki, Riga, Tallinn' => 'Europe/Helsinki',
'Israel, Jerusalem Standard Time' => 'Asia/Jerusalem',
'Baghdad' => 'Asia/Baghdad',
'Arab, Kuwait, Riyadh' => 'Asia/Kuwait',
'Moscow, St. Petersburg, Volgograd' => 'Europe/Moscow',
'East Africa, Nairobi' => 'Africa/Nairobi',
'Tehran' => 'Asia/Tehran',
'Abu Dhabi, Muscat' => 'Asia/Muscat', // Best guess
'Baku, Tbilisi, Yerevan' => 'Asia/Baku',
'Kabul' => 'Asia/Kabul',
'Ekaterinburg' => 'Asia/Yekaterinburg',
'Islamabad, Karachi, Tashkent' => 'Asia/Karachi',
'Kolkata, Chennai, Mumbai, New Delhi, India Standard Time' => 'Asia/Calcutta',
'Kathmandu, Nepal' => 'Asia/Kathmandu',
'Almaty, Novosibirsk, North Central Asia' => 'Asia/Almaty',
'Astana, Dhaka' => 'Asia/Dhaka',
'Sri Jayawardenepura, Sri Lanka' => 'Asia/Colombo',
'Rangoon' => 'Asia/Rangoon',
'Bangkok, Hanoi, Jakarta' => 'Asia/Bangkok',
'Krasnoyarsk' => 'Asia/Krasnoyarsk',
'Beijing, Chongqing, Hong Kong SAR, Urumqi' => 'Asia/Shanghai',
'Irkutsk, Ulaan Bataar' => 'Asia/Irkutsk',
'Kuala Lumpur, Singapore' => 'Asia/Singapore',
'Perth, Western Australia' => 'Australia/Perth',
'Taipei' => 'Asia/Taipei',
'Osaka, Sapporo, Tokyo' => 'Asia/Tokyo',
'Seoul, Korea Standard time' => 'Asia/Seoul',
'Yakutsk' => 'Asia/Yakutsk',
'Adelaide, Central Australia' => 'Australia/Adelaide',
'Darwin' => 'Australia/Darwin',
'Brisbane, East Australia' => 'Australia/Brisbane',
'Canberra, Melbourne, Sydney, Hobart (year 2000 only)' => 'Australia/Sydney',
'Guam, Port Moresby' => 'Pacific/Guam',
'Hobart, Tasmania' => 'Australia/Hobart',
'Vladivostok' => 'Asia/Vladivostok',
'Magadan, Solomon Is., New Caledonia' => 'Asia/Magadan',
'Auckland, Wellington' => 'Pacific/Auckland',
'Fiji Islands, Kamchatka, Marshall Is.' => 'Pacific/Fiji',
'Nuku\'alofa, Tonga' => 'Pacific/Tongatapu',
'Azores' => 'Atlantic/Azores',
'Cape Verde Is.' => 'Atlantic/Cape_Verde',
'Mid-Atlantic' => 'America/Noronha',
'Brasilia' => 'America/Sao_Paulo', // Best guess
'Buenos Aires' => 'America/Argentina/Buenos_Aires',
'Greenland' => 'America/Godthab',
'Newfoundland' => 'America/St_Johns',
'Atlantic Time (Canada)' => 'America/Halifax',
'Caracas, La Paz' => 'America/Caracas',
'Santiago' => 'America/Santiago',
'Bogota, Lima, Quito' => 'America/Bogota',
'Eastern Time (US & Canada)' => 'America/New_York',
'Indiana (East)' => 'America/Indiana/Indianapolis',
'Central America' => 'America/Guatemala',
'Central Time (US & Canada)' => 'America/Chicago',
'Mexico City, Tegucigalpa' => 'America/Mexico_City',
'Saskatchewan' => 'America/Edmonton',
'Arizona' => 'America/Phoenix',
'Mountain Time (US & Canada)' => 'America/Denver', // Best guess
'Pacific Time (US & Canada); Tijuana' => 'America/Los_Angeles', // Best guess
'Alaska' => 'America/Anchorage',
'Hawaii' => 'Pacific/Honolulu',
'Midway Island, Samoa' => 'Pacific/Midway',
'Eniwetok, Kwajalein, Dateline Time' => 'Pacific/Kwajalein',
);
public static $microsoftExchangeMap = array(
0 => 'UTC',
31 => 'Africa/Casablanca',
2 => 'Europe/Lisbon',
1 => 'Europe/London',
4 => 'Europe/Berlin',
6 => 'Europe/Prague',
3 => 'Europe/Paris',
69 => 'Africa/Luanda', // This was a best guess
7 => 'Europe/Athens',
5 => 'Europe/Bucharest',
49 => 'Africa/Cairo',
50 => 'Africa/Harare',
59 => 'Europe/Helsinki',
27 => 'Asia/Jerusalem',
26 => 'Asia/Baghdad',
74 => 'Asia/Kuwait',
51 => 'Europe/Moscow',
56 => 'Africa/Nairobi',
25 => 'Asia/Tehran',
24 => 'Asia/Muscat', // Best guess
54 => 'Asia/Baku',
48 => 'Asia/Kabul',
58 => 'Asia/Yekaterinburg',
47 => 'Asia/Karachi',
23 => 'Asia/Calcutta',
62 => 'Asia/Kathmandu',
46 => 'Asia/Almaty',
71 => 'Asia/Dhaka',
66 => 'Asia/Colombo',
61 => 'Asia/Rangoon',
22 => 'Asia/Bangkok',
64 => 'Asia/Krasnoyarsk',
45 => 'Asia/Shanghai',
63 => 'Asia/Irkutsk',
21 => 'Asia/Singapore',
73 => 'Australia/Perth',
75 => 'Asia/Taipei',
20 => 'Asia/Tokyo',
72 => 'Asia/Seoul',
70 => 'Asia/Yakutsk',
19 => 'Australia/Adelaide',
44 => 'Australia/Darwin',
18 => 'Australia/Brisbane',
76 => 'Australia/Sydney',
43 => 'Pacific/Guam',
42 => 'Australia/Hobart',
68 => 'Asia/Vladivostok',
41 => 'Asia/Magadan',
17 => 'Pacific/Auckland',
40 => 'Pacific/Fiji',
67 => 'Pacific/Tongatapu',
29 => 'Atlantic/Azores',
53 => 'Atlantic/Cape_Verde',
30 => 'America/Noronha',
8 => 'America/Sao_Paulo', // Best guess
32 => 'America/Argentina/Buenos_Aires',
69 => 'America/Godthab',
28 => 'America/St_Johns',
9 => 'America/Halifax',
33 => 'America/Caracas',
65 => 'America/Santiago',
35 => 'America/Bogota',
10 => 'America/New_York',
34 => 'America/Indiana/Indianapolis',
55 => 'America/Guatemala',
11 => 'America/Chicago',
37 => 'America/Mexico_City',
36 => 'America/Edmonton',
38 => 'America/Phoenix',
12 => 'America/Denver', // Best guess
13 => 'America/Los_Angeles', // Best guess
14 => 'America/Anchorage',
15 => 'Pacific/Honolulu',
16 => 'Pacific/Midway',
39 => 'Pacific/Kwajalein',
);
/**
* This method will try to find out the correct timezone for an iCalendar
* date-time value.
*
* You must pass the contents of the TZID parameter, as well as the full
* calendar.
*
* If the lookup fails, this method will return UTC.
*
* @param string $tzid
* @param Sabre_VObject_Component $vcalendar
* @return DateTimeZone
*/
static public function getTimeZone($tzid, Sabre_VObject_Component $vcalendar = null) {
// First we will just see if the tzid is a support timezone identifier.
try {
return new DateTimeZone($tzid);
} catch (\Exception $e) {
}
// Next, we check if the tzid is somewhere in our tzid map.
if (isset(self::$map[$tzid])) {
return new DateTimeZone(self::$map[$tzid]);
}
if ($vcalendar) {
// If that didn't work, we will scan VTIMEZONE objects
foreach($vcalendar->select('VTIMEZONE') as $vtimezone) {
if ((string)$vtimezone->TZID === $tzid) {
// Some clients add 'X-LIC-LOCATION' with the olson name.
if (isset($vtimezone->{'X-LIC-LOCATION'})) {
try {
return new DateTimeZone($vtimezone->{'X-LIC-LOCATION'});
} catch (\Exception $e) {
}
}
// Microsoft may add a magic number, which we also have an
// answer for.
if (isset($vtimezone->{'X-MICROSOFT-CDO-TZID'})) {
if (isset(self::$microsoftExchangeMap[(int)$vtimezone->{'X-MICROSOFT-CDO-TZID'}->value])) {
return new DateTimeZone(self::$microsoftExchangeMap[(int)$vtimezone->{'X-MICROSOFT-CDO-TZID'}->value]);
}
}
}
}
}
// If we got all the way here, we default to UTC.
return new DateTimeZone(date_default_timezone_get());
}
}

View file

@ -1,24 +0,0 @@
<?php
/**
* This class contains the version number for the VObject package
*
* @package Sabre
* @subpackage VObject
* @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
* @author Evert Pot (http://www.rooftopsolutions.nl/)
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
*/
class Sabre_VObject_Version {
/**
* Full version number
*/
const VERSION = '1.3.4';
/**
* Stability : alpha, beta, stable
*/
const STABILITY = 'stable';
}

View file

@ -1,39 +0,0 @@
<?php
/**
* Sabre_VObject includes file
*
* Including this file will automatically include all files from the VObject
* package.
*
* This often allows faster loadtimes, as autoload-speed is often quite slow.
*
* @package Sabre
* @subpackage VObject
* @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
* @author Evert Pot (http://www.rooftopsolutions.nl/)
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
*/
// Begin includes
include __DIR__ . '/DateTimeParser.php';
include __DIR__ . '/ElementList.php';
include __DIR__ . '/FreeBusyGenerator.php';
include __DIR__ . '/Node.php';
include __DIR__ . '/Parameter.php';
include __DIR__ . '/ParseException.php';
include __DIR__ . '/Reader.php';
include __DIR__ . '/RecurrenceIterator.php';
include __DIR__ . '/TimeZoneUtil.php';
include __DIR__ . '/Version.php';
include __DIR__ . '/Element.php';
include __DIR__ . '/Property.php';
include __DIR__ . '/Component.php';
include __DIR__ . '/Property/DateTime.php';
include __DIR__ . '/Property/MultiDateTime.php';
include __DIR__ . '/Component/VAlarm.php';
include __DIR__ . '/Component/VCalendar.php';
include __DIR__ . '/Component/VEvent.php';
include __DIR__ . '/Component/VJournal.php';
include __DIR__ . '/Component/VTodo.php';
// End includes