default services conflit ?
This commit is contained in:
48
old.vendor/simshaun/recurr/src/Recurr/DateExclusion.php
Normal file
48
old.vendor/simshaun/recurr/src/Recurr/DateExclusion.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2014 Shaun Simmons
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Recurr;
|
||||
|
||||
/**
|
||||
* Class DateExclusion is a container for a single \DateTimeInterface.
|
||||
*
|
||||
* The purpose of this class is to hold a flag that specifies whether
|
||||
* or not the \DateTimeInterface was created from a DATE only, or with a
|
||||
* DATETIME.
|
||||
*
|
||||
* It also tracks whether or not the exclusion is explicitly set to UTC.
|
||||
*
|
||||
* @package Recurr
|
||||
* @author Shaun Simmons <shaun@envysphere.com>
|
||||
*/
|
||||
class DateExclusion
|
||||
{
|
||||
/** @var \DateTimeInterface */
|
||||
public $date;
|
||||
|
||||
/** @var bool Day of year */
|
||||
public $hasTime;
|
||||
|
||||
/** @var bool */
|
||||
public $isUtcExplicit;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param \DateTimeInterface $date
|
||||
* @param bool $hasTime
|
||||
* @param bool $isUtcExplicit
|
||||
*/
|
||||
public function __construct(\DateTimeInterface $date, $hasTime = true, $isUtcExplicit = false)
|
||||
{
|
||||
$this->date = $date;
|
||||
$this->hasTime = $hasTime;
|
||||
$this->isUtcExplicit = $isUtcExplicit;
|
||||
}
|
||||
}
|
||||
48
old.vendor/simshaun/recurr/src/Recurr/DateInclusion.php
Normal file
48
old.vendor/simshaun/recurr/src/Recurr/DateInclusion.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2015 Shaun Simmons
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Recurr;
|
||||
|
||||
/**
|
||||
* Class DateInclusion is a container for a single \DateTimeInterface.
|
||||
*
|
||||
* The purpose of this class is to hold a flag that specifies whether
|
||||
* or not the \DateTimeInterface was created from a DATE only, or with a
|
||||
* DATETIME.
|
||||
*
|
||||
* It also tracks whether or not the inclusion is explicitly set to UTC.
|
||||
*
|
||||
* @package Recurr
|
||||
* @author Shaun Simmons <shaun@envysphere.com>
|
||||
*/
|
||||
class DateInclusion
|
||||
{
|
||||
/** @var \DateTimeInterface */
|
||||
public $date;
|
||||
|
||||
/** @var bool Day of year */
|
||||
public $hasTime;
|
||||
|
||||
/** @var bool */
|
||||
public $isUtcExplicit;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param \DateTimeInterface $date
|
||||
* @param bool $hasTime
|
||||
* @param bool $isUtcExplicit
|
||||
*/
|
||||
public function __construct(\DateTimeInterface $date, $hasTime = true, $isUtcExplicit = false)
|
||||
{
|
||||
$this->date = $date;
|
||||
$this->hasTime = $hasTime;
|
||||
$this->isUtcExplicit = $isUtcExplicit;
|
||||
}
|
||||
}
|
||||
73
old.vendor/simshaun/recurr/src/Recurr/DateInfo.php
Normal file
73
old.vendor/simshaun/recurr/src/Recurr/DateInfo.php
Normal file
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2013 Shaun Simmons
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* Based on rrule.js
|
||||
* Copyright 2010, Jakub Roztocil and Lars Schoning
|
||||
* https://github.com/jkbr/rrule/blob/master/LICENCE
|
||||
*/
|
||||
|
||||
namespace Recurr;
|
||||
|
||||
/**
|
||||
* Class DateInfo is responsible for holding information based on a particular
|
||||
* date that is applicable to a Rule.
|
||||
*
|
||||
* @package Recurr
|
||||
* @author Shaun Simmons <shaun@envysphere.com>
|
||||
*/
|
||||
class DateInfo
|
||||
{
|
||||
/** @var \DateTime */
|
||||
public $dt;
|
||||
|
||||
/**
|
||||
* @var int Number of days in the month.
|
||||
*/
|
||||
public $monthLength;
|
||||
|
||||
/**
|
||||
* @var int Number of days in the year (365 normally, 366 on leap years)
|
||||
*/
|
||||
public $yearLength;
|
||||
|
||||
/**
|
||||
* @var int Number of days in the next year (365 normally, 366 on leap years)
|
||||
*/
|
||||
public $nextYearLength;
|
||||
|
||||
/**
|
||||
* @var array Day of year of last day of each month.
|
||||
*/
|
||||
public $mRanges;
|
||||
|
||||
/** @var int Day of week */
|
||||
public $dayOfWeek;
|
||||
|
||||
/** @var int Day of week of the year's first day */
|
||||
public $dayOfWeekYearDay1;
|
||||
|
||||
/**
|
||||
* @var array Month number for each day of the year.
|
||||
*/
|
||||
public $mMask;
|
||||
|
||||
/**
|
||||
* @var array Month-daynumber for each day of the year.
|
||||
*/
|
||||
public $mDayMask;
|
||||
|
||||
/**
|
||||
* @var array Month-daynumber for each day of the year (in reverse).
|
||||
*/
|
||||
public $mDayMaskNeg;
|
||||
|
||||
/**
|
||||
* @var array Day of week (0-6) for each day of the year, 0 being Monday
|
||||
*/
|
||||
public $wDayMask;
|
||||
}
|
||||
571
old.vendor/simshaun/recurr/src/Recurr/DateUtil.php
Normal file
571
old.vendor/simshaun/recurr/src/Recurr/DateUtil.php
Normal file
@@ -0,0 +1,571 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2013 Shaun Simmons
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* Based on rrule.js
|
||||
* Copyright 2010, Jakub Roztocil and Lars Schoning
|
||||
* https://github.com/jkbr/rrule/blob/master/LICENCE
|
||||
*
|
||||
* Based on python-dateutil - Extensions to the standard Python datetime module.
|
||||
* Copyright (c) 2003-2011 - Gustavo Niemeyer <gustavo@niemeyer.net>
|
||||
* Copyright (c) 2012 - Tomi Pieviläinen <tomi.pievilainen@iki.fi>
|
||||
*/
|
||||
|
||||
namespace Recurr;
|
||||
|
||||
/**
|
||||
* Class DateUtil is responsible for providing utilities applicable to Rules.
|
||||
*
|
||||
* @package Recurr
|
||||
* @author Shaun Simmons <shaun@envysphere.com>
|
||||
*/
|
||||
class DateUtil
|
||||
{
|
||||
public static $leapBug = null;
|
||||
|
||||
public static $monthEndDoY366 = array(
|
||||
0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366
|
||||
);
|
||||
|
||||
public static $monthEndDoY365 = array(
|
||||
0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365
|
||||
);
|
||||
|
||||
public static $wDayMask = array(
|
||||
0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6,
|
||||
0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6,
|
||||
0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6,
|
||||
0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6,
|
||||
0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6,
|
||||
0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6,
|
||||
0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6,
|
||||
0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6,
|
||||
0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6,
|
||||
0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6,
|
||||
0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6,
|
||||
0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6,
|
||||
0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6,
|
||||
0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6,
|
||||
0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6,
|
||||
0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6,
|
||||
0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6,
|
||||
0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6,
|
||||
0, 1, 2, 3, 4, 5, 6,
|
||||
);
|
||||
|
||||
/**
|
||||
* Get an object containing info for a particular date
|
||||
*
|
||||
* @param \DateTimeInterface $dt
|
||||
*
|
||||
* @return DateInfo
|
||||
*/
|
||||
public static function getDateInfo(\DateTimeInterface $dt)
|
||||
{
|
||||
$i = new DateInfo();
|
||||
$i->dt = $dt;
|
||||
$i->dayOfWeek = self::getDayOfWeek($dt);
|
||||
$i->monthLength = $dt->format('t');
|
||||
$i->yearLength = self::getYearLength($dt);
|
||||
|
||||
$i->mMask = self::getMonthMask($dt);
|
||||
$i->mDayMask = self::getMonthDaysMask($dt);
|
||||
$i->mDayMaskNeg = self::getMonthDaysMask($dt, true);
|
||||
|
||||
if ($i->yearLength == 365) {
|
||||
$i->mRanges = self::$monthEndDoY365;
|
||||
} else {
|
||||
$i->mRanges = self::$monthEndDoY366;
|
||||
}
|
||||
|
||||
$tmpDt = clone $dt;
|
||||
$tmpDt = $tmpDt->setDate($dt->format('Y') + 1, 1, 1);
|
||||
$i->nextYearLength = self::getYearLength($tmpDt);
|
||||
|
||||
$tmpDt = clone $dt;
|
||||
$tmpDt = $tmpDt->setDate($dt->format('Y'), 1, 1);
|
||||
$i->dayOfWeekYearDay1 = self::getDayOfWeek($tmpDt);
|
||||
|
||||
$i->wDayMask = array_slice(
|
||||
self::$wDayMask,
|
||||
$i->dayOfWeekYearDay1
|
||||
);
|
||||
|
||||
return $i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of DOY (Day of Year) for each day in a particular week.
|
||||
*
|
||||
* @param \DateTimeInterface $dt
|
||||
* @param \DateTimeInterface $start
|
||||
* @param null|Rule $rule
|
||||
* @param null|DateInfo $dtInfo
|
||||
*
|
||||
* @return DaySet
|
||||
*/
|
||||
public static function getDaySetOfWeek(
|
||||
\DateTimeInterface $dt,
|
||||
\DateTimeInterface $start,
|
||||
Rule $rule = null,
|
||||
DateInfo $dtInfo = null
|
||||
)
|
||||
{
|
||||
$start = clone $dt;
|
||||
$start = $start->setDate($start->format('Y'), 1, 1);
|
||||
|
||||
$diff = $dt->diff($start);
|
||||
$start = $diff->days;
|
||||
|
||||
$set = array();
|
||||
for ($i = $start, $k = 0; $k < 7; $k++) {
|
||||
$set[] = $i;
|
||||
++$i;
|
||||
|
||||
if (null !== $dtInfo && null !== $rule && $dtInfo->wDayMask[$i] == $rule->getWeekStartAsNum()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$obj = new DaySet($set, $start, $i);
|
||||
|
||||
return $obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Rule $rule
|
||||
* @param \DateTimeInterface $dt
|
||||
* @param DateInfo $dtInfo
|
||||
* @param \DateTimeInterface $start
|
||||
*
|
||||
* @return DaySet
|
||||
*/
|
||||
public static function getDaySet(Rule $rule, \DateTimeInterface $dt, DateInfo $dtInfo, $start)
|
||||
{
|
||||
switch ($rule->getFreq()) {
|
||||
case Frequency::SECONDLY:
|
||||
return self::getDaySetOfDay($dt, $start, $rule, $dtInfo);
|
||||
break;
|
||||
case Frequency::MINUTELY:
|
||||
return self::getDaySetOfDay($dt, $start, $rule, $dtInfo);
|
||||
break;
|
||||
case Frequency::HOURLY:
|
||||
return self::getDaySetOfDay($dt, $start, $rule, $dtInfo);
|
||||
break;
|
||||
case Frequency::DAILY:
|
||||
return self::getDaySetOfDay($dt, $start, $rule, $dtInfo);
|
||||
break;
|
||||
case Frequency::WEEKLY:
|
||||
return self::getDaySetOfWeek($dt, $start, $rule, $dtInfo);
|
||||
case Frequency::MONTHLY:
|
||||
return self::getDaySetOfMonth($dt, $start, $rule, $dtInfo);
|
||||
case Frequency::YEARLY:
|
||||
return self::getDaySetOfYear($dt, $start, $rule, $dtInfo);
|
||||
}
|
||||
|
||||
throw new \RuntimeException('Invalid freq.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of DOY (Day of Year) for each day in a particular year.
|
||||
*
|
||||
* @param \DateTimeInterface $dt The datetime
|
||||
*
|
||||
* @return DaySet
|
||||
*/
|
||||
public static function getDaySetOfYear(\DateTimeInterface $dt)
|
||||
{
|
||||
$yearLen = self::getYearLength($dt);
|
||||
$set = range(0, $yearLen - 1);
|
||||
|
||||
return new DaySet($set, 0, $yearLen);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of DOY (Day of Year) for each day in a particular month.
|
||||
*
|
||||
* @param \DateTimeInterface $dt The datetime
|
||||
*
|
||||
* @return DaySet
|
||||
*/
|
||||
public static function getDaySetOfMonth(\DateTimeInterface $dt)
|
||||
{
|
||||
$dateInfo = self::getDateInfo($dt);
|
||||
$monthNum = $dt->format('n');
|
||||
|
||||
$start = $dateInfo->mRanges[$monthNum - 1];
|
||||
$end = $dateInfo->mRanges[$monthNum];
|
||||
|
||||
$days = range(0, $dt->format('t') - 1);
|
||||
$set = range($start, $end - 1);
|
||||
$set = array_combine($days, $set);
|
||||
$obj = new DaySet($set, $start, $end - 1);
|
||||
|
||||
return $obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of DOY (Day of Year) for each day in a particular month.
|
||||
*
|
||||
* @param \DateTimeInterface $dt The datetime
|
||||
*
|
||||
* @return DaySet
|
||||
*/
|
||||
public static function getDaySetOfDay(\DateTimeInterface $dt)
|
||||
{
|
||||
$dayOfYear = $dt->format('z');
|
||||
|
||||
if (self::isLeapYearDate($dt) && self::hasLeapYearBug() && $dt->format('nj') > 229) {
|
||||
$dayOfYear -= 1;
|
||||
}
|
||||
|
||||
$start = $dayOfYear;
|
||||
$end = $dayOfYear;
|
||||
|
||||
$set = range($start, $end);
|
||||
$obj = new DaySet($set, $start, $end + 1);
|
||||
|
||||
return $obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Rule $rule
|
||||
* @param \DateTimeInterface $dt
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getTimeSetOfHour(Rule $rule, \DateTimeInterface $dt)
|
||||
{
|
||||
$set = array();
|
||||
|
||||
$hour = $dt->format('G');
|
||||
$byMinute = $rule->getByMinute();
|
||||
$bySecond = $rule->getBySecond();
|
||||
|
||||
if (empty($byMinute)) {
|
||||
$byMinute = array($dt->format('i'));
|
||||
}
|
||||
|
||||
if (empty($bySecond)) {
|
||||
$bySecond = array($dt->format('s'));
|
||||
}
|
||||
|
||||
foreach ($byMinute as $minute) {
|
||||
foreach ($bySecond as $second) {
|
||||
$set[] = new Time($hour, $minute, $second);
|
||||
}
|
||||
}
|
||||
|
||||
return $set;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Rule $rule
|
||||
* @param \DateTimeInterface $dt
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getTimeSetOfMinute(Rule $rule, \DateTimeInterface $dt)
|
||||
{
|
||||
$set = array();
|
||||
|
||||
$hour = $dt->format('G');
|
||||
$minute = $dt->format('i');
|
||||
$bySecond = $rule->getBySecond();
|
||||
|
||||
if (empty($bySecond)) {
|
||||
$bySecond = array($dt->format('s'));
|
||||
}
|
||||
|
||||
foreach ($bySecond as $second) {
|
||||
$set[] = new Time($hour, $minute, $second);
|
||||
}
|
||||
|
||||
return $set;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \DateTimeInterface $dt
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getTimeSetOfSecond(\DateTimeInterface $dt)
|
||||
{
|
||||
return array(new Time($dt->format('G'), $dt->format('i'), $dt->format('s')));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Rule $rule
|
||||
* @param \DateTimeInterface $dt
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getTimeSet(Rule $rule, \DateTimeInterface $dt)
|
||||
{
|
||||
$set = array();
|
||||
|
||||
if (null === $rule || $rule->getFreq() >= Frequency::HOURLY) {
|
||||
return $set;
|
||||
}
|
||||
|
||||
$byHour = $rule->getByHour();
|
||||
$byMinute = $rule->getByMinute();
|
||||
$bySecond = $rule->getBySecond();
|
||||
|
||||
if (empty($byHour)) {
|
||||
$byHour = array($dt->format('G'));
|
||||
}
|
||||
|
||||
if (empty($byMinute)) {
|
||||
$byMinute = array($dt->format('i'));
|
||||
}
|
||||
|
||||
if (empty($bySecond)) {
|
||||
$bySecond = array($dt->format('s'));
|
||||
}
|
||||
|
||||
foreach ($byHour as $hour) {
|
||||
foreach ($byMinute as $minute) {
|
||||
foreach ($bySecond as $second) {
|
||||
$set[] = new Time($hour, $minute, $second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $set;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a reference array with the day number for each day of each month.
|
||||
*
|
||||
* @param \DateTimeInterface $dt The datetime
|
||||
* @param bool $negative
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getMonthDaysMask(\DateTimeInterface $dt, $negative = false)
|
||||
{
|
||||
if ($negative) {
|
||||
$m29 = range(-29, -1);
|
||||
$m30 = range(-30, -1);
|
||||
$m31 = range(-31, -1);
|
||||
} else {
|
||||
$m29 = range(1, 29);
|
||||
$m30 = range(1, 30);
|
||||
$m31 = range(1, 31);
|
||||
}
|
||||
|
||||
$mask = array_merge(
|
||||
$m31, // Jan (31)
|
||||
$m29, // Feb (28)
|
||||
$m31, // Mar (31)
|
||||
$m30, // Apr (30)
|
||||
$m31, // May (31)
|
||||
$m30, // Jun (30)
|
||||
$m31, // Jul (31)
|
||||
$m31, // Aug (31)
|
||||
$m30, // Sep (30)
|
||||
$m31, // Oct (31)
|
||||
$m30, // Nov (30)
|
||||
$m31, // Dec (31)
|
||||
array_slice(
|
||||
$m31,
|
||||
0,
|
||||
7
|
||||
)
|
||||
);
|
||||
|
||||
if (self::isLeapYearDate($dt)) {
|
||||
return $mask;
|
||||
} else {
|
||||
if ($negative) {
|
||||
$mask = array_merge(array_slice($mask, 0, 31), array_slice($mask, 32));
|
||||
} else {
|
||||
$mask = array_merge(array_slice($mask, 0, 59), array_slice($mask, 60));
|
||||
}
|
||||
|
||||
return $mask;
|
||||
}
|
||||
}
|
||||
|
||||
public static function getMonthMask(\DateTimeInterface $dt)
|
||||
{
|
||||
if (self::isLeapYearDate($dt)) {
|
||||
return array_merge(
|
||||
array_fill(0, 31, 1), // Jan (31)
|
||||
array_fill(0, 29, 2), // Feb (29)
|
||||
array_fill(0, 31, 3), // Mar (31)
|
||||
array_fill(0, 30, 4), // Apr (30)
|
||||
array_fill(0, 31, 5), // May (31)
|
||||
array_fill(0, 30, 6), // Jun (30)
|
||||
array_fill(0, 31, 7), // Jul (31)
|
||||
array_fill(0, 31, 8), // Aug (31)
|
||||
array_fill(0, 30, 9), // Sep (30)
|
||||
array_fill(0, 31, 10), // Oct (31)
|
||||
array_fill(0, 30, 11), // Nov (30)
|
||||
array_fill(0, 31, 12), // Dec (31)
|
||||
array_fill(0, 7, 1)
|
||||
);
|
||||
} else {
|
||||
return array_merge(
|
||||
array_fill(0, 31, 1), // Jan (31)
|
||||
array_fill(0, 28, 2), // Feb (28)
|
||||
array_fill(0, 31, 3), // Mar (31)
|
||||
array_fill(0, 30, 4), // Apr (30)
|
||||
array_fill(0, 31, 5), // May (31)
|
||||
array_fill(0, 30, 6), // Jun (30)
|
||||
array_fill(0, 31, 7), // Jul (31)
|
||||
array_fill(0, 31, 8), // Aug (31)
|
||||
array_fill(0, 30, 9), // Sep (30)
|
||||
array_fill(0, 31, 10), // Oct (31)
|
||||
array_fill(0, 30, 11), // Nov (30)
|
||||
array_fill(0, 31, 12), // Dec (31)
|
||||
array_fill(0, 7, 1)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public static function getDateTimeByDayOfYear($dayOfYear, $year, \DateTimeZone $timezone)
|
||||
{
|
||||
$dtTmp = new \DateTime('now', $timezone);
|
||||
$dtTmp = $dtTmp->setDate($year, 1, 1);
|
||||
$dtTmp = $dtTmp->modify("+$dayOfYear day");
|
||||
|
||||
return $dtTmp;
|
||||
}
|
||||
|
||||
public static function hasLeapYearBug()
|
||||
{
|
||||
$leapBugTest = \DateTime::createFromFormat('Y-m-d', '2016-03-21');
|
||||
return $leapBugTest->format('z') != '80';
|
||||
}
|
||||
|
||||
/**
|
||||
* closure/goog/math/math.js:modulo
|
||||
* Copyright 2006 The Closure Library Authors.
|
||||
*
|
||||
* The % operator in PHP returns the remainder of a / b, but differs from
|
||||
* some other languages in that the result will have the same sign as the
|
||||
* dividend. For example, -1 % 8 == -1, whereas in some other languages
|
||||
* (such as Python) the result would be 7. This function emulates the more
|
||||
* correct modulo behavior, which is useful for certain applications such as
|
||||
* calculating an offset index in a circular list.
|
||||
*
|
||||
* @param int $a The dividend.
|
||||
* @param int $b The divisor.
|
||||
*
|
||||
* @return int $a % $b where the result is between 0 and $b
|
||||
* (either 0 <= x < $b
|
||||
* or $b < x <= 0, depending on the sign of $b).
|
||||
*/
|
||||
public static function pymod($a, $b)
|
||||
{
|
||||
$x = $a % $b;
|
||||
|
||||
// If $x and $b differ in sign, add $b to wrap the result to the correct sign.
|
||||
return ($x * $b < 0) ? $x + $b : $x;
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias method to determine if a date falls within a leap year.
|
||||
*
|
||||
* @param \DateTimeInterface $dt
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function isLeapYearDate(\DateTimeInterface $dt)
|
||||
{
|
||||
return $dt->format('L') ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias method to determine if a year is a leap year.
|
||||
*
|
||||
* @param int $year
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function isLeapYear($year)
|
||||
{
|
||||
$isDivisBy4 = $year % 4 == 0 ? true : false;
|
||||
$isDivisBy100 = $year % 100 == 0? true : false;
|
||||
$isDivisBy400 = $year % 400 == 0 ? true : false;
|
||||
|
||||
// http://en.wikipedia.org/wiki/February_29
|
||||
if ($isDivisBy100 && !$isDivisBy400) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $isDivisBy4;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to determine the day of the week from MO-SU.
|
||||
*
|
||||
* MO = Monday
|
||||
* TU = Tuesday
|
||||
* WE = Wednesday
|
||||
* TH = Thursday
|
||||
* FR = Friday
|
||||
* SA = Saturday
|
||||
* SU = Sunday
|
||||
*
|
||||
* @param \DateTimeInterface $dt
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getDayOfWeekAsText(\DateTimeInterface $dt)
|
||||
{
|
||||
$dayOfWeek = $dt->format('w') - 1;
|
||||
|
||||
if ($dayOfWeek < 0) {
|
||||
$dayOfWeek = 6;
|
||||
}
|
||||
|
||||
$map = array('MO', 'TU', 'WE', 'TH', 'FR', 'SA', 'SU');
|
||||
|
||||
return $map[$dayOfWeek];
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias method to determine the day of the week from 0-6.
|
||||
*
|
||||
* 0 = Monday
|
||||
* 1 = Tuesday
|
||||
* 2 = Wednesday
|
||||
* 3 = Thursday
|
||||
* 4 = Friday
|
||||
* 5 = Saturday
|
||||
* 6 = Sunday
|
||||
*
|
||||
* @param \DateTimeInterface $dt
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function getDayOfWeek(\DateTimeInterface $dt)
|
||||
{
|
||||
$dayOfWeek = $dt->format('w') - 1;
|
||||
|
||||
if ($dayOfWeek < 0) {
|
||||
$dayOfWeek = 6;
|
||||
}
|
||||
|
||||
return $dayOfWeek;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of days in a year.
|
||||
*
|
||||
* @param \DateTimeInterface $dt
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function getYearLength(\DateTimeInterface $dt)
|
||||
{
|
||||
return self::isLeapYearDate($dt) ? 366 : 365;
|
||||
}
|
||||
}
|
||||
46
old.vendor/simshaun/recurr/src/Recurr/DaySet.php
Normal file
46
old.vendor/simshaun/recurr/src/Recurr/DaySet.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2013 Shaun Simmons
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* Based on rrule.js
|
||||
* Copyright 2010, Jakub Roztocil and Lars Schoning
|
||||
* https://github.com/jkbr/rrule/blob/master/LICENCE
|
||||
*/
|
||||
|
||||
namespace Recurr;
|
||||
|
||||
/**
|
||||
* Class DaySet is a container for a set and its meta.
|
||||
*
|
||||
* @package Recurr
|
||||
* @author Shaun Simmons <shaun@envysphere.com>
|
||||
*/
|
||||
class DaySet
|
||||
{
|
||||
/** @var array */
|
||||
public $set;
|
||||
|
||||
/** @var int Day of year */
|
||||
public $start;
|
||||
|
||||
/** @var int Day of year */
|
||||
public $end;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param array $set Set of days
|
||||
* @param int $start Day of year of start day
|
||||
* @param int $end Day of year of end day
|
||||
*/
|
||||
public function __construct($set, $start, $end)
|
||||
{
|
||||
$this->set = $set;
|
||||
$this->start = $start;
|
||||
$this->end = $end;
|
||||
}
|
||||
}
|
||||
17
old.vendor/simshaun/recurr/src/Recurr/Exception.php
Normal file
17
old.vendor/simshaun/recurr/src/Recurr/Exception.php
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2013 Shaun Simmons
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Recurr;
|
||||
|
||||
/**
|
||||
* The base Recurr exception class
|
||||
*/
|
||||
class Exception extends \Exception
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2013 Shaun Simmons
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Recurr\Exception;
|
||||
|
||||
use Recurr\Exception;
|
||||
|
||||
/**
|
||||
* @package Recurr\Exception
|
||||
* @author Shaun Simmons <shaun@envysphere.com>
|
||||
*/
|
||||
class InvalidArgument extends Exception
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2013 Shaun Simmons
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Recurr\Exception;
|
||||
|
||||
use Recurr\Exception;
|
||||
|
||||
/**
|
||||
* @package Recurr\Exception
|
||||
* @author Shaun Simmons <shaun@envysphere.com>
|
||||
*/
|
||||
class InvalidRRule extends Exception
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2013 Shaun Simmons
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Recurr\Exception;
|
||||
|
||||
use Recurr\Exception;
|
||||
|
||||
/**
|
||||
* @package Recurr\Exception
|
||||
* @author Shaun Simmons <shaun@envysphere.com>
|
||||
*/
|
||||
class InvalidWeekday extends Exception
|
||||
{
|
||||
}
|
||||
25
old.vendor/simshaun/recurr/src/Recurr/Frequency.php
Normal file
25
old.vendor/simshaun/recurr/src/Recurr/Frequency.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2014 Shaun Simmons
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* Based on:
|
||||
* rrule.js - Library for working with recurrence rules for calendar dates.
|
||||
* Copyright 2010, Jakub Roztocil and Lars Schoning
|
||||
* https://github.com/jkbr/rrule/blob/master/LICENCE
|
||||
*/
|
||||
|
||||
namespace Recurr;
|
||||
|
||||
class Frequency {
|
||||
const YEARLY = 0;
|
||||
const MONTHLY = 1;
|
||||
const WEEKLY = 2;
|
||||
const DAILY = 3;
|
||||
const HOURLY = 4;
|
||||
const MINUTELY = 5;
|
||||
const SECONDLY = 6;
|
||||
}
|
||||
90
old.vendor/simshaun/recurr/src/Recurr/Recurrence.php
Normal file
90
old.vendor/simshaun/recurr/src/Recurr/Recurrence.php
Normal file
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2014 Shaun Simmons
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Recurr;
|
||||
|
||||
/**
|
||||
* Class Recurrence is responsible for storing the start and end \DateTime of
|
||||
* a specific recurrence in a RRULE.
|
||||
*
|
||||
* @package Recurr
|
||||
* @author Shaun Simmons <shaun@envysphere.com>
|
||||
*/
|
||||
class Recurrence
|
||||
{
|
||||
/** @var \DateTimeInterface */
|
||||
protected $start;
|
||||
|
||||
/** @var \DateTimeInterface */
|
||||
protected $end;
|
||||
|
||||
/** @var int */
|
||||
protected $index;
|
||||
|
||||
public function __construct(\DateTimeInterface $start = null, \DateTimeInterface $end = null, $index = 0)
|
||||
{
|
||||
if ($start instanceof \DateTimeInterface) {
|
||||
$this->setStart($start);
|
||||
}
|
||||
|
||||
if ($end instanceof \DateTimeInterface) {
|
||||
$this->setEnd($end);
|
||||
}
|
||||
|
||||
$this->index = $index;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \DateTimeInterface
|
||||
*/
|
||||
public function getStart()
|
||||
{
|
||||
return $this->start;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \DateTime $start
|
||||
*/
|
||||
public function setStart($start)
|
||||
{
|
||||
$this->start = $start;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \DateTime
|
||||
*/
|
||||
public function getEnd()
|
||||
{
|
||||
return $this->end;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \DateTime $end
|
||||
*/
|
||||
public function setEnd($end)
|
||||
{
|
||||
$this->end = $end;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getIndex()
|
||||
{
|
||||
return $this->index;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $index
|
||||
*/
|
||||
public function setIndex($index)
|
||||
{
|
||||
$this->index = $index;
|
||||
}
|
||||
}
|
||||
153
old.vendor/simshaun/recurr/src/Recurr/RecurrenceCollection.php
Normal file
153
old.vendor/simshaun/recurr/src/Recurr/RecurrenceCollection.php
Normal file
@@ -0,0 +1,153 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2014 Shaun Simmons
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Recurr;
|
||||
|
||||
use \Doctrine\Common\Collections\ArrayCollection as BaseCollection;
|
||||
|
||||
/**
|
||||
* @package Recurr
|
||||
* @author Shaun Simmons <shaun@envysphere.com>
|
||||
*/
|
||||
class RecurrenceCollection extends BaseCollection
|
||||
{
|
||||
/**
|
||||
* @param \DateTimeInterface $after
|
||||
* @param \DateTimeInterface $before
|
||||
* @param bool $inc Include $after or $before if they happen to be a recurrence.
|
||||
*
|
||||
* @return RecurrenceCollection
|
||||
*/
|
||||
public function startsBetween(\DateTimeInterface $after, \DateTimeInterface $before, $inc = false)
|
||||
{
|
||||
return $this->filter(
|
||||
function ($recurrence) use ($after, $before, $inc) {
|
||||
/** @var $recurrence Recurrence */
|
||||
$start = $recurrence->getStart();
|
||||
|
||||
if ($inc) {
|
||||
return $start >= $after && $start <= $before;
|
||||
}
|
||||
|
||||
return $start > $after && $start < $before;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \DateTimeInterface $before
|
||||
* @param bool $inc Include $before if it is a recurrence.
|
||||
*
|
||||
* @return RecurrenceCollection
|
||||
*/
|
||||
public function startsBefore(\DateTimeInterface $before, $inc = false)
|
||||
{
|
||||
return $this->filter(
|
||||
function ($recurrence) use ($before, $inc) {
|
||||
/** @var $recurrence Recurrence */
|
||||
$start = $recurrence->getStart();
|
||||
|
||||
if ($inc) {
|
||||
return $start <= $before;
|
||||
}
|
||||
|
||||
return $start < $before;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \DateTimeInterface $after
|
||||
* @param bool $inc Include $after if it a recurrence.
|
||||
*
|
||||
* @return RecurrenceCollection
|
||||
*/
|
||||
public function startsAfter(\DateTimeInterface $after, $inc = false)
|
||||
{
|
||||
return $this->filter(
|
||||
function ($recurrence) use ($after, $inc) {
|
||||
/** @var $recurrence Recurrence */
|
||||
$start = $recurrence->getStart();
|
||||
|
||||
if ($inc) {
|
||||
return $start >= $after;
|
||||
}
|
||||
|
||||
return $start > $after;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \DateTimeInterface $after
|
||||
* @param \DateTimeInterface $before
|
||||
* @param bool $inc Include $after or $before if they happen to be a recurrence.
|
||||
*
|
||||
* @return RecurrenceCollection
|
||||
*/
|
||||
public function endsBetween(\DateTimeInterface $after, \DateTimeInterface $before, $inc = false)
|
||||
{
|
||||
return $this->filter(
|
||||
function ($recurrence) use ($after, $before, $inc) {
|
||||
/** @var $recurrence Recurrence */
|
||||
$end = $recurrence->getEnd();
|
||||
|
||||
if ($inc) {
|
||||
return $end >= $after && $end <= $before;
|
||||
}
|
||||
|
||||
return $end > $after && $end < $before;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \DateTimeInterface $before
|
||||
* @param bool $inc Include $before if it is a recurrence.
|
||||
*
|
||||
* @return RecurrenceCollection
|
||||
*/
|
||||
public function endsBefore(\DateTimeInterface $before, $inc = false)
|
||||
{
|
||||
return $this->filter(
|
||||
function ($recurrence) use ($before, $inc) {
|
||||
/** @var $recurrence Recurrence */
|
||||
$end = $recurrence->getEnd();
|
||||
|
||||
if ($inc) {
|
||||
return $end <= $before;
|
||||
}
|
||||
|
||||
return $end < $before;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \DateTimeInterface $after
|
||||
* @param bool $inc Include $after if it a recurrence.
|
||||
*
|
||||
* @return RecurrenceCollection
|
||||
*/
|
||||
public function endsAfter(\DateTimeInterface $after, $inc = false)
|
||||
{
|
||||
return $this->filter(
|
||||
function ($recurrence) use ($after, $inc) {
|
||||
/** @var $recurrence Recurrence */
|
||||
$end = $recurrence->getEnd();
|
||||
|
||||
if ($inc) {
|
||||
return $end >= $after;
|
||||
}
|
||||
|
||||
return $end > $after;
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
1315
old.vendor/simshaun/recurr/src/Recurr/Rule.php
Normal file
1315
old.vendor/simshaun/recurr/src/Recurr/Rule.php
Normal file
File diff suppressed because it is too large
Load Diff
39
old.vendor/simshaun/recurr/src/Recurr/Time.php
Normal file
39
old.vendor/simshaun/recurr/src/Recurr/Time.php
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2013 Shaun Simmons
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* Based on rrule.js
|
||||
* Copyright 2010, Jakub Roztocil and Lars Schoning
|
||||
* https://github.com/jkbr/rrule/blob/master/LICENCE
|
||||
*/
|
||||
|
||||
namespace Recurr;
|
||||
|
||||
/**
|
||||
* Class Time is a storage container for a time of day.
|
||||
*
|
||||
* @package Recurr
|
||||
* @author Shaun Simmons <shaun@envysphere.com>
|
||||
*/
|
||||
class Time
|
||||
{
|
||||
/** @var int */
|
||||
public $hour;
|
||||
|
||||
/** @var int */
|
||||
public $minute;
|
||||
|
||||
/** @var int */
|
||||
public $second;
|
||||
|
||||
public function __construct($hour, $minute, $second)
|
||||
{
|
||||
$this->hour = $hour;
|
||||
$this->minute = $minute;
|
||||
$this->second = $second;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,736 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2013 Shaun Simmons
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* Based on:
|
||||
* rrule.js - Library for working with recurrence rules for calendar dates.
|
||||
* Copyright 2010, Jakub Roztocil and Lars Schoning
|
||||
* https://github.com/jkbr/rrule/blob/master/LICENCE
|
||||
*/
|
||||
|
||||
namespace Recurr\Transformer;
|
||||
|
||||
use Recurr\DateExclusion;
|
||||
use Recurr\DateInclusion;
|
||||
use Recurr\Exception\InvalidWeekday;
|
||||
use Recurr\Frequency;
|
||||
use Recurr\Recurrence;
|
||||
use Recurr\RecurrenceCollection;
|
||||
use Recurr\Rule;
|
||||
use Recurr\Time;
|
||||
use Recurr\Weekday;
|
||||
use Recurr\DateUtil;
|
||||
|
||||
/**
|
||||
* This class is responsible for transforming a Rule in to an array
|
||||
* of \DateTimeInterface objects.
|
||||
*
|
||||
* If a recurrence rule is infinitely recurring, a virtual limit is imposed.
|
||||
*
|
||||
* @package Recurr
|
||||
* @author Shaun Simmons <shaun@envysphere.com>
|
||||
*/
|
||||
class ArrayTransformer
|
||||
{
|
||||
/** @var ArrayTransformerConfig */
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* Some versions of PHP are affected by a bug where
|
||||
* \DateTimeInterface::createFromFormat('z Y', ...) does not account for leap years.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $leapBug = false;
|
||||
|
||||
/**
|
||||
* Construct a new ArrayTransformer
|
||||
*
|
||||
* @param ArrayTransformerConfig $config
|
||||
*/
|
||||
public function __construct(ArrayTransformerConfig $config = null)
|
||||
{
|
||||
if (!$config instanceof ArrayTransformerConfig) {
|
||||
$config = new ArrayTransformerConfig();
|
||||
}
|
||||
|
||||
$this->config = $config;
|
||||
|
||||
$this->leapBug = DateUtil::hasLeapYearBug();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ArrayTransformerConfig $config
|
||||
*/
|
||||
public function setConfig($config)
|
||||
{
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform a Rule in to an array of \DateTimeInterface objects
|
||||
*
|
||||
* @param Rule $rule the Rule object
|
||||
* @param ConstraintInterface|null $constraint Potential recurrences must pass the constraint, else
|
||||
* they will not be included in the returned collection.
|
||||
* @param bool $countConstraintFailures Whether recurrences that fail the constraint's test
|
||||
* should count towards a rule's COUNT limit.
|
||||
*
|
||||
* @return RecurrenceCollection|Recurrence[]
|
||||
* @throws InvalidWeekday
|
||||
*/
|
||||
public function transform(Rule $rule, ConstraintInterface $constraint = null, $countConstraintFailures = true)
|
||||
{
|
||||
$start = $rule->getStartDate();
|
||||
$end = $rule->getEndDate();
|
||||
$until = $rule->getUntil();
|
||||
|
||||
if (null === $start) {
|
||||
$start = new \DateTime(
|
||||
'now', $until instanceof \DateTimeInterface ? $until->getTimezone() : null
|
||||
);
|
||||
}
|
||||
|
||||
if (null === $end) {
|
||||
$end = $start;
|
||||
}
|
||||
|
||||
$durationInterval = $start->diff($end);
|
||||
|
||||
$startDay = $start->format('j');
|
||||
$startMonthLength = $start->format('t');
|
||||
$fixLastDayOfMonth = false;
|
||||
|
||||
$dt = clone $start;
|
||||
|
||||
$maxCount = $rule->getCount();
|
||||
$vLimit = $this->config->getVirtualLimit();
|
||||
|
||||
$freq = $rule->getFreq();
|
||||
$weekStart = $rule->getWeekStartAsNum();
|
||||
$bySecond = $rule->getBySecond();
|
||||
$byMinute = $rule->getByMinute();
|
||||
$byHour = $rule->getByHour();
|
||||
$byMonth = $rule->getByMonth();
|
||||
$byWeekNum = $rule->getByWeekNumber();
|
||||
$byYearDay = $rule->getByYearDay();
|
||||
$byMonthDay = $rule->getByMonthDay();
|
||||
$byMonthDayNeg = array();
|
||||
$byWeekDay = $rule->getByDayTransformedToWeekdays();
|
||||
$byWeekDayRel = array();
|
||||
$bySetPos = $rule->getBySetPosition();
|
||||
|
||||
$implicitByMonthDay = false;
|
||||
if (!(!empty($byWeekNum) || !empty($byYearDay) || !empty($byMonthDay) || !empty($byWeekDay))) {
|
||||
switch ($freq) {
|
||||
case Frequency::YEARLY:
|
||||
if (empty($byMonth)) {
|
||||
$byMonth = array($start->format('n'));
|
||||
}
|
||||
|
||||
if ($startDay > 28) {
|
||||
$fixLastDayOfMonth = true;
|
||||
}
|
||||
|
||||
$implicitByMonthDay = true;
|
||||
$byMonthDay = array($startDay);
|
||||
break;
|
||||
case Frequency::MONTHLY:
|
||||
if ($startDay > 28) {
|
||||
$fixLastDayOfMonth = true;
|
||||
}
|
||||
|
||||
$implicitByMonthDay = true;
|
||||
$byMonthDay = array($startDay);
|
||||
break;
|
||||
case Frequency::WEEKLY:
|
||||
$byWeekDay = array(
|
||||
new Weekday(
|
||||
DateUtil::getDayOfWeek($start), null
|
||||
)
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$this->config->isLastDayOfMonthFixEnabled()) {
|
||||
$fixLastDayOfMonth = false;
|
||||
}
|
||||
|
||||
if (is_array($byMonthDay) && count($byMonthDay)) {
|
||||
foreach ($byMonthDay as $idx => $day) {
|
||||
if ($day < 0) {
|
||||
unset($byMonthDay[$idx]);
|
||||
$byMonthDayNeg[] = $day;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($byWeekDay)) {
|
||||
foreach ($byWeekDay as $idx => $day) {
|
||||
/** @var $day Weekday */
|
||||
|
||||
if (!empty($day->num)) {
|
||||
$byWeekDayRel[] = $day;
|
||||
unset($byWeekDay[$idx]);
|
||||
} else {
|
||||
$byWeekDay[$idx] = $day->weekday;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($byYearDay)) {
|
||||
$byYearDay = null;
|
||||
}
|
||||
|
||||
if (empty($byMonthDay)) {
|
||||
$byMonthDay = null;
|
||||
}
|
||||
|
||||
if (empty($byMonthDayNeg)) {
|
||||
$byMonthDayNeg = null;
|
||||
}
|
||||
|
||||
if (empty($byWeekDay)) {
|
||||
$byWeekDay = null;
|
||||
}
|
||||
|
||||
if (!count($byWeekDayRel)) {
|
||||
$byWeekDayRel = null;
|
||||
}
|
||||
|
||||
$year = $dt->format('Y');
|
||||
$month = $dt->format('n');
|
||||
$hour = $dt->format('G');
|
||||
$minute = $dt->format('i');
|
||||
$second = $dt->format('s');
|
||||
|
||||
$dates = array();
|
||||
$total = 1;
|
||||
$count = $maxCount;
|
||||
$continue = true;
|
||||
$iterations = 0;
|
||||
while ($continue) {
|
||||
$dtInfo = DateUtil::getDateInfo($dt);
|
||||
|
||||
$tmp = DateUtil::getDaySet($rule, $dt, $dtInfo, $start);
|
||||
$daySet = $tmp->set;
|
||||
$daySetStart = $tmp->start;
|
||||
$daySetEnd = $tmp->end;
|
||||
$wNoMask = array();
|
||||
$wDayMaskRel = array();
|
||||
$timeSet = DateUtil::getTimeSet($rule, $dt);
|
||||
|
||||
if ($freq >= Frequency::HOURLY) {
|
||||
if (
|
||||
($freq >= Frequency::HOURLY && !empty($byHour) && !in_array($hour, $byHour))
|
||||
|| ($freq >= Frequency::MINUTELY && !empty($byMinute) && !in_array($minute, $byMinute))
|
||||
|| ($freq >= Frequency::SECONDLY && !empty($bySecond) && !in_array($second, $bySecond))
|
||||
) {
|
||||
$timeSet = array();
|
||||
} else {
|
||||
switch ($freq) {
|
||||
case Frequency::HOURLY:
|
||||
$timeSet = DateUtil::getTimeSetOfHour($rule, $dt);
|
||||
break;
|
||||
case Frequency::MINUTELY:
|
||||
$timeSet = DateUtil::getTimeSetOfMinute($rule, $dt);
|
||||
break;
|
||||
case Frequency::SECONDLY:
|
||||
$timeSet = DateUtil::getTimeSetOfSecond($dt);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle byWeekNum
|
||||
if (!empty($byWeekNum)) {
|
||||
$no1WeekStart = $firstWeekStart = DateUtil::pymod(7 - $dtInfo->dayOfWeekYearDay1 + $weekStart, 7);
|
||||
|
||||
if ($no1WeekStart >= 4) {
|
||||
$no1WeekStart = 0;
|
||||
|
||||
$wYearLength = $dtInfo->yearLength + DateUtil::pymod(
|
||||
$dtInfo->dayOfWeekYearDay1 - $weekStart,
|
||||
7
|
||||
);
|
||||
} else {
|
||||
$wYearLength = $dtInfo->yearLength - $no1WeekStart;
|
||||
}
|
||||
|
||||
$div = floor($wYearLength / 7);
|
||||
$mod = DateUtil::pymod($wYearLength, 7);
|
||||
$numWeeks = floor($div + ($mod / 4));
|
||||
|
||||
foreach ($byWeekNum as $weekNum) {
|
||||
if ($weekNum < 0) {
|
||||
$weekNum += $numWeeks + 1;
|
||||
}
|
||||
|
||||
if (!(0 < $weekNum && $weekNum <= $numWeeks)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($weekNum > 1) {
|
||||
$offset = $no1WeekStart + ($weekNum - 1) * 7;
|
||||
if ($no1WeekStart != $firstWeekStart) {
|
||||
$offset -= 7 - $firstWeekStart;
|
||||
}
|
||||
} else {
|
||||
$offset = $no1WeekStart;
|
||||
}
|
||||
|
||||
for ($i = 0; $i < 7; $i++) {
|
||||
$wNoMask[] = $offset;
|
||||
$offset++;
|
||||
if ($dtInfo->wDayMask[$offset] == $weekStart) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check week number 1 of next year as well
|
||||
if (in_array(1, $byWeekNum)) {
|
||||
$offset = $no1WeekStart + $numWeeks * 7;
|
||||
|
||||
if ($no1WeekStart != $firstWeekStart) {
|
||||
$offset -= 7 - $firstWeekStart;
|
||||
}
|
||||
|
||||
// If week starts in next year, we don't care about it.
|
||||
if ($offset < $dtInfo->yearLength) {
|
||||
for ($k = 0; $k < 7; $k++) {
|
||||
$wNoMask[] = $offset;
|
||||
$offset += 1;
|
||||
if ($dtInfo->wDayMask[$offset] == $weekStart) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($no1WeekStart) {
|
||||
// Check last week number of last year as well.
|
||||
// If $no1WeekStart is 0, either the year started on week start,
|
||||
// or week number 1 got days from last year, so there are no
|
||||
// days from last year's last week number in this year.
|
||||
if (!in_array(-1, $byWeekNum)) {
|
||||
$dtTmp = new \DateTime();
|
||||
$dtTmp = $dtTmp->setDate($year - 1, 1, 1);
|
||||
$lastYearWeekDay = DateUtil::getDayOfWeek($dtTmp);
|
||||
$lastYearNo1WeekStart = DateUtil::pymod(7 - $lastYearWeekDay + $weekStart, 7);
|
||||
$lastYearLength = DateUtil::getYearLength($dtTmp);
|
||||
if ($lastYearNo1WeekStart >= 4) {
|
||||
$lastYearNo1WeekStart = 0;
|
||||
$lastYearNumWeeks = floor(
|
||||
52 + DateUtil::pymod(
|
||||
$lastYearLength + DateUtil::pymod(
|
||||
$lastYearWeekDay - $weekStart,
|
||||
7
|
||||
),
|
||||
7
|
||||
) / 4
|
||||
);
|
||||
} else {
|
||||
$lastYearNumWeeks = floor(
|
||||
52 + DateUtil::pymod(
|
||||
$dtInfo->yearLength - $no1WeekStart,
|
||||
7
|
||||
) / 4
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$lastYearNumWeeks = -1;
|
||||
}
|
||||
|
||||
if (in_array($lastYearNumWeeks, $byWeekNum)) {
|
||||
for ($i = 0; $i < $no1WeekStart; $i++) {
|
||||
$wNoMask[] = $i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle relative weekdays (e.g. 3rd Friday of month)
|
||||
if (!empty($byWeekDayRel)) {
|
||||
$ranges = array();
|
||||
|
||||
if (Frequency::YEARLY == $freq) {
|
||||
if (!empty($byMonth)) {
|
||||
foreach ($byMonth as $mo) {
|
||||
$ranges[] = array_slice($dtInfo->mRanges, $mo - 1, 2);
|
||||
}
|
||||
} else {
|
||||
$ranges[] = array(0, $dtInfo->yearLength);
|
||||
}
|
||||
} elseif (Frequency::MONTHLY == $freq) {
|
||||
$ranges[] = array_slice($dtInfo->mRanges, $month - 1, 2);
|
||||
}
|
||||
|
||||
if (!empty($ranges)) {
|
||||
foreach ($ranges as $range) {
|
||||
$rangeStart = $range[0];
|
||||
$rangeEnd = $range[1];
|
||||
--$rangeEnd;
|
||||
|
||||
reset($byWeekDayRel);
|
||||
foreach ($byWeekDayRel as $weekday) {
|
||||
/** @var Weekday $weekday */
|
||||
|
||||
if ($weekday->num < 0) {
|
||||
$i = $rangeEnd + ($weekday->num + 1) * 7;
|
||||
$i -= DateUtil::pymod(
|
||||
$dtInfo->wDayMask[$i] - $weekday->weekday,
|
||||
7
|
||||
);
|
||||
} else {
|
||||
$i = $rangeStart + ($weekday->num - 1) * 7;
|
||||
$i += DateUtil::pymod(
|
||||
7 - $dtInfo->wDayMask[$i] + $weekday->weekday,
|
||||
7
|
||||
);
|
||||
}
|
||||
|
||||
if ($rangeStart <= $i && $i <= $rangeEnd) {
|
||||
$wDayMaskRel[] = $i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$numMatched = 0;
|
||||
foreach ($daySet as $i => $dayOfYear) {
|
||||
$dayOfMonth = $dtInfo->mDayMask[$dayOfYear];
|
||||
|
||||
$ifByMonth = $byMonth !== null && !in_array($dtInfo->mMask[$dayOfYear], $byMonth);
|
||||
|
||||
$ifByWeekNum = $byWeekNum !== null && !in_array($i, $wNoMask);
|
||||
|
||||
$ifByYearDay = $byYearDay !== null && (
|
||||
(
|
||||
$i < $dtInfo->yearLength &&
|
||||
!in_array($i + 1, $byYearDay) &&
|
||||
!in_array(-$dtInfo->yearLength + $i, $byYearDay)
|
||||
) ||
|
||||
(
|
||||
$i >= $dtInfo->yearLength &&
|
||||
!in_array($i + 1 - $dtInfo->yearLength, $byYearDay) &&
|
||||
!in_array(-$dtInfo->nextYearLength + $i - $dtInfo->yearLength, $byYearDay)
|
||||
)
|
||||
);
|
||||
|
||||
$ifByMonthDay = $byMonthDay !== null && !in_array($dtInfo->mDayMask[$dayOfYear], $byMonthDay);
|
||||
|
||||
// Handle "last day of next month" problem.
|
||||
if ($fixLastDayOfMonth
|
||||
&& $ifByMonthDay
|
||||
&& $implicitByMonthDay
|
||||
&& $startMonthLength > $dtInfo->monthLength
|
||||
&& $dayOfMonth == $dtInfo->monthLength
|
||||
&& $dayOfMonth < $startMonthLength
|
||||
&& !$numMatched
|
||||
) {
|
||||
$ifByMonthDay = false;
|
||||
}
|
||||
|
||||
$ifByMonthDayNeg = $byMonthDayNeg !== null
|
||||
&& !in_array($dtInfo->mDayMaskNeg[$dayOfYear], $byMonthDayNeg);
|
||||
|
||||
$ifByDay = $byWeekDay !== null && count($byWeekDay)
|
||||
&& !in_array($dtInfo->wDayMask[$dayOfYear], $byWeekDay);
|
||||
|
||||
$ifWDayMaskRel = $byWeekDayRel !== null && !in_array($dayOfYear, $wDayMaskRel);
|
||||
|
||||
if ($byMonthDay !== null && $byMonthDayNeg !== null) {
|
||||
if ($ifByMonthDay && $ifByMonthDayNeg) {
|
||||
unset($daySet[$i]);
|
||||
}
|
||||
} elseif ($ifByMonth || $ifByWeekNum || $ifByYearDay || $ifByMonthDay || $ifByMonthDayNeg || $ifByDay || $ifWDayMaskRel) {
|
||||
unset($daySet[$i]);
|
||||
} else {
|
||||
++$numMatched;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($bySetPos) && !empty($daySet)) {
|
||||
$datesAdj = array();
|
||||
$tmpDaySet = array_combine($daySet, $daySet);
|
||||
|
||||
foreach ($bySetPos as $setPos) {
|
||||
if ($setPos < 0) {
|
||||
$dayPos = floor($setPos / count($timeSet));
|
||||
$timePos = DateUtil::pymod($setPos, count($timeSet));
|
||||
} else {
|
||||
$dayPos = floor(($setPos - 1) / count($timeSet));
|
||||
$timePos = DateUtil::pymod(($setPos - 1), count($timeSet));
|
||||
}
|
||||
|
||||
$tmp = array();
|
||||
for ($k = $daySetStart; $k <= $daySetEnd; $k++) {
|
||||
if (!array_key_exists($k, $tmpDaySet)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$tmp[] = $tmpDaySet[$k];
|
||||
}
|
||||
|
||||
if ($dayPos < 0) {
|
||||
$nextInSet = array_slice($tmp, $dayPos, 1);
|
||||
if (count($nextInSet) === 0) {
|
||||
continue;
|
||||
}
|
||||
$nextInSet = $nextInSet[0];
|
||||
} else {
|
||||
$nextInSet = isset($tmp[$dayPos]) ? $tmp[$dayPos] : null;
|
||||
}
|
||||
|
||||
if (null !== $nextInSet) {
|
||||
/** @var Time $time */
|
||||
$time = $timeSet[$timePos];
|
||||
|
||||
$dtTmp = DateUtil::getDateTimeByDayOfYear($nextInSet, $dt->format('Y'), $start->getTimezone());
|
||||
|
||||
$dtTmp = $dtTmp->setTime(
|
||||
$time->hour,
|
||||
$time->minute,
|
||||
$time->second
|
||||
);
|
||||
|
||||
$datesAdj[] = $dtTmp;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($datesAdj as $dtTmp) {
|
||||
if (null !== $until && $dtTmp > $until) {
|
||||
$continue = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if ($dtTmp < $start) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($constraint instanceof ConstraintInterface && !$constraint->test($dtTmp)) {
|
||||
if (!$countConstraintFailures) {
|
||||
if ($constraint->stopsTransformer()) {
|
||||
$continue = false;
|
||||
break;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$dates[$total] = $dtTmp;
|
||||
}
|
||||
|
||||
if (null !== $count) {
|
||||
--$count;
|
||||
if ($count <= 0) {
|
||||
$continue = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
++$total;
|
||||
if ($total > $vLimit) {
|
||||
$continue = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
foreach ($daySet as $dayOfYear) {
|
||||
$dtTmp = DateUtil::getDateTimeByDayOfYear($dayOfYear, $dt->format('Y'), $start->getTimezone());
|
||||
|
||||
foreach ($timeSet as $time) {
|
||||
/** @var Time $time */
|
||||
$dtTmp = $dtTmp->setTime(
|
||||
$time->hour,
|
||||
$time->minute,
|
||||
$time->second
|
||||
);
|
||||
|
||||
if (null !== $until && $dtTmp > $until) {
|
||||
$continue = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if ($dtTmp < $start) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($constraint instanceof ConstraintInterface && !$constraint->test($dtTmp)) {
|
||||
if (!$countConstraintFailures) {
|
||||
if ($constraint->stopsTransformer()) {
|
||||
$continue = false;
|
||||
break;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$dates[$total] = clone $dtTmp;
|
||||
}
|
||||
|
||||
if (null !== $count) {
|
||||
--$count;
|
||||
if ($count <= 0) {
|
||||
$continue = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
++$total;
|
||||
if ($total > $vLimit) {
|
||||
$continue = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$continue) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($total > $vLimit) {
|
||||
$continue = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch ($freq) {
|
||||
case Frequency::YEARLY:
|
||||
$year += $rule->getInterval();
|
||||
$month = $dt->format('n');
|
||||
$dt = $dt->setDate($year, $month, 1);
|
||||
|
||||
// Stop an infinite loop w/ a sane limit
|
||||
++$iterations;
|
||||
if ($iterations > 300 && !count($dates)) {
|
||||
break 2;
|
||||
}
|
||||
break;
|
||||
case Frequency::MONTHLY:
|
||||
$month += $rule->getInterval();
|
||||
if ($month > 12) {
|
||||
$delta = floor($month / 12);
|
||||
$mod = DateUtil::pymod($month, 12);
|
||||
$month = $mod;
|
||||
$year += $delta;
|
||||
if ($month == 0) {
|
||||
$month = 12;
|
||||
--$year;
|
||||
}
|
||||
}
|
||||
$dt = $dt->setDate($year, $month, 1);
|
||||
break;
|
||||
case Frequency::WEEKLY:
|
||||
if ($weekStart > $dtInfo->dayOfWeek) {
|
||||
$delta = ($dtInfo->dayOfWeek + 1 + (6 - $weekStart)) * -1 + $rule->getInterval() * 7;
|
||||
} else {
|
||||
$delta = ($dtInfo->dayOfWeek - $weekStart) * -1 + $rule->getInterval() * 7;
|
||||
}
|
||||
|
||||
$dt = $dt->modify("+$delta day");
|
||||
$year = $dt->format('Y');
|
||||
$month = $dt->format('n');
|
||||
break;
|
||||
case Frequency::DAILY:
|
||||
$dt = $dt->modify('+'.$rule->getInterval().' day');
|
||||
$year = $dt->format('Y');
|
||||
$month = $dt->format('n');
|
||||
break;
|
||||
case Frequency::HOURLY:
|
||||
$dt = $dt->modify('+'.$rule->getInterval().' hours');
|
||||
$year = $dt->format('Y');
|
||||
$month = $dt->format('n');
|
||||
$hour = $dt->format('G');
|
||||
break;
|
||||
case Frequency::MINUTELY:
|
||||
$dt = $dt->modify('+'.$rule->getInterval().' minutes');
|
||||
$year = $dt->format('Y');
|
||||
$month = $dt->format('n');
|
||||
$hour = $dt->format('G');
|
||||
$minute = $dt->format('i');
|
||||
break;
|
||||
case Frequency::SECONDLY:
|
||||
$dt = $dt->modify('+'.$rule->getInterval().' seconds');
|
||||
$year = $dt->format('Y');
|
||||
$month = $dt->format('n');
|
||||
$hour = $dt->format('G');
|
||||
$minute = $dt->format('i');
|
||||
$second = $dt->format('s');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/** @var Recurrence[] $recurrences */
|
||||
$recurrences = array();
|
||||
foreach ($dates as $key => $start) {
|
||||
/** @var \DateTimeInterface $end */
|
||||
$end = clone $start;
|
||||
|
||||
$recurrences[] = new Recurrence($start, $end->add($durationInterval), $key);
|
||||
}
|
||||
|
||||
$recurrences = $this->handleInclusions($rule->getRDates(), $recurrences);
|
||||
$recurrences = $this->handleExclusions($rule->getExDates(), $recurrences);
|
||||
|
||||
return new RecurrenceCollection($recurrences);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DateExclusion[] $exclusions
|
||||
* @param Recurrence[] $recurrences
|
||||
*
|
||||
* @return Recurrence[]
|
||||
*/
|
||||
protected function handleExclusions(array $exclusions, array $recurrences)
|
||||
{
|
||||
foreach ($exclusions as $exclusion) {
|
||||
$exclusionDate = $exclusion->date->format('Ymd');
|
||||
$exclusionTime = $exclusion->date->format('Ymd\THis');
|
||||
$exclusionTimezone = $exclusion->date->getTimezone();
|
||||
|
||||
foreach ($recurrences as $key => $recurrence) {
|
||||
$recurrenceDate = $recurrence->getStart();
|
||||
|
||||
if ($recurrenceDate->getTimezone()->getName() !== $exclusionTimezone->getName()) {
|
||||
$recurrenceDate = clone $recurrenceDate;
|
||||
$recurrenceDate = $recurrenceDate->setTimezone($exclusionTimezone);
|
||||
}
|
||||
|
||||
if (!$exclusion->hasTime && $recurrenceDate->format('Ymd') == $exclusionDate) {
|
||||
unset($recurrences[$key]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($exclusion->hasTime && $recurrenceDate->format('Ymd\THis') == $exclusionTime) {
|
||||
unset($recurrences[$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return array_values($recurrences);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DateInclusion[] $inclusions
|
||||
* @param Recurrence[] $recurrences
|
||||
*
|
||||
* @return Recurrence[]
|
||||
*/
|
||||
protected function handleInclusions(array $inclusions, array $recurrences)
|
||||
{
|
||||
foreach ($inclusions as $inclusion) {
|
||||
$recurrence = new Recurrence(clone $inclusion->date, clone $inclusion->date);
|
||||
$recurrences[] = $recurrence;
|
||||
}
|
||||
|
||||
return array_values($recurrences);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2014 Shaun Simmons
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Recurr\Transformer;
|
||||
|
||||
class ArrayTransformerConfig
|
||||
{
|
||||
/** @var int */
|
||||
protected $virtualLimit = 732;
|
||||
|
||||
protected $lastDayOfMonthFix = false;
|
||||
|
||||
/**
|
||||
* Set the virtual limit imposed upon infinitely recurring events.
|
||||
*
|
||||
* @param int $virtualLimit The limit
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setVirtualLimit($virtualLimit)
|
||||
{
|
||||
$this->virtualLimit = (int) $virtualLimit;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the virtual limit imposed upon infinitely recurring events.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getVirtualLimit()
|
||||
{
|
||||
return $this->virtualLimit;
|
||||
}
|
||||
|
||||
/**
|
||||
* By default, January 30 + 1 month results in March 30 because February doesn't have 30 days.
|
||||
*
|
||||
* Enabling this fix tells Recurr that +1 month means "last day of next month".
|
||||
*/
|
||||
public function enableLastDayOfMonthFix()
|
||||
{
|
||||
$this->lastDayOfMonthFix = true;
|
||||
}
|
||||
|
||||
public function disableLastDayOfMonthFix()
|
||||
{
|
||||
$this->lastDayOfMonthFix = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
public function isLastDayOfMonthFixEnabled()
|
||||
{
|
||||
return $this->lastDayOfMonthFix;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2014 Shaun Simmons
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Recurr\Transformer;
|
||||
|
||||
abstract class Constraint implements ConstraintInterface
|
||||
{
|
||||
|
||||
protected $stopsTransformer = true;
|
||||
|
||||
public function stopsTransformer()
|
||||
{
|
||||
return $this->stopsTransformer;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2014 Shaun Simmons
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Recurr\Transformer\Constraint;
|
||||
|
||||
use Recurr\Transformer\Constraint;
|
||||
|
||||
class AfterConstraint extends Constraint
|
||||
{
|
||||
|
||||
protected $stopsTransformer = false;
|
||||
|
||||
/** @var \DateTimeInterface */
|
||||
protected $after;
|
||||
|
||||
/** @var bool */
|
||||
protected $inc;
|
||||
|
||||
/**
|
||||
* @param \DateTimeInterface $after
|
||||
* @param bool $inc Include date if it equals $after.
|
||||
*/
|
||||
public function __construct(\DateTimeInterface $after, $inc = false)
|
||||
{
|
||||
$this->after = $after;
|
||||
$this->inc = $inc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Passes if $date is after $after
|
||||
*
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function test(\DateTimeInterface $date)
|
||||
{
|
||||
if ($this->inc) {
|
||||
return $date >= $this->after;
|
||||
}
|
||||
|
||||
return $date > $this->after;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \DateTimeInterface
|
||||
*/
|
||||
public function getAfter()
|
||||
{
|
||||
return $this->after;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isInc()
|
||||
{
|
||||
return $this->inc;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2014 Shaun Simmons
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Recurr\Transformer\Constraint;
|
||||
|
||||
use Recurr\Transformer\Constraint;
|
||||
|
||||
class BeforeConstraint extends Constraint
|
||||
{
|
||||
|
||||
protected $stopsTransformer = true;
|
||||
|
||||
/** @var \DateTimeInterface */
|
||||
protected $before;
|
||||
|
||||
/** @var bool */
|
||||
protected $inc;
|
||||
|
||||
/**
|
||||
* @param \DateTimeInterface $before
|
||||
* @param bool $inc Include date if it equals $before.
|
||||
*/
|
||||
public function __construct(\DateTimeInterface $before, $inc = false)
|
||||
{
|
||||
$this->before = $before;
|
||||
$this->inc = $inc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Passes if $date is before $before
|
||||
*
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function test(\DateTimeInterface $date)
|
||||
{
|
||||
if ($this->inc) {
|
||||
return $date <= $this->before;
|
||||
}
|
||||
|
||||
return $date < $this->before;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \DateTimeInterface
|
||||
*/
|
||||
public function getBefore()
|
||||
{
|
||||
return $this->before;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isInc()
|
||||
{
|
||||
return $this->inc;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2014 Shaun Simmons
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Recurr\Transformer\Constraint;
|
||||
|
||||
use Recurr\Transformer\Constraint;
|
||||
|
||||
class BetweenConstraint extends Constraint
|
||||
{
|
||||
|
||||
protected $stopsTransformer = false;
|
||||
|
||||
/** @var \DateTimeInterface */
|
||||
protected $before;
|
||||
|
||||
/** @var \DateTimeInterface */
|
||||
protected $after;
|
||||
|
||||
/** @var bool */
|
||||
protected $inc;
|
||||
|
||||
/**
|
||||
* @param \DateTimeInterface $after
|
||||
* @param \DateTimeInterface $before
|
||||
* @param bool $inc Include date if it equals $after or $before.
|
||||
*/
|
||||
public function __construct(\DateTimeInterface $after, \DateTimeInterface $before, $inc = false)
|
||||
{
|
||||
$this->after = $after;
|
||||
$this->before = $before;
|
||||
$this->inc = $inc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Passes if $date is between $after and $before
|
||||
*
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function test(\DateTimeInterface $date)
|
||||
{
|
||||
if ($date > $this->before) {
|
||||
$this->stopsTransformer = true;
|
||||
}
|
||||
|
||||
if ($this->inc) {
|
||||
return $date >= $this->after && $date <= $this->before;
|
||||
}
|
||||
|
||||
return $date > $this->after && $date < $this->before;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \DateTimeInterface
|
||||
*/
|
||||
public function getBefore()
|
||||
{
|
||||
return $this->before;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \DateTimeInterface
|
||||
*/
|
||||
public function getAfter()
|
||||
{
|
||||
return $this->after;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isInc()
|
||||
{
|
||||
return $this->inc;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2014 Shaun Simmons
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Recurr\Transformer;
|
||||
|
||||
interface ConstraintInterface
|
||||
{
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function stopsTransformer();
|
||||
|
||||
/**
|
||||
* @param \DateTimeInterface $date
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function test(\DateTimeInterface $date);
|
||||
}
|
||||
@@ -0,0 +1,502 @@
|
||||
<?php
|
||||
|
||||
namespace Recurr\Transformer;
|
||||
|
||||
use Recurr\Rule;
|
||||
|
||||
class TextTransformer
|
||||
{
|
||||
protected $fragments = array();
|
||||
protected $translator;
|
||||
|
||||
public function __construct(TranslatorInterface $translator = null)
|
||||
{
|
||||
$this->translator = $translator ?: new Translator('en');
|
||||
}
|
||||
|
||||
public function transform(Rule $rule)
|
||||
{
|
||||
$this->fragments = array();
|
||||
|
||||
switch ($rule->getFreq()) {
|
||||
case 0:
|
||||
$this->addYearly($rule);
|
||||
break;
|
||||
case 1:
|
||||
$this->addMonthly($rule);
|
||||
break;
|
||||
case 2:
|
||||
$this->addWeekly($rule);
|
||||
break;
|
||||
case 3:
|
||||
$this->addDaily($rule);
|
||||
break;
|
||||
case 4:
|
||||
$this->addHourly($rule);
|
||||
break;
|
||||
case 5:
|
||||
case 6:
|
||||
return $this->translator->trans('Unable to fully convert this rrule to text.');
|
||||
}
|
||||
|
||||
$until = $rule->getUntil();
|
||||
$count = $rule->getCount();
|
||||
if ($until instanceof \DateTimeInterface) {
|
||||
$dateFormatted = $this->translator->trans('day_date', array('date' => $until->format('U')));
|
||||
$this->addFragment($this->translator->trans('until %date%', array('date' => $dateFormatted)));
|
||||
} else if (!empty($count)) {
|
||||
if ($this->isPlural($count)) {
|
||||
$this->addFragment($this->translator->trans('for %count% times', array('count' => $count)));
|
||||
} else {
|
||||
$this->addFragment($this->translator->trans('for one time'));
|
||||
}
|
||||
}
|
||||
|
||||
if (!$this->isFullyConvertible($rule)) {
|
||||
$this->addFragment($this->translator->trans('(~ approximate)'));
|
||||
}
|
||||
|
||||
return implode(' ', $this->fragments);
|
||||
}
|
||||
|
||||
protected function isFullyConvertible(Rule $rule)
|
||||
{
|
||||
if ($rule->getFreq() >= 5) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$until = $rule->getUntil();
|
||||
$count = $rule->getCount();
|
||||
if (!empty($until) && !empty($count)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$bySecond = $rule->getBySecond();
|
||||
$byMinute = $rule->getByMinute();
|
||||
$byHour = $rule->getByHour();
|
||||
|
||||
if (!empty($bySecond) || !empty($byMinute) || !empty($byHour)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$byWeekNum = $rule->getByWeekNumber();
|
||||
$byYearDay = $rule->getByYearDay();
|
||||
if ($rule->getFreq() != 0 && (!empty($byWeekNum) || !empty($byYearDay))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function addYearly(Rule $rule)
|
||||
{
|
||||
$interval = $rule->getInterval();
|
||||
$byMonth = $rule->getByMonth();
|
||||
$byMonthDay = $rule->getByMonthDay();
|
||||
$byDay = $rule->getByDay();
|
||||
$byYearDay = $rule->getByYearDay();
|
||||
$byWeekNum = $rule->getByWeekNumber();
|
||||
|
||||
if (!empty($byMonth) && count($byMonth) > 1 && $interval == 1) {
|
||||
$this->addFragment($this->translator->trans('every_month_list'));
|
||||
} else {
|
||||
$this->addFragment($this->translator->trans($this->isPlural($interval) ? 'every %count% years' : 'every year', array('count' => $interval)));
|
||||
}
|
||||
|
||||
$hasNoOrOneByMonth = is_null($byMonth) || count($byMonth) <= 1;
|
||||
if ($hasNoOrOneByMonth && empty($byMonthDay) && empty($byDay) && empty($byYearDay) && empty($byWeekNum)) {
|
||||
$this->addFragment($this->translator->trans('on'));
|
||||
$monthNum = (is_array($byMonth) && count($byMonth)) ? $byMonth[0] : $rule->getStartDate()->format('n');
|
||||
$this->addFragment(
|
||||
$this->translator->trans('day_month', array('month' => $monthNum, 'day' => $rule->getStartDate()->format('d')))
|
||||
);
|
||||
} elseif (!empty($byMonth)) {
|
||||
if ($interval != 1) {
|
||||
$this->addFragment($this->translator->trans('in_month'));
|
||||
}
|
||||
|
||||
$this->addByMonth($rule);
|
||||
}
|
||||
|
||||
if (!empty($byMonthDay)) {
|
||||
$this->addByMonthDay($rule);
|
||||
$this->addFragment($this->translator->trans('of_the_month'));
|
||||
} else if (!empty($byDay)) {
|
||||
$this->addByDay($rule);
|
||||
}
|
||||
|
||||
if (!empty($byYearDay)) {
|
||||
$this->addFragment($this->translator->trans('on the'));
|
||||
$this->addFragment($this->getByYearDayAsText($byYearDay));
|
||||
$this->addFragment($this->translator->trans('day'));
|
||||
}
|
||||
|
||||
if (!empty($byWeekNum)) {
|
||||
$this->addFragment($this->translator->trans('in_week'));
|
||||
$this->addFragment($this->translator->trans($this->isPlural(count($byWeekNum)) ? 'weeks' : 'week'));
|
||||
$this->addFragment($this->getByWeekNumberAsText($byWeekNum));
|
||||
}
|
||||
|
||||
if (empty($byMonthDay) && empty($byYearDay) && empty($byDay) && !empty($byWeekNum)) {
|
||||
$this->addDayOfWeek($rule);
|
||||
}
|
||||
}
|
||||
|
||||
protected function addMonthly(Rule $rule)
|
||||
{
|
||||
$interval = $rule->getInterval();
|
||||
$byMonth = $rule->getByMonth();
|
||||
|
||||
if (!empty($byMonth) && $interval == 1) {
|
||||
$this->addFragment($this->translator->trans('every_month_list'));
|
||||
} else {
|
||||
$this->addFragment($this->translator->trans($this->isPlural($interval) ? 'every %count% months' : 'every month', array('count' => $interval)));
|
||||
}
|
||||
|
||||
if (!empty($byMonth)) {
|
||||
if ($interval != 1) {
|
||||
$this->addFragment($this->translator->trans('in_month'));
|
||||
}
|
||||
|
||||
$this->addByMonth($rule);
|
||||
}
|
||||
|
||||
$byMonthDay = $rule->getByMonthDay();
|
||||
$byDay = $rule->getByDay();
|
||||
if (!empty($byMonthDay)) {
|
||||
$this->addByMonthDay($rule);
|
||||
} else if (!empty($byDay)) {
|
||||
$this->addByDay($rule);
|
||||
}
|
||||
}
|
||||
|
||||
protected function addWeekly(Rule $rule)
|
||||
{
|
||||
$interval = $rule->getInterval();
|
||||
$byMonth = $rule->getByMonth();
|
||||
$byMonthDay = $rule->getByMonthDay();
|
||||
$byDay = $rule->getByDay();
|
||||
|
||||
$this->addFragment($this->translator->trans($this->isPlural($interval) ? 'every %count% weeks' : 'every week', array('count' => $interval)));
|
||||
|
||||
if (empty($byMonthDay) && empty($byDay)) {
|
||||
$this->addDayOfWeek($rule);
|
||||
}
|
||||
|
||||
if (!empty($byMonth)) {
|
||||
$this->addFragment($this->translator->trans('in_month'));
|
||||
$this->addByMonth($rule);
|
||||
}
|
||||
|
||||
if (!empty($byMonthDay)) {
|
||||
$this->addByMonthDay($rule);
|
||||
$this->addFragment($this->translator->trans('of_the_month'));
|
||||
} else if (!empty($byDay)) {
|
||||
$this->addByDay($rule);
|
||||
}
|
||||
}
|
||||
|
||||
protected function addDaily(Rule $rule)
|
||||
{
|
||||
$interval = $rule->getInterval();
|
||||
$byMonth = $rule->getByMonth();
|
||||
|
||||
$this->addFragment($this->translator->trans($this->isPlural($interval) ? 'every %count% days' : 'every day', array('count' => $interval)));
|
||||
|
||||
if (!empty($byMonth)) {
|
||||
$this->addFragment($this->translator->trans('in_month'));
|
||||
$this->addByMonth($rule);
|
||||
}
|
||||
|
||||
$byMonthDay = $rule->getByMonthDay();
|
||||
$byDay = $rule->getByDay();
|
||||
if (!empty($byMonthDay)) {
|
||||
$this->addByMonthDay($rule);
|
||||
$this->addFragment($this->translator->trans('of_the_month'));
|
||||
} else if (!empty($byDay)) {
|
||||
$this->addByDay($rule);
|
||||
}
|
||||
}
|
||||
|
||||
protected function addHourly(Rule $rule)
|
||||
{
|
||||
$interval = $rule->getInterval();
|
||||
$byMonth = $rule->getByMonth();
|
||||
|
||||
$this->addFragment($this->translator->trans($this->isPlural($interval) ? 'every %count% hours' : 'every hour', array('count' => $interval)));
|
||||
|
||||
if (!empty($byMonth)) {
|
||||
$this->addFragment($this->translator->trans('in_month'));
|
||||
$this->addByMonth($rule);
|
||||
}
|
||||
|
||||
$byMonthDay = $rule->getByMonthDay();
|
||||
$byDay = $rule->getByDay();
|
||||
if (!empty($byMonthDay)) {
|
||||
$this->addByMonthDay($rule);
|
||||
$this->addFragment($this->translator->trans('of_the_month'));
|
||||
} else if (!empty($byDay)) {
|
||||
$this->addByDay($rule);
|
||||
}
|
||||
}
|
||||
|
||||
protected function addByMonth(Rule $rule)
|
||||
{
|
||||
$byMonth = $rule->getByMonth();
|
||||
|
||||
if (empty($byMonth)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->addFragment($this->getByMonthAsText($byMonth));
|
||||
}
|
||||
|
||||
protected function addByMonthDay(Rule $rule)
|
||||
{
|
||||
$byMonthDay = $rule->getByMonthDay();
|
||||
$byDay = $rule->getByDay();
|
||||
|
||||
if (!empty($byDay)) {
|
||||
$this->addFragment($this->translator->trans('on'));
|
||||
$this->addFragment($this->getByDayAsText($byDay, 'or'));
|
||||
$this->addFragment($this->translator->trans('the_for_monthday'));
|
||||
$this->addFragment($this->getByMonthDayAsText($byMonthDay, 'or'));
|
||||
} else {
|
||||
$this->addFragment($this->translator->trans('on the'));
|
||||
$this->addFragment($this->getByMonthDayAsText($byMonthDay, 'and'));
|
||||
}
|
||||
}
|
||||
|
||||
protected function addByDay(Rule $rule)
|
||||
{
|
||||
$byDay = $rule->getByDay();
|
||||
|
||||
$this->addFragment($this->translator->trans('on'));
|
||||
$this->addFragment($this->getByDayAsText($byDay));
|
||||
}
|
||||
|
||||
protected function addDayOfWeek(Rule $rule)
|
||||
{
|
||||
$this->addFragment($this->translator->trans('on'));
|
||||
$dayNames = $this->translator->trans('day_names');
|
||||
$this->addFragment($dayNames[$rule->getStartDate()->format('w')]);
|
||||
}
|
||||
|
||||
public function getByMonthAsText($byMonth)
|
||||
{
|
||||
if (empty($byMonth)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (count($byMonth) > 1) {
|
||||
sort($byMonth);
|
||||
}
|
||||
|
||||
$monthNames = $this->translator->trans('month_names');
|
||||
$byMonth = array_map(
|
||||
function ($monthInt) use ($monthNames) {
|
||||
return $monthNames[$monthInt - 1];
|
||||
},
|
||||
$byMonth
|
||||
);
|
||||
|
||||
return $this->getListStringFromArray($byMonth);
|
||||
}
|
||||
|
||||
public function getByDayAsText($byDay, $listSeparator = 'and')
|
||||
{
|
||||
if (empty($byDay)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$map = array(
|
||||
'SU' => null,
|
||||
'MO' => null,
|
||||
'TU' => null,
|
||||
'WE' => null,
|
||||
'TH' => null,
|
||||
'FR' => null,
|
||||
'SA' => null
|
||||
);
|
||||
|
||||
$dayNames = $this->translator->trans('day_names');
|
||||
$timestamp = mktime(1, 1, 1, 1, 12, 2014); // A Sunday
|
||||
foreach (array_keys($map) as $short) {
|
||||
$long = $dayNames[date('w', $timestamp)];
|
||||
$map[$short] = $long;
|
||||
$timestamp += 86400;
|
||||
}
|
||||
|
||||
$numOrdinals = 0;
|
||||
foreach ($byDay as $key => $short) {
|
||||
$day = strtoupper($short);
|
||||
$string = '';
|
||||
|
||||
if (preg_match('/([+-]?)([0-9]*)([A-Z]+)/', $short, $parts)) {
|
||||
$symbol = $parts[1];
|
||||
$nth = $parts[2];
|
||||
$day = $parts[3];
|
||||
|
||||
if (!empty($nth)) {
|
||||
++$numOrdinals;
|
||||
$string .= $this->getOrdinalNumber($symbol == '-' ? -$nth : $nth);
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($map[$day])) {
|
||||
throw new \RuntimeException("byDay $short could not be transformed");
|
||||
}
|
||||
|
||||
if (!empty($string)) {
|
||||
$string .= ' ';
|
||||
}
|
||||
|
||||
$byDay[$key] = ltrim($string.$map[$day]);
|
||||
}
|
||||
|
||||
$output = $numOrdinals ? $this->translator->trans('the_for_weekday') . ' ' : '';
|
||||
if ($output == ' ') {
|
||||
$output = '';
|
||||
}
|
||||
$output .= $this->getListStringFromArray($byDay, $listSeparator);
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
public function getByMonthDayAsText($byMonthDay, $listSeparator = 'and')
|
||||
{
|
||||
if (empty($byMonthDay)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
// sort negative indices in reverse order so we get e.g. 1st, 2nd, 4th, 3rd last, last day
|
||||
usort($byMonthDay, function ($a, $b) {
|
||||
if (($a < 0 && $b < 0) || ($a >= 0 && $b >= 0)) {
|
||||
return $a - $b;
|
||||
}
|
||||
|
||||
return $b - $a;
|
||||
});
|
||||
|
||||
// generate ordinal numbers and insert a "on the" for clarity in the middle if we have both
|
||||
// positive and negative ordinals. This is to avoid confusing situations like:
|
||||
//
|
||||
// monthly on the 1st and 2nd to the last day
|
||||
//
|
||||
// which gets clarified to:
|
||||
//
|
||||
// monthly on the 1st day and on the 2nd to the last day
|
||||
$hadPositives = false;
|
||||
$hadNegatives = false;
|
||||
foreach ($byMonthDay as $index => $day) {
|
||||
$prefix = '';
|
||||
if ($day >= 0) {
|
||||
$hadPositives = true;
|
||||
}
|
||||
if ($day < 0) {
|
||||
if ($hadPositives && !$hadNegatives && $listSeparator === 'and') {
|
||||
$prefix = $this->translator->trans('on the') . ' ';
|
||||
}
|
||||
$hadNegatives = true;
|
||||
}
|
||||
$byMonthDay[$index] = $prefix . $this->getOrdinalNumber($day, end($byMonthDay) < 0, true);
|
||||
}
|
||||
|
||||
return $this->getListStringFromArray($byMonthDay, $listSeparator);
|
||||
}
|
||||
|
||||
public function getByYearDayAsText($byYearDay)
|
||||
{
|
||||
if (empty($byYearDay)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
// sort negative indices in reverse order so we get e.g. 1st, 2nd, 4th, 3rd last, last day
|
||||
usort($byYearDay, function ($a, $b) {
|
||||
if (($a < 0 && $b < 0) || ($a >= 0 && $b >= 0)) {
|
||||
return $a - $b;
|
||||
}
|
||||
|
||||
return $b - $a;
|
||||
});
|
||||
|
||||
$byYearDay = array_map(
|
||||
array($this, 'getOrdinalNumber'),
|
||||
$byYearDay,
|
||||
array_fill(0, count($byYearDay), end($byYearDay) < 0)
|
||||
);
|
||||
|
||||
return $this->getListStringFromArray($byYearDay);
|
||||
}
|
||||
|
||||
public function getByWeekNumberAsText($byWeekNum)
|
||||
{
|
||||
if (empty($byWeekNum)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (count($byWeekNum) > 1) {
|
||||
sort($byWeekNum);
|
||||
}
|
||||
|
||||
return $this->getListStringFromArray($byWeekNum);
|
||||
}
|
||||
|
||||
protected function addFragment($fragment)
|
||||
{
|
||||
if ($fragment && $fragment !== ' ') {
|
||||
$this->fragments[] = $fragment;
|
||||
}
|
||||
}
|
||||
|
||||
public function resetFragments()
|
||||
{
|
||||
$this->fragments = array();
|
||||
}
|
||||
|
||||
protected function isPlural($number)
|
||||
{
|
||||
return $number % 100 != 1;
|
||||
}
|
||||
|
||||
|
||||
protected function getOrdinalNumber($number, $hasNegatives = false, $dayInMonth = false)
|
||||
{
|
||||
if (!preg_match('{^-?\d+$}D', $number)) {
|
||||
throw new \RuntimeException('$number must be a whole number');
|
||||
}
|
||||
|
||||
return $this->translator->trans('ordinal_number', array('number' => $number, 'has_negatives' => $hasNegatives, 'day_in_month' => $dayInMonth));
|
||||
}
|
||||
|
||||
protected function getListStringFromArray($values, $separator = 'and')
|
||||
{
|
||||
$separator = $this->translator->trans($separator);
|
||||
|
||||
if (!is_array($values)) {
|
||||
throw new \RuntimeException('$values must be an array.');
|
||||
}
|
||||
|
||||
$numValues = count($values);
|
||||
|
||||
if (!$numValues) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if ($numValues == 1) {
|
||||
reset($values);
|
||||
|
||||
return current($values);
|
||||
}
|
||||
|
||||
if ($numValues == 2) {
|
||||
return implode(" $separator ", $values);
|
||||
}
|
||||
|
||||
$lastValue = array_pop($values);
|
||||
$output = implode(', ', $values);
|
||||
$output .= " $separator ".$lastValue;
|
||||
|
||||
return $output;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace Recurr\Transformer;
|
||||
|
||||
class Translator implements TranslatorInterface
|
||||
{
|
||||
protected $data = array();
|
||||
|
||||
public function __construct($locale = 'en', $fallbackLocale = 'en')
|
||||
{
|
||||
$this->loadLocale($fallbackLocale);
|
||||
if ($locale !== $fallbackLocale) {
|
||||
$this->loadLocale($locale);
|
||||
}
|
||||
}
|
||||
|
||||
public function loadLocale($locale, $path = null)
|
||||
{
|
||||
if (!$path) {
|
||||
$path = __DIR__ . '/../../../translations/' . $locale . '.php';
|
||||
}
|
||||
if (!file_exists($path)) {
|
||||
throw new \InvalidArgumentException('Locale '.$locale.' could not be found in '.$path);
|
||||
}
|
||||
|
||||
$this->data = array_merge($this->data, include $path);
|
||||
}
|
||||
|
||||
public function trans($string, array $params = array())
|
||||
{
|
||||
$res = $this->data[$string];
|
||||
if (is_object($res) && is_callable($res)) {
|
||||
$res = $res($string, $params);
|
||||
}
|
||||
|
||||
foreach ($params as $key => $val) {
|
||||
$res = str_replace('%' . $key . '%', $val, $res);
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace Recurr\Transformer;
|
||||
|
||||
interface TranslatorInterface
|
||||
{
|
||||
public function trans($string);
|
||||
}
|
||||
72
old.vendor/simshaun/recurr/src/Recurr/Weekday.php
Normal file
72
old.vendor/simshaun/recurr/src/Recurr/Weekday.php
Normal file
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2013 Shaun Simmons
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* Based on rrule.js
|
||||
* Copyright 2010, Jakub Roztocil and Lars Schoning
|
||||
* https://github.com/jkbr/rrule/blob/master/LICENCE
|
||||
*/
|
||||
|
||||
namespace Recurr;
|
||||
|
||||
use Recurr\Exception\InvalidWeekday;
|
||||
|
||||
/**
|
||||
* Class Weekday is a storage container for a day of the week.
|
||||
*
|
||||
* @package Recurr
|
||||
* @author Shaun Simmons <shaun@envysphere.com>
|
||||
*/
|
||||
class Weekday
|
||||
{
|
||||
/**
|
||||
* Weekday number.
|
||||
*
|
||||
* 0 = Sunday
|
||||
* 1 = Monday
|
||||
* 2 = Tuesday
|
||||
* 3 = Wednesday
|
||||
* 4 = Thursday
|
||||
* 5 = Friday
|
||||
* 6 = Saturday
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $weekday;
|
||||
|
||||
/** @var int nth occurrence of the weekday */
|
||||
public $num;
|
||||
|
||||
protected $days = array('MO', 'TU', 'WE', 'TH', 'FR', 'SA', 'SU');
|
||||
|
||||
/**
|
||||
* @param int|string $weekday 0-6 or MO..SU
|
||||
* @param null|int $num
|
||||
*
|
||||
* @throws InvalidWeekday
|
||||
*/
|
||||
public function __construct($weekday, $num)
|
||||
{
|
||||
if (is_numeric($weekday) && $weekday > 6 || $weekday < 0) {
|
||||
throw new InvalidWeekday('Day is not a valid weekday (0-6)');
|
||||
} elseif (!is_numeric($weekday) && !in_array($weekday, $this->days)) {
|
||||
throw new InvalidWeekday('Day is not a valid weekday (SU, MO, ...)');
|
||||
}
|
||||
|
||||
if (!is_numeric($weekday)) {
|
||||
$weekday = array_search($weekday, $this->days);
|
||||
}
|
||||
|
||||
$this->weekday = $weekday;
|
||||
$this->num = $num;
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return $this->num . $this->days[$this->weekday];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user