作者:sebbie4
项目:casebo
/**
* The deserialize method is called during xml parsing.
*
* This method is called statictly, this is because in theory this method
* may be used as a type of constructor, or factory method.
*
* Often you want to return an instance of the current class, but you are
* free to return other data as well.
*
* You are responsible for advancing the reader to the next element. Not
* doing anything will result in a never-ending loop.
*
* If you just want to skip parsing for this element altogether, you can
* just call $reader->next();
*
* $reader->parseInnerTree() will parse the entire sub-tree, and advance to
* the next element.
*
* @param Reader $reader
* @return mixed
*/
static function xmlDeserialize(Reader $reader)
{
$timeRange = '{' . Plugin::NS_CALDAV . '}time-range';
$start = null;
$end = null;
foreach ((array) $reader->parseInnerTree([]) as $elem) {
if ($elem['name'] !== $timeRange) {
continue;
}
$start = empty($elem['attributes']['start']) ?: $elem['attributes']['start'];
$end = empty($elem['attributes']['end']) ?: $elem['attributes']['end'];
}
if (!$start && !$end) {
throw new BadRequest('The freebusy report must have a time-range element');
}
if ($start) {
$start = DateTimeParser::parseDateTime($start);
}
if ($end) {
$end = DateTimeParser::parseDateTime($end);
}
$result = new self();
$result->start = $start;
$result->end = $end;
return $result;
}
作者:BlaBlaNe
项目:hubzill
/**
* The deserialize method is called during xml parsing.
*
* This method is called statictly, this is because in theory this method
* may be used as a type of constructor, or factory method.
*
* Often you want to return an instance of the current class, but you are
* free to return other data as well.
*
* You are responsible for advancing the reader to the next element. Not
* doing anything will result in a never-ending loop.
*
* If you just want to skip parsing for this element altogether, you can
* just call $reader->next();
*
* $reader->parseInnerTree() will parse the entire sub-tree, and advance to
* the next element.
*
* @param Reader $reader
* @return mixed
*/
static function xmlDeserialize(Reader $reader)
{
$result = ['name' => null, 'is-not-defined' => false, 'param-filters' => [], 'text-match' => null, 'time-range' => false];
$att = $reader->parseAttributes();
$result['name'] = $att['name'];
$elems = $reader->parseInnerTree();
if (is_array($elems)) {
foreach ($elems as $elem) {
switch ($elem['name']) {
case '{' . Plugin::NS_CALDAV . '}param-filter':
$result['param-filters'][] = $elem['value'];
break;
case '{' . Plugin::NS_CALDAV . '}is-not-defined':
$result['is-not-defined'] = true;
break;
case '{' . Plugin::NS_CALDAV . '}time-range':
$result['time-range'] = ['start' => isset($elem['attributes']['start']) ? DateTimeParser::parseDateTime($elem['attributes']['start']) : null, 'end' => isset($elem['attributes']['end']) ? DateTimeParser::parseDateTime($elem['attributes']['end']) : null];
if ($result['time-range']['start'] && $result['time-range']['end'] && $result['time-range']['end'] <= $result['time-range']['start']) {
throw new BadRequest('The end-date must be larger than the start-date');
}
break;
case '{' . Plugin::NS_CALDAV . '}text-match':
$result['text-match'] = ['negate-condition' => isset($elem['attributes']['negate-condition']) && $elem['attributes']['negate-condition'] === 'yes', 'collation' => isset($elem['attributes']['collation']) ? $elem['attributes']['collation'] : 'i;ascii-casemap', 'value' => $elem['value']];
break;
}
}
}
return $result;
}
作者:BlaBlaNe
项目:hubzill
/**
* The deserialize method is called during xml parsing.
*
* This method is called statictly, this is because in theory this method
* may be used as a type of constructor, or factory method.
*
* Often you want to return an instance of the current class, but you are
* free to return other data as well.
*
* You are responsible for advancing the reader to the next element. Not
* doing anything will result in a never-ending loop.
*
* If you just want to skip parsing for this element altogether, you can
* just call $reader->next();
*
* $reader->parseInnerTree() will parse the entire sub-tree, and advance to
* the next element.
*
* @param Reader $reader
* @return mixed
*/
static function xmlDeserialize(Reader $reader)
{
$result = ['name' => null, 'is-not-defined' => false, 'comp-filters' => [], 'prop-filters' => [], 'time-range' => false];
$att = $reader->parseAttributes();
$result['name'] = $att['name'];
$elems = $reader->parseInnerTree();
if (is_array($elems)) {
foreach ($elems as $elem) {
switch ($elem['name']) {
case '{' . Plugin::NS_CALDAV . '}comp-filter':
$result['comp-filters'][] = $elem['value'];
break;
case '{' . Plugin::NS_CALDAV . '}prop-filter':
$result['prop-filters'][] = $elem['value'];
break;
case '{' . Plugin::NS_CALDAV . '}is-not-defined':
$result['is-not-defined'] = true;
break;
case '{' . Plugin::NS_CALDAV . '}time-range':
if ($result['name'] === 'VCALENDAR') {
throw new BadRequest('You cannot add time-range filters on the VCALENDAR component');
}
$result['time-range'] = ['start' => isset($elem['attributes']['start']) ? DateTimeParser::parseDateTime($elem['attributes']['start']) : null, 'end' => isset($elem['attributes']['end']) ? DateTimeParser::parseDateTime($elem['attributes']['end']) : null];
if ($result['time-range']['start'] && $result['time-range']['end'] && $result['time-range']['end'] <= $result['time-range']['start']) {
throw new BadRequest('The end-date must be larger than the start-date');
}
break;
}
}
}
return $result;
}
作者:floffel0
项目:pydio-cor
/**
* 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 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)) {
// The DTEND property is considered non inclusive. So for a 3 day
// event in july, dtstart and dtend would have to be July 1st and
// July 4th respectively.
//
// See:
// http://tools.ietf.org/html/rfc5545#page-54
$effectiveEnd = $this->DTEND->getDateTime();
} elseif (isset($this->DURATION)) {
$effectiveEnd = clone $effectiveStart;
$effectiveEnd->add(VObject\DateTimeParser::parseDuration($this->DURATION));
} elseif ($this->DTSTART->getDateType() == VObject\Property\DateTime::DATE) {
$effectiveEnd = clone $effectiveStart;
$effectiveEnd->modify('+1 day');
} else {
$effectiveEnd = clone $effectiveStart;
}
return $start <= $effectiveEnd && $end > $effectiveStart;
}
作者:LobbyO
项目:serve
/**
* 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) ? 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;
}
作者:drognise
项目:Portfolio-Sit
/**
* Checks based on the contained FREEBUSY information, if a timeslot is
* available.
*
* @param DateTime $start
* @param Datetime $end
* @return bool
*/
public function isFree(\DateTime $start, \Datetime $end)
{
foreach ($this->select('FREEBUSY') as $freebusy) {
// We are only interested in FBTYPE=BUSY (the default),
// FBTYPE=BUSY-TENTATIVE or FBTYPE=BUSY-UNAVAILABLE.
if (isset($freebusy['FBTYPE']) && strtoupper(substr((string) $freebusy['FBTYPE'], 0, 4)) !== 'BUSY') {
continue;
}
// The freebusy component can hold more than 1 value, separated by
// commas.
$periods = explode(',', (string) $freebusy);
foreach ($periods as $period) {
// Every period is formatted as [start]/[end]. The start is an
// absolute UTC time, the end may be an absolute UTC time, or
// duration (relative) value.
list($busyStart, $busyEnd) = explode('/', $period);
$busyStart = VObject\DateTimeParser::parse($busyStart);
$busyEnd = VObject\DateTimeParser::parse($busyEnd);
if ($busyEnd instanceof \DateInterval) {
$tmp = clone $busyStart;
$tmp->add($busyEnd);
$busyEnd = $tmp;
}
if ($start < $busyEnd && $end > $busyStart) {
return false;
}
}
}
return true;
}
作者:drognise
项目:Portfolio-Sit
/**
* Goes on to the next iteration.
*
* @return void
*/
public function next()
{
$this->counter++;
if (!$this->valid()) {
return;
}
$this->currentDate = DateTimeParser::parse($this->dates[$this->counter - 1]);
}
作者:linagor
项目:sabre-vobjec
/**
* Goes on to the next iteration.
*
* @return void
*/
function next()
{
$this->counter++;
if (!$this->valid()) {
return;
}
$this->currentDate = DateTimeParser::parse($this->dates[$this->counter - 1], $this->startDate->getTimezone());
}
作者:ddolbi
项目:sabre-vobjec
/**
* Returns the 'effective start' and 'effective end' of this VAVAILABILITY
* component.
*
* We use the DTSTART and DTEND or DURATION to determine this.
*
* The returned value is an array containing DateTimeImmutable instances.
* If either the start or end is 'unbounded' its value will be null
* instead.
*
* @return array
*/
function getEffectiveStartEnd()
{
$effectiveStart = $this->DTSTART->getDateTime();
if (isset($this->DTEND)) {
$effectiveEnd = $this->DTEND->getDateTime();
} else {
$effectiveEnd = $effectiveStart->add(VObject\DateTimeParser::parseDuration($this->DURATION));
}
return [$effectiveStart, $effectiveEnd];
}
作者:hiaio-platform-medica
项目:rainloop-webmai
/**
* Returns the value, in the format it should be encoded for json.
*
* This method must always return an array.
*
* @return array
*/
public function getJsonValue()
{
$parts = DateTimeParser::parseVCardDateTime($this->getValue());
$dateStr = $parts['year'] . '-' . $parts['month'] . '-' . $parts['date'] . 'T' . $parts['hour'] . ':' . $parts['minute'] . ':' . $parts['second'];
// Timezone
if (!is_null($parts['timezone'])) {
$dateStr .= $parts['timezone'];
}
return array($dateStr);
}
作者:zamentu
项目:roundcube_yn
/**
* Returns the value, in the format it should be encoded for json.
*
* This method must always return an array.
*
* @return array
*/
public function getJsonValue()
{
$return = array();
foreach ($this->getParts() as $item) {
list($start, $end) = explode('/', $item, 2);
$start = DateTimeParser::parseDateTime($start);
// This is a duration value.
if ($end[0] === 'P') {
$return[] = array($start->format('Y-m-d\\TH:i:s'), $end);
} else {
$end = DateTimeParser::parseDateTime($end);
$return[] = array($start->format('Y-m-d\\TH:i:s'), $end->format('Y-m-d\\TH:i:s'));
}
}
return $return;
}
作者:BlaBlaNe
项目:hubzill
/**
* The deserialize method is called during xml parsing.
*
* This method is called statictly, this is because in theory this method
* may be used as a type of constructor, or factory method.
*
* Often you want to return an instance of the current class, but you are
* free to return other data as well.
*
* You are responsible for advancing the reader to the next element. Not
* doing anything will result in a never-ending loop.
*
* If you just want to skip parsing for this element altogether, you can
* just call $reader->next();
*
* $reader->parseInnerTree() will parse the entire sub-tree, and advance to
* the next element.
*
* @param Reader $reader
* @return mixed
*/
static function xmlDeserialize(Reader $reader)
{
$result = ['contentType' => $reader->getAttribute('content-type') ?: 'text/calendar', 'version' => $reader->getAttribute('version') ?: '2.0'];
$elems = (array) $reader->parseInnerTree();
foreach ($elems as $elem) {
switch ($elem['name']) {
case '{' . Plugin::NS_CALDAV . '}expand':
$result['expand'] = ['start' => isset($elem['attributes']['start']) ? DateTimeParser::parseDateTime($elem['attributes']['start']) : null, 'end' => isset($elem['attributes']['end']) ? DateTimeParser::parseDateTime($elem['attributes']['end']) : null];
if (!$result['expand']['start'] || !$result['expand']['end']) {
throw new BadRequest('The "start" and "end" attributes are required when expanding calendar-data');
}
if ($result['expand']['end'] <= $result['expand']['start']) {
throw new BadRequest('The end-date must be larger than the start-date when expanding calendar-data');
}
break;
}
}
return $result;
}
作者:omusic
项目:isle-web-framewor
/**
* 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 = 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;
}
}
作者:ddolbi
项目:sabre-vobjec
/**
* Returns the value, in the format it should be encoded for json.
*
* This method must always return an array.
*
* @return array
*/
function getJsonValue()
{
$parts = DateTimeParser::parseVCardTime($this->getValue());
$timeStr = '';
// Hour
if (!is_null($parts['hour'])) {
$timeStr .= $parts['hour'];
if (!is_null($parts['minute'])) {
$timeStr .= ':';
}
} else {
// We know either minute or second _must_ be set, so we insert a
// dash for an empty value.
$timeStr .= '-';
}
// Minute
if (!is_null($parts['minute'])) {
$timeStr .= $parts['minute'];
if (!is_null($parts['second'])) {
$timeStr .= ':';
}
} else {
if (isset($parts['second'])) {
// Dash for empty minute
$timeStr .= '-';
}
}
// Second
if (!is_null($parts['second'])) {
$timeStr .= $parts['second'];
}
// Timezone
if (!is_null($parts['timezone'])) {
if ($parts['timezone'] === 'Z') {
$timeStr .= 'Z';
} else {
$timeStr .= preg_replace('/([0-9]{2})([0-9]{2})$/', '$1:$2', $parts['timezone']);
}
}
return [$timeStr];
}
作者:cedta
项目:sabre-vobjec
/**
* 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 DateTimeInterface $start
* @param DateTimeInterface $end
*
* @return bool
*/
function isInTimeRange(DateTimeInterface $start, DateTimeInterface $end)
{
if ($this->RRULE) {
try {
$it = new EventIterator($this, null, $start->getTimezone());
} catch (NoInstancesException $e) {
// If we've catched this exception, there are no instances
// for the event that fall into the specified time-range.
return false;
}
$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;
}
if (!isset($this->DTSTART)) {
return false;
}
$effectiveStart = $this->DTSTART->getDateTime($start->getTimezone());
if (isset($this->DTEND)) {
// The DTEND property is considered non inclusive. So for a 3 day
// event in july, dtstart and dtend would have to be July 1st and
// July 4th respectively.
//
// See:
// http://tools.ietf.org/html/rfc5545#page-54
$effectiveEnd = $this->DTEND->getDateTime($end->getTimezone());
} elseif (isset($this->DURATION)) {
$effectiveEnd = $effectiveStart->add(VObject\DateTimeParser::parseDuration($this->DURATION));
} elseif (!$this->DTSTART->hasTime()) {
$effectiveEnd = $effectiveStart->modify('+1 day');
} else {
$effectiveEnd = $effectiveStart;
}
return $start < $effectiveEnd && $end > $effectiveStart;
}
作者:zamentu
项目:roundcube_yn
/**
* Returns the value, in the format it should be encoded for json.
*
* This method must always return an array.
*
* @return array
*/
public function getJsonValue()
{
$parts = DateTimeParser::parseVCardTime($this->getValue());
$timeStr = '';
// Hour
if (!is_null($parts['hour'])) {
$timeStr .= $parts['hour'];
if (!is_null($parts['minute'])) {
$timeStr .= ':';
}
} else {
// We know either minute or second _must_ be set, so we insert a
// dash for an empty value.
$timeStr .= '-';
}
// Minute
if (!is_null($parts['minute'])) {
$timeStr .= $parts['minute'];
if (!is_null($parts['second'])) {
$timeStr .= ':';
}
} else {
if (isset($parts['second'])) {
// Dash for empty minute
$timeStr .= '-';
}
}
// Second
if (!is_null($parts['second'])) {
$timeStr .= $parts['second'];
}
// Timezone
if (!is_null($parts['timezone'])) {
$timeStr .= $parts['timezone'];
}
return array($timeStr);
}
作者:Henn
项目:sabre-vobjec
protected function assertDateAndOrTimeEqualsTo($date, $parts)
{
$this->assertSame(DateTimeParser::parseVCardDateAndOrTime($date), array_merge(['year' => null, 'month' => null, 'date' => null, 'hour' => null, 'minute' => null, 'second' => null, 'timezone' => null], $parts));
}
作者:sbambac
项目:task
public static function arrayForJSON($id, $vtodo, $user_timezone, $calendarId)
{
$task = array('id' => $id);
$task['calendarid'] = $calendarId;
$task['type'] = 'task';
$task['name'] = (string) $vtodo->SUMMARY;
$task['created'] = (string) $vtodo->CREATED;
$task['note'] = (string) $vtodo->DESCRIPTION;
$task['location'] = (string) $vtodo->LOCATION;
$categories = $vtodo->CATEGORIES;
if ($categories) {
$task['categories'] = $categories->getParts();
}
$start = $vtodo->DTSTART;
if ($start) {
try {
$start = $start->getDateTime();
$start->setTimezone(new \DateTimeZone($user_timezone));
$task['start'] = $start->format('Ymd\\THis');
} catch (\Exception $e) {
$task['start'] = null;
\OCP\Util::writeLog('tasks', $e->getMessage(), \OCP\Util::ERROR);
}
} else {
$task['start'] = null;
}
$due = $vtodo->DUE;
if ($due) {
try {
$due = $due->getDateTime();
$due->setTimezone(new \DateTimeZone($user_timezone));
$task['due'] = $due->format('Ymd\\THis');
} catch (\Exception $e) {
$task['due'] = null;
\OCP\Util::writeLog('tasks', $e->getMessage(), \OCP\Util::ERROR);
}
} else {
$task['due'] = null;
}
$reminder = $vtodo->VALARM;
if ($reminder) {
try {
$reminderType = $reminder->TRIGGER['VALUE']->getValue();
$reminderAction = $reminder->ACTION->getValue();
$reminderDate = null;
$reminderDuration = null;
if ($reminderType == 'DATE-TIME') {
$reminderDate = $reminder->TRIGGER->getDateTime();
$reminderDate->setTimezone(new \DateTimeZone($user_timezone));
$reminderDate = $reminderDate->format('Ymd\\THis');
} elseif ($reminderType == 'DURATION' && ($start || $due)) {
$parsed = VObject\DateTimeParser::parseDuration($reminder->TRIGGER, true);
// Calculate the reminder date from duration and start date
$related = null;
if (is_object($reminder->TRIGGER['RELATED'])) {
$related = $reminder->TRIGGER['RELATED']->getValue();
if ($related == 'END' && $due) {
$reminderDate = $due->modify($parsed)->format('Ymd\\THis');
} else {
throw new \Exception('Reminder duration related to not available date.');
}
} elseif ($start) {
$reminderDate = $start->modify($parsed)->format('Ymd\\THis');
} else {
throw new \Exception('Reminder duration related to not available date.');
}
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)?)?$/', $reminder->TRIGGER, $matches);
$invert = false;
if ($matches['plusminus'] === '-') {
$invert = true;
}
$parts = array('week', 'day', 'hour', 'minute', 'second');
$reminderDuration = array('token' => null);
foreach ($parts as $part) {
$matches[$part] = isset($matches[$part]) && $matches[$part] ? (int) $matches[$part] : 0;
$reminderDuration[$part] = $matches[$part];
if ($matches[$part] && !$reminderDuration['token']) {
$reminderDuration['token'] = $part;
}
}
if ($reminderDuration['token'] == null) {
$reminderDuration['token'] = $parts[0];
}
$reminderDuration['params'] = array('id' => (int) $invert . (int) ($related == 'END'), 'related' => $related ? $related : 'START', 'invert' => $invert);
} else {
$reminderDate = null;
$reminderDuration = null;
}
$task['reminder'] = array('type' => $reminderType, 'action' => $reminderAction, 'date' => $reminderDate, 'duration' => $reminderDuration);
} catch (\Exception $e) {
$task['reminder'] = null;
\OCP\Util::writeLog('tasks', $e->getMessage(), \OCP\Util::ERROR);
}
} else {
$task['reminder'] = null;
}
$priority = $vtodo->PRIORITY;
if (isset($priority)) {
$priority = (10 - $priority->getValue()) % 10;
$task['priority'] = (string) $priority;
//.........这里部分代码省略.........
作者:sksre
项目:Jorani_ne
/**
* Parse an event update for an attendee.
*
* This function figures out if we need to send a reply to an organizer.
*
* @param VCalendar $calendar
* @param array $eventInfo
* @param array $oldEventInfo
* @param string $attendee
* @return Message[]
*/
protected function parseEventForAttendee(VCalendar $calendar, array $eventInfo, array $oldEventInfo, $attendee)
{
if ($this->scheduleAgentServerRules && $eventInfo['organizerScheduleAgent'] === 'CLIENT') {
return array();
}
// Don't bother generating messages for events that have already been
// cancelled.
if ($eventInfo['status'] === 'CANCELLED') {
return array();
}
$instances = array();
foreach ($oldEventInfo['attendees'][$attendee]['instances'] as $instance) {
$instances[$instance['id']] = array('id' => $instance['id'], 'oldstatus' => $instance['partstat'], 'newstatus' => null);
}
foreach ($eventInfo['attendees'][$attendee]['instances'] as $instance) {
if (isset($instances[$instance['id']])) {
$instances[$instance['id']]['newstatus'] = $instance['partstat'];
} else {
$instances[$instance['id']] = array('id' => $instance['id'], 'oldstatus' => null, 'newstatus' => $instance['partstat']);
}
}
// We need to also look for differences in EXDATE. If there are new
// items in EXDATE, it means that an attendee deleted instances of an
// event, which means we need to send DECLINED specifically for those
// instances.
// We only need to do that though, if the master event is not declined.
if ($instances['master']['newstatus'] !== 'DECLINED') {
foreach ($eventInfo['exdate'] as $exDate) {
if (!in_array($exDate, $oldEventInfo['exdate'])) {
if (isset($instances[$exDate])) {
$instances[$exDate]['newstatus'] = 'DECLINED';
} else {
$instances[$exDate] = array('id' => $exDate, 'oldstatus' => null, 'newstatus' => 'DECLINED');
}
}
}
}
// Gathering a few extra properties for each instance.
foreach ($instances as $recurId => $instanceInfo) {
if (isset($eventInfo['instances'][$recurId])) {
$instances[$recurId]['dtstart'] = clone $eventInfo['instances'][$recurId]->DTSTART;
} else {
$instances[$recurId]['dtstart'] = $recurId;
}
}
$message = new Message();
$message->uid = $eventInfo['uid'];
$message->method = 'REPLY';
$message->component = 'VEVENT';
$message->sequence = $eventInfo['sequence'];
$message->sender = $attendee;
$message->senderName = $eventInfo['attendees'][$attendee]['name'];
$message->recipient = $eventInfo['organizer'];
$message->recipientName = $eventInfo['organizerName'];
$icalMsg = new VCalendar();
$icalMsg->METHOD = 'REPLY';
$hasReply = false;
foreach ($instances as $instance) {
if ($instance['oldstatus'] == $instance['newstatus'] && $eventInfo['organizerForceSend'] !== 'REPLY') {
// Skip
continue;
}
$event = $icalMsg->add('VEVENT', array('UID' => $message->uid, 'SEQUENCE' => $message->sequence));
$summary = isset($calendar->VEVENT->SUMMARY) ? $calendar->VEVENT->SUMMARY->getValue() : '';
// Adding properties from the correct source instance
if (isset($eventInfo['instances'][$instance['id']])) {
$instanceObj = $eventInfo['instances'][$instance['id']];
$event->add(clone $instanceObj->DTSTART);
if (isset($instanceObj->SUMMARY)) {
$event->add('SUMMARY', $instanceObj->SUMMARY->getValue());
} elseif ($summary) {
$event->add('SUMMARY', $summary);
}
} else {
// This branch of the code is reached, when a reply is
// generated for an instance of a recurring event, through the
// fact that the instance has disappeared by showing up in
// EXDATE
$dt = DateTimeParser::parse($instance['id'], $eventInfo['timezone']);
// Treat is as a DATE field
if (strlen($instance['id']) <= 8) {
$recur = $event->add('DTSTART', $dt, array('VALUE' => 'DATE'));
} else {
$recur = $event->add('DTSTART', $dt);
}
if ($summary) {
$event->add('SUMMARY', $summary);
}
}
//.........这里部分代码省略.........
作者:floffel0
项目:pydio-cor
/**
* @depends testParseICalendarDate
* @expectedException LogicException
*/
function testParseICalendarDateBadFormat()
{
$dateTime = DateTimeParser::parseDate('20100316T141405');
}