Update Horde_Date_Recurrence with fixes from upstream

This commit is contained in:
Aleksander Machniak 2016-03-01 15:30:04 +01:00
parent 65c49e78c7
commit 494785384d
2 changed files with 80 additions and 42 deletions

View file

@ -393,8 +393,8 @@ class Horde_Date
*/ */
public static function fromDays($days) public static function fromDays($days)
{ {
if (function_exists('JDToGregorian')) { if (function_exists('jdtogregorian')) {
list($month, $day, $year) = explode('/', JDToGregorian($days)); list($month, $day, $year) = explode('/', jdtogregorian($days));
} else { } else {
$days = intval($days); $days = intval($days);

View file

@ -1,13 +1,14 @@
<?php <?php
/** /**
* This is a modified copy of Horde/Date/Recurrence.php * This is a modified copy of Horde/Date/Recurrence.php (2015-01-05)
* Pull the latest version of this file from the PEAR channel of the Horde * Pull the latest version of this file from the PEAR channel of the Horde
* project at http://pear.horde.org by installing the Horde_Date package. * project at http://pear.horde.org by installing the Horde_Date package.
*/ */
if (!class_exists('Horde_Date')) if (!class_exists('Horde_Date')) {
require_once(dirname(__FILE__) . '/Horde_Date.php'); require_once(__DIR__ . '/Horde_Date.php');
}
// minimal required implementation of Horde_Date_Translation to avoid a huge dependency nightmare // minimal required implementation of Horde_Date_Translation to avoid a huge dependency nightmare
class Horde_Date_Translation class Horde_Date_Translation
@ -20,7 +21,7 @@ class Horde_Date_Translation
/** /**
* This file contains the Horde_Date_Recurrence class and according constants. * This file contains the Horde_Date_Recurrence class and according constants.
* *
* Copyright 2007-2012 Horde LLC (http://www.horde.org/) * Copyright 2007-2015 Horde LLC (http://www.horde.org/)
* *
* See the enclosed file COPYING for license information (LGPL). If you * See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.horde.org/licenses/lgpl21. * did not receive this file, see http://www.horde.org/licenses/lgpl21.
@ -285,14 +286,19 @@ class Horde_Date_Recurrence
public function getRecurName() public function getRecurName()
{ {
switch ($this->getRecurType()) { switch ($this->getRecurType()) {
case self::RECUR_NONE: return Horde_Date_Translation::t("No recurrence"); case self::RECUR_NONE:
case self::RECUR_DAILY: return Horde_Date_Translation::t("Daily"); return Horde_Date_Translation::t("No recurrence");
case self::RECUR_WEEKLY: return Horde_Date_Translation::t("Weekly"); case self::RECUR_DAILY:
return Horde_Date_Translation::t("Daily");
case self::RECUR_WEEKLY:
return Horde_Date_Translation::t("Weekly");
case self::RECUR_MONTHLY_DATE: case self::RECUR_MONTHLY_DATE:
case self::RECUR_MONTHLY_WEEKDAY: return Horde_Date_Translation::t("Monthly"); case self::RECUR_MONTHLY_WEEKDAY:
return Horde_Date_Translation::t("Monthly");
case self::RECUR_YEARLY_DATE: case self::RECUR_YEARLY_DATE:
case self::RECUR_YEARLY_DAY: case self::RECUR_YEARLY_DAY:
case self::RECUR_YEARLY_WEEKDAY: return Horde_Date_Translation::t("Yearly"); case self::RECUR_YEARLY_WEEKDAY:
return Horde_Date_Translation::t("Yearly");
} }
} }
@ -453,6 +459,7 @@ class Horde_Date_Recurrence
$next->compareDateTime($after) >= 0) { $next->compareDateTime($after) >= 0) {
return $next; return $next;
} }
break; break;
case self::RECUR_WEEKLY: case self::RECUR_WEEKLY:
@ -482,7 +489,6 @@ class Horde_Date_Recurrence
$after_week = Horde_Date_Utils::firstDayOfWeek($week, $theYear); $after_week = Horde_Date_Utils::firstDayOfWeek($week, $theYear);
$after_week->timezone = $this->start->timezone; $after_week->timezone = $this->start->timezone;
$after_week_end = clone $after_week; $after_week_end = clone $after_week;
$after_week_end->mday += 7;
$diff = $start_week->diff($after_week); $diff = $start_week->diff($after_week);
$interval = $this->recurInterval * 7; $interval = $this->recurInterval * 7;
@ -650,6 +656,10 @@ class Horde_Date_Recurrence
$next = clone $estart; $next = clone $estart;
$next->setNthWeekday($weekday, $nth); $next->setNthWeekday($weekday, $nth);
if ($next->month != $estart->month) {
// We're already in the next month.
continue;
}
if ($next->compareDateTime($after) < 0) { if ($next->compareDateTime($after) < 0) {
// We haven't made it past $after yet, try again. // We haven't made it past $after yet, try again.
continue; continue;
@ -875,8 +885,11 @@ class Horde_Date_Recurrence
*/ */
public function addException($year, $month, $mday) public function addException($year, $month, $mday)
{ {
$key = sprintf('%04d%02d%02d', $year, $month, $mday);
if (array_search($key, $this->exceptions) === false) {
$this->exceptions[] = sprintf('%04d%02d%02d', $year, $month, $mday); $this->exceptions[] = sprintf('%04d%02d%02d', $year, $month, $mday);
} }
}
/** /**
* Deletes an exception from a recurring event. * Deletes an exception from a recurring event.
@ -1053,13 +1066,15 @@ class Horde_Date_Recurrence
if (strpos($remainder, '#') === 0) { if (strpos($remainder, '#') === 0) {
$this->setRecurCount(substr($remainder, 1)); $this->setRecurCount(substr($remainder, 1));
} else { } else {
list($year, $month, $mday) = sscanf($remainder, '%04d%02d%02d'); list($year, $month, $mday, $hour, $min, $sec, $tz) =
sscanf($remainder, '%04d%02d%02dT%02d%02d%02d%s');
$this->setRecurEnd(new Horde_Date(array('year' => $year, $this->setRecurEnd(new Horde_Date(array('year' => $year,
'month' => $month, 'month' => $month,
'mday' => $mday, 'mday' => $mday,
'hour' => 23, 'hour' => $hour,
'min' => 59, 'min' => $min,
'sec' => 59))); 'sec' => $sec),
$tz == 'Z' ? 'UTC' : $this->start->timezone));
} }
} }
} }
@ -1225,15 +1240,23 @@ class Horde_Date_Recurrence
break; break;
} }
// MUST take into account the time portion if it is present.
// See Bug: 12869 and Bug: 2813
if (isset($rdata['UNTIL'])) { if (isset($rdata['UNTIL'])) {
if (preg_match('/^(\d{4})-?(\d{2})-?(\d{2})T? ?(\d{2}):?(\d{2}):?(\d{2})(?:\.\d+)?(Z?)$/', $rdata['UNTIL'], $parts)) {
$until = new Horde_Date($rdata['UNTIL'], 'UTC');
$until->setTimezone($this->start->timezone);
} else {
list($year, $month, $mday) = sscanf($rdata['UNTIL'], list($year, $month, $mday) = sscanf($rdata['UNTIL'],
'%04d%02d%02d'); '%04d%02d%02d');
$this->setRecurEnd(new Horde_Date(array('year' => $year, $until = new Horde_Date(
array('year' => $year,
'month' => $month, 'month' => $month,
'mday' => $mday, 'mday' => $mday + 1),
'hour' => 23, $this->start->timezone
'min' => 59, );
'sec' => 59))); }
$this->setRecurEnd($until);
} }
if (isset($rdata['COUNT'])) { if (isset($rdata['COUNT'])) {
$this->setRecurCount($rdata['COUNT']); $this->setRecurCount($rdata['COUNT']);
@ -1266,16 +1289,18 @@ class Horde_Date_Recurrence
break; break;
case self::RECUR_WEEKLY: case self::RECUR_WEEKLY:
$rrule = 'FREQ=WEEKLY;INTERVAL=' . $this->recurInterval . ';BYDAY='; $rrule = 'FREQ=WEEKLY;INTERVAL=' . $this->recurInterval;
$vcaldays = array('SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA'); $vcaldays = array('SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA');
for ($i = $flag = 0; $i <= 7; ++$i) { for ($i = $flag = 0; $i <= 7; ++$i) {
if ($this->recurOnDay(pow(2, $i))) { if ($this->recurOnDay(pow(2, $i))) {
if ($flag) { if ($flag == 0) {
$rrule .= ';BYDAY=';
$flag = 1;
} else {
$rrule .= ','; $rrule .= ',';
} }
$rrule .= $vcaldays[$i]; $rrule .= $vcaldays[$i];
$flag = true;
} }
} }
break; break;
@ -1341,13 +1366,13 @@ class Horde_Date_Recurrence
} }
/** /**
* Parses the recurrence data from a hash. * Parses the recurrence data from a Kolab hash.
* *
* @param array $hash The hash to convert. * @param array $hash The hash to convert.
* *
* @return boolean True if the hash seemed valid, false otherwise. * @return boolean True if the hash seemed valid, false otherwise.
*/ */
public function fromHash($hash) public function fromKolab($hash)
{ {
$this->reset(); $this->reset();
@ -1426,7 +1451,7 @@ class Horde_Date_Recurrence
break; break;
case 'yearday': case 'yearday':
if (!isset($hash['month'])) { if (!isset($hash['daynumber'])) {
$this->setRecurType(self::RECUR_NONE); $this->setRecurType(self::RECUR_NONE);
return false; return false;
} }
@ -1537,23 +1562,31 @@ class Horde_Date_Recurrence
} }
// Exceptions. // Exceptions.
if (isset($hash['exceptions'])) { if (isset($hash['exclusion'])) {
$this->exceptions = $hash['exceptions']; foreach ($hash['exclusion'] as $exception) {
if ($exception instanceof DateTime) {
$this->exceptions[] = $exception->format('Ymd');
}
}
} }
if (isset($hash['completions'])) { if (isset($hash['complete'])) {
$this->completions = $hash['completions']; foreach ($hash['complete'] as $completion) {
if ($exception instanceof DateTime) {
$this->completions[] = $completion->format('Ymd');
}
}
} }
return true; return true;
} }
/** /**
* Export this object into a hash. * Export this object into a Kolab hash.
* *
* @return array The recurrence hash. * @return array The recurrence hash.
*/ */
public function toHash() public function toKolab()
{ {
if ($this->getRecurType() == self::RECUR_NONE) { if ($this->getRecurType() == self::RECUR_NONE) {
return array(); return array();
@ -1651,15 +1684,20 @@ class Horde_Date_Recurrence
} elseif ($this->hasRecurEnd()) { } elseif ($this->hasRecurEnd()) {
$date = $this->getRecurEnd(); $date = $this->getRecurEnd();
$hash['range-type'] = 'date'; $hash['range-type'] = 'date';
$hash['range'] = $date->datestamp(); $hash['range'] = $date->toDateTime();
} else { } else {
$hash['range-type'] = 'none'; $hash['range-type'] = 'none';
$hash['range'] = ''; $hash['range'] = '';
} }
// Recurrence exceptions // Recurrence exceptions
$hash['exceptions'] = $this->exceptions; $hash['exclusion'] = $hash['complete'] = array();
$hash['completions'] = $this->completions; foreach ($this->exceptions as $exception) {
$hash['exclusion'][] = new DateTime($exception);
}
foreach ($this->completions as $completionexception) {
$hash['complete'][] = new DateTime($completionexception);
}
return $hash; return $hash;
} }