Laravel 5.6 updates
Travis config update Removed HHVM script as Laravel no longer support HHVM after releasing 5.3
This commit is contained in:
16
vendor/dragonmantank/cron-expression/.editorconfig
vendored
Normal file
16
vendor/dragonmantank/cron-expression/.editorconfig
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[*.yml]
|
||||
indent_style = space
|
||||
indent_size = 2
|
66
vendor/dragonmantank/cron-expression/CHANGELOG.md
vendored
Normal file
66
vendor/dragonmantank/cron-expression/CHANGELOG.md
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
# Change Log
|
||||
|
||||
## [2.2.0] - 2018-06-05
|
||||
### Added
|
||||
- Added support for steps larger than field ranges (#6)
|
||||
## Changed
|
||||
- N/A
|
||||
### Fixed
|
||||
- Fixed validation for numbers with leading 0s (#12)
|
||||
|
||||
## [2.1.0] - 2018-04-06
|
||||
### Added
|
||||
- N/A
|
||||
### Changed
|
||||
- Upgraded to PHPUnit 6 (#2)
|
||||
### Fixed
|
||||
- Refactored timezones to deal with some inconsistent behavior (#3)
|
||||
- Allow ranges and lists in same expression (#5)
|
||||
- Fixed regression where literals were not converted to their numerical counterpart (#)
|
||||
|
||||
## [2.0.0] - 2017-10-12
|
||||
### Added
|
||||
- N/A
|
||||
|
||||
### Changed
|
||||
- Dropped support for PHP 5.x
|
||||
- Dropped support for the YEAR field, as it was not part of the cron standard
|
||||
|
||||
### Fixed
|
||||
- Reworked validation for all the field types
|
||||
- Stepping should now work for 1-indexed fields like Month (#153)
|
||||
|
||||
## [1.2.0] - 2017-01-22
|
||||
### Added
|
||||
- Added IDE, CodeSniffer, and StyleCI.IO support
|
||||
|
||||
### Changed
|
||||
- Switched to PSR-4 Autoloading
|
||||
|
||||
### Fixed
|
||||
- 0 step expressions are handled better
|
||||
- Fixed `DayOfMonth` validation to be more strict
|
||||
- Typos
|
||||
|
||||
## [1.1.0] - 2016-01-26
|
||||
### Added
|
||||
- Support for non-hourly offset timezones
|
||||
- Checks for valid expressions
|
||||
|
||||
### Changed
|
||||
- Max Iterations no longer hardcoded for `getRunDate()`
|
||||
- Supports DateTimeImmutable for newer PHP verions
|
||||
|
||||
### Fixed
|
||||
- Fixed looping bug for PHP 7 when determining the last specified weekday of a month
|
||||
|
||||
## [1.0.3] - 2013-11-23
|
||||
### Added
|
||||
- Now supports expressions with any number of extra spaces, tabs, or newlines
|
||||
|
||||
### Changed
|
||||
- Using static instead of self in `CronExpression::factory`
|
||||
|
||||
### Fixed
|
||||
- Fixes issue [#28](https://github.com/mtdowling/cron-expression/issues/28) where PHP increments of ranges were failing due to PHP casting hyphens to 0
|
||||
- Only set default timezone if the given $currentTime is not a DateTime instance ([#34](https://github.com/mtdowling/cron-expression/issues/34))
|
19
vendor/dragonmantank/cron-expression/LICENSE
vendored
Normal file
19
vendor/dragonmantank/cron-expression/LICENSE
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
Copyright (c) 2011 Michael Dowling <mtdowling@gmail.com>, 2016 Chris Tankersley <chris@ctankersley.com>, and contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
73
vendor/dragonmantank/cron-expression/README.md
vendored
Normal file
73
vendor/dragonmantank/cron-expression/README.md
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
PHP Cron Expression Parser
|
||||
==========================
|
||||
|
||||
[](https://packagist.org/packages/dragonmantank/cron-expression) [](https://packagist.org/packages/dragonmantank/cron-expression) [](http://travis-ci.org/dragonmantank/cron-expression)
|
||||
|
||||
The PHP cron expression parser can parse a CRON expression, determine if it is
|
||||
due to run, calculate the next run date of the expression, and calculate the previous
|
||||
run date of the expression. You can calculate dates far into the future or past by
|
||||
skipping n number of matching dates.
|
||||
|
||||
The parser can handle increments of ranges (e.g. */12, 2-59/3), intervals (e.g. 0-9),
|
||||
lists (e.g. 1,2,3), W to find the nearest weekday for a given day of the month, L to
|
||||
find the last day of the month, L to find the last given weekday of a month, and hash
|
||||
(#) to find the nth weekday of a given month.
|
||||
|
||||
More information about this fork can be found in the blog post [here](http://ctankersley.com/2017/10/12/cron-expression-update/). tl;dr - v2.0.0 is a major breaking change, and @dragonmantank can better take care of the project in a separate fork.
|
||||
|
||||
Installing
|
||||
==========
|
||||
|
||||
Add the dependency to your project:
|
||||
|
||||
```bash
|
||||
composer require dragonmantank/cron-expression
|
||||
```
|
||||
|
||||
Usage
|
||||
=====
|
||||
```php
|
||||
<?php
|
||||
|
||||
require_once '/vendor/autoload.php';
|
||||
|
||||
// Works with predefined scheduling definitions
|
||||
$cron = Cron\CronExpression::factory('@daily');
|
||||
$cron->isDue();
|
||||
echo $cron->getNextRunDate()->format('Y-m-d H:i:s');
|
||||
echo $cron->getPreviousRunDate()->format('Y-m-d H:i:s');
|
||||
|
||||
// Works with complex expressions
|
||||
$cron = Cron\CronExpression::factory('3-59/15 6-12 */15 1 2-5');
|
||||
echo $cron->getNextRunDate()->format('Y-m-d H:i:s');
|
||||
|
||||
// Calculate a run date two iterations into the future
|
||||
$cron = Cron\CronExpression::factory('@daily');
|
||||
echo $cron->getNextRunDate(null, 2)->format('Y-m-d H:i:s');
|
||||
|
||||
// Calculate a run date relative to a specific time
|
||||
$cron = Cron\CronExpression::factory('@monthly');
|
||||
echo $cron->getNextRunDate('2010-01-12 00:00:00')->format('Y-m-d H:i:s');
|
||||
```
|
||||
|
||||
CRON Expressions
|
||||
================
|
||||
|
||||
A CRON expression is a string representing the schedule for a particular command to execute. The parts of a CRON schedule are as follows:
|
||||
|
||||
* * * * *
|
||||
- - - - -
|
||||
| | | | |
|
||||
| | | | |
|
||||
| | | | +----- day of week (0 - 7) (Sunday=0 or 7)
|
||||
| | | +---------- month (1 - 12)
|
||||
| | +--------------- day of month (1 - 31)
|
||||
| +-------------------- hour (0 - 23)
|
||||
+------------------------- min (0 - 59)
|
||||
|
||||
Requirements
|
||||
============
|
||||
|
||||
- PHP 7.0+
|
||||
- PHPUnit is required to run the unit tests
|
||||
- Composer is required to run the unit tests
|
35
vendor/dragonmantank/cron-expression/composer.json
vendored
Normal file
35
vendor/dragonmantank/cron-expression/composer.json
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"name": "dragonmantank/cron-expression",
|
||||
"type": "library",
|
||||
"description": "CRON for PHP: Calculate the next or previous run date and determine if a CRON expression is due",
|
||||
"keywords": ["cron", "schedule"],
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Michael Dowling",
|
||||
"email": "mtdowling@gmail.com",
|
||||
"homepage": "https://github.com/mtdowling"
|
||||
},
|
||||
{
|
||||
"name": "Chris Tankersley",
|
||||
"email": "chris@ctankersley.com",
|
||||
"homepage": "https://github.com/dragonmantank"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=7.0.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~6.4"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Cron\\": "src/Cron/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Tests\\": "tests/Cron/"
|
||||
}
|
||||
}
|
||||
}
|
278
vendor/dragonmantank/cron-expression/src/Cron/AbstractField.php
vendored
Normal file
278
vendor/dragonmantank/cron-expression/src/Cron/AbstractField.php
vendored
Normal file
@@ -0,0 +1,278 @@
|
||||
<?php
|
||||
|
||||
namespace Cron;
|
||||
|
||||
/**
|
||||
* Abstract CRON expression field
|
||||
*/
|
||||
abstract class AbstractField implements FieldInterface
|
||||
{
|
||||
/**
|
||||
* Full range of values that are allowed for this field type
|
||||
* @var array
|
||||
*/
|
||||
protected $fullRange = [];
|
||||
|
||||
/**
|
||||
* Literal values we need to convert to integers
|
||||
* @var array
|
||||
*/
|
||||
protected $literals = [];
|
||||
|
||||
/**
|
||||
* Start value of the full range
|
||||
* @var integer
|
||||
*/
|
||||
protected $rangeStart;
|
||||
|
||||
/**
|
||||
* End value of the full range
|
||||
* @var integer
|
||||
*/
|
||||
protected $rangeEnd;
|
||||
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->fullRange = range($this->rangeStart, $this->rangeEnd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if a field is satisfied by a value
|
||||
*
|
||||
* @param string $dateValue Date value to check
|
||||
* @param string $value Value to test
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isSatisfied($dateValue, $value)
|
||||
{
|
||||
if ($this->isIncrementsOfRanges($value)) {
|
||||
return $this->isInIncrementsOfRanges($dateValue, $value);
|
||||
} elseif ($this->isRange($value)) {
|
||||
return $this->isInRange($dateValue, $value);
|
||||
}
|
||||
|
||||
return $value == '*' || $dateValue == $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a value is a range
|
||||
*
|
||||
* @param string $value Value to test
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isRange($value)
|
||||
{
|
||||
return strpos($value, '-') !== false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a value is an increments of ranges
|
||||
*
|
||||
* @param string $value Value to test
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isIncrementsOfRanges($value)
|
||||
{
|
||||
return strpos($value, '/') !== false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if a value is within a range
|
||||
*
|
||||
* @param string $dateValue Set date value
|
||||
* @param string $value Value to test
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isInRange($dateValue, $value)
|
||||
{
|
||||
$parts = array_map(function($value) {
|
||||
$value = trim($value);
|
||||
$value = $this->convertLiterals($value);
|
||||
return $value;
|
||||
},
|
||||
explode('-', $value, 2)
|
||||
);
|
||||
|
||||
|
||||
return $dateValue >= $parts[0] && $dateValue <= $parts[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if a value is within an increments of ranges (offset[-to]/step size)
|
||||
*
|
||||
* @param string $dateValue Set date value
|
||||
* @param string $value Value to test
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isInIncrementsOfRanges($dateValue, $value)
|
||||
{
|
||||
$chunks = array_map('trim', explode('/', $value, 2));
|
||||
$range = $chunks[0];
|
||||
$step = isset($chunks[1]) ? $chunks[1] : 0;
|
||||
|
||||
// No step or 0 steps aren't cool
|
||||
if (is_null($step) || '0' === $step || 0 === $step) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Expand the * to a full range
|
||||
if ('*' == $range) {
|
||||
$range = $this->rangeStart . '-' . $this->rangeEnd;
|
||||
}
|
||||
|
||||
// Generate the requested small range
|
||||
$rangeChunks = explode('-', $range, 2);
|
||||
$rangeStart = $rangeChunks[0];
|
||||
$rangeEnd = isset($rangeChunks[1]) ? $rangeChunks[1] : $rangeStart;
|
||||
|
||||
if ($rangeStart < $this->rangeStart || $rangeStart > $this->rangeEnd || $rangeStart > $rangeEnd) {
|
||||
throw new \OutOfRangeException('Invalid range start requested');
|
||||
}
|
||||
|
||||
if ($rangeEnd < $this->rangeStart || $rangeEnd > $this->rangeEnd || $rangeEnd < $rangeStart) {
|
||||
throw new \OutOfRangeException('Invalid range end requested');
|
||||
}
|
||||
|
||||
// Steps larger than the range need to wrap around and be handled slightly differently than smaller steps
|
||||
if ($step >= $this->rangeEnd) {
|
||||
$thisRange = [$this->fullRange[$step % count($this->fullRange)]];
|
||||
} else {
|
||||
$thisRange = range($rangeStart, $rangeEnd, $step);
|
||||
}
|
||||
|
||||
return in_array($dateValue, $thisRange);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a range of values for the given cron expression
|
||||
*
|
||||
* @param string $expression The expression to evaluate
|
||||
* @param int $max Maximum offset for range
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getRangeForExpression($expression, $max)
|
||||
{
|
||||
$values = array();
|
||||
$expression = $this->convertLiterals($expression);
|
||||
|
||||
if (strpos($expression, ',') !== false) {
|
||||
$ranges = explode(',', $expression);
|
||||
$values = [];
|
||||
foreach ($ranges as $range) {
|
||||
$expanded = $this->getRangeForExpression($range, $this->rangeEnd);
|
||||
$values = array_merge($values, $expanded);
|
||||
}
|
||||
return $values;
|
||||
}
|
||||
|
||||
if ($this->isRange($expression) || $this->isIncrementsOfRanges($expression)) {
|
||||
if (!$this->isIncrementsOfRanges($expression)) {
|
||||
list ($offset, $to) = explode('-', $expression);
|
||||
$offset = $this->convertLiterals($offset);
|
||||
$to = $this->convertLiterals($to);
|
||||
$stepSize = 1;
|
||||
}
|
||||
else {
|
||||
$range = array_map('trim', explode('/', $expression, 2));
|
||||
$stepSize = isset($range[1]) ? $range[1] : 0;
|
||||
$range = $range[0];
|
||||
$range = explode('-', $range, 2);
|
||||
$offset = $range[0];
|
||||
$to = isset($range[1]) ? $range[1] : $max;
|
||||
}
|
||||
$offset = $offset == '*' ? $this->rangeStart : $offset;
|
||||
if ($stepSize >= $this->rangeEnd) {
|
||||
$values = [$this->fullRange[$stepSize % count($this->fullRange)]];
|
||||
} else {
|
||||
for ($i = $offset; $i <= $to; $i += $stepSize) {
|
||||
$values[] = (int)$i;
|
||||
}
|
||||
}
|
||||
sort($values);
|
||||
}
|
||||
else {
|
||||
$values = array($expression);
|
||||
}
|
||||
|
||||
return $values;
|
||||
}
|
||||
|
||||
protected function convertLiterals($value)
|
||||
{
|
||||
if (count($this->literals)) {
|
||||
$key = array_search($value, $this->literals);
|
||||
if ($key !== false) {
|
||||
return $key;
|
||||
}
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if a value is valid for the field
|
||||
*
|
||||
* @param string $value
|
||||
* @return bool
|
||||
*/
|
||||
public function validate($value)
|
||||
{
|
||||
$value = $this->convertLiterals($value);
|
||||
|
||||
// All fields allow * as a valid value
|
||||
if ('*' === $value) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (strpos($value, '/') !== false) {
|
||||
list($range, $step) = explode('/', $value);
|
||||
return $this->validate($range) && filter_var($step, FILTER_VALIDATE_INT);
|
||||
}
|
||||
|
||||
// Validate each chunk of a list individually
|
||||
if (strpos($value, ',') !== false) {
|
||||
foreach (explode(',', $value) as $listItem) {
|
||||
if (!$this->validate($listItem)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (strpos($value, '-') !== false) {
|
||||
if (substr_count($value, '-') > 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$chunks = explode('-', $value);
|
||||
$chunks[0] = $this->convertLiterals($chunks[0]);
|
||||
$chunks[1] = $this->convertLiterals($chunks[1]);
|
||||
|
||||
if ('*' == $chunks[0] || '*' == $chunks[1]) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->validate($chunks[0]) && $this->validate($chunks[1]);
|
||||
}
|
||||
|
||||
if (!is_numeric($value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (is_float($value) || strpos($value, '.') !== false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We should have a numeric by now, so coerce this into an integer
|
||||
$value = (int) $value;
|
||||
|
||||
return in_array($value, $this->fullRange, true);
|
||||
}
|
||||
}
|
411
vendor/dragonmantank/cron-expression/src/Cron/CronExpression.php
vendored
Normal file
411
vendor/dragonmantank/cron-expression/src/Cron/CronExpression.php
vendored
Normal file
@@ -0,0 +1,411 @@
|
||||
<?php
|
||||
|
||||
namespace Cron;
|
||||
|
||||
use DateTime;
|
||||
use DateTimeImmutable;
|
||||
use DateTimeZone;
|
||||
use Exception;
|
||||
use InvalidArgumentException;
|
||||
use RuntimeException;
|
||||
|
||||
/**
|
||||
* CRON expression parser that can determine whether or not a CRON expression is
|
||||
* due to run, the next run date and previous run date of a CRON expression.
|
||||
* The determinations made by this class are accurate if checked run once per
|
||||
* minute (seconds are dropped from date time comparisons).
|
||||
*
|
||||
* Schedule parts must map to:
|
||||
* minute [0-59], hour [0-23], day of month, month [1-12|JAN-DEC], day of week
|
||||
* [1-7|MON-SUN], and an optional year.
|
||||
*
|
||||
* @link http://en.wikipedia.org/wiki/Cron
|
||||
*/
|
||||
class CronExpression
|
||||
{
|
||||
const MINUTE = 0;
|
||||
const HOUR = 1;
|
||||
const DAY = 2;
|
||||
const MONTH = 3;
|
||||
const WEEKDAY = 4;
|
||||
const YEAR = 5;
|
||||
|
||||
/**
|
||||
* @var array CRON expression parts
|
||||
*/
|
||||
private $cronParts;
|
||||
|
||||
/**
|
||||
* @var FieldFactory CRON field factory
|
||||
*/
|
||||
private $fieldFactory;
|
||||
|
||||
/**
|
||||
* @var int Max iteration count when searching for next run date
|
||||
*/
|
||||
private $maxIterationCount = 1000;
|
||||
|
||||
/**
|
||||
* @var array Order in which to test of cron parts
|
||||
*/
|
||||
private static $order = array(self::YEAR, self::MONTH, self::DAY, self::WEEKDAY, self::HOUR, self::MINUTE);
|
||||
|
||||
/**
|
||||
* Factory method to create a new CronExpression.
|
||||
*
|
||||
* @param string $expression The CRON expression to create. There are
|
||||
* several special predefined values which can be used to substitute the
|
||||
* CRON expression:
|
||||
*
|
||||
* `@yearly`, `@annually` - Run once a year, midnight, Jan. 1 - 0 0 1 1 *
|
||||
* `@monthly` - Run once a month, midnight, first of month - 0 0 1 * *
|
||||
* `@weekly` - Run once a week, midnight on Sun - 0 0 * * 0
|
||||
* `@daily` - Run once a day, midnight - 0 0 * * *
|
||||
* `@hourly` - Run once an hour, first minute - 0 * * * *
|
||||
* @param FieldFactory $fieldFactory Field factory to use
|
||||
*
|
||||
* @return CronExpression
|
||||
*/
|
||||
public static function factory($expression, FieldFactory $fieldFactory = null)
|
||||
{
|
||||
$mappings = array(
|
||||
'@yearly' => '0 0 1 1 *',
|
||||
'@annually' => '0 0 1 1 *',
|
||||
'@monthly' => '0 0 1 * *',
|
||||
'@weekly' => '0 0 * * 0',
|
||||
'@daily' => '0 0 * * *',
|
||||
'@hourly' => '0 * * * *'
|
||||
);
|
||||
|
||||
if (isset($mappings[$expression])) {
|
||||
$expression = $mappings[$expression];
|
||||
}
|
||||
|
||||
return new static($expression, $fieldFactory ?: new FieldFactory());
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate a CronExpression.
|
||||
*
|
||||
* @param string $expression The CRON expression to validate.
|
||||
*
|
||||
* @return bool True if a valid CRON expression was passed. False if not.
|
||||
* @see \Cron\CronExpression::factory
|
||||
*/
|
||||
public static function isValidExpression($expression)
|
||||
{
|
||||
try {
|
||||
self::factory($expression);
|
||||
} catch (InvalidArgumentException $e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a CRON expression
|
||||
*
|
||||
* @param string $expression CRON expression (e.g. '8 * * * *')
|
||||
* @param FieldFactory $fieldFactory Factory to create cron fields
|
||||
*/
|
||||
public function __construct($expression, FieldFactory $fieldFactory)
|
||||
{
|
||||
$this->fieldFactory = $fieldFactory;
|
||||
$this->setExpression($expression);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set or change the CRON expression
|
||||
*
|
||||
* @param string $value CRON expression (e.g. 8 * * * *)
|
||||
*
|
||||
* @return CronExpression
|
||||
* @throws \InvalidArgumentException if not a valid CRON expression
|
||||
*/
|
||||
public function setExpression($value)
|
||||
{
|
||||
$this->cronParts = preg_split('/\s/', $value, -1, PREG_SPLIT_NO_EMPTY);
|
||||
if (count($this->cronParts) < 5) {
|
||||
throw new InvalidArgumentException(
|
||||
$value . ' is not a valid CRON expression'
|
||||
);
|
||||
}
|
||||
|
||||
foreach ($this->cronParts as $position => $part) {
|
||||
$this->setPart($position, $part);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set part of the CRON expression
|
||||
*
|
||||
* @param int $position The position of the CRON expression to set
|
||||
* @param string $value The value to set
|
||||
*
|
||||
* @return CronExpression
|
||||
* @throws \InvalidArgumentException if the value is not valid for the part
|
||||
*/
|
||||
public function setPart($position, $value)
|
||||
{
|
||||
if (!$this->fieldFactory->getField($position)->validate($value)) {
|
||||
throw new InvalidArgumentException(
|
||||
'Invalid CRON field value ' . $value . ' at position ' . $position
|
||||
);
|
||||
}
|
||||
|
||||
$this->cronParts[$position] = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set max iteration count for searching next run dates
|
||||
*
|
||||
* @param int $maxIterationCount Max iteration count when searching for next run date
|
||||
*
|
||||
* @return CronExpression
|
||||
*/
|
||||
public function setMaxIterationCount($maxIterationCount)
|
||||
{
|
||||
$this->maxIterationCount = $maxIterationCount;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a next run date relative to the current date or a specific date
|
||||
*
|
||||
* @param string|\DateTime $currentTime Relative calculation date
|
||||
* @param int $nth Number of matches to skip before returning a
|
||||
* matching next run date. 0, the default, will return the current
|
||||
* date and time if the next run date falls on the current date and
|
||||
* time. Setting this value to 1 will skip the first match and go to
|
||||
* the second match. Setting this value to 2 will skip the first 2
|
||||
* matches and so on.
|
||||
* @param bool $allowCurrentDate Set to TRUE to return the current date if
|
||||
* it matches the cron expression.
|
||||
* @param null|string $timeZone TimeZone to use instead of the system default
|
||||
*
|
||||
* @return \DateTime
|
||||
* @throws \RuntimeException on too many iterations
|
||||
*/
|
||||
public function getNextRunDate($currentTime = 'now', $nth = 0, $allowCurrentDate = false, $timeZone = null)
|
||||
{
|
||||
return $this->getRunDate($currentTime, $nth, false, $allowCurrentDate, $timeZone);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a previous run date relative to the current date or a specific date
|
||||
*
|
||||
* @param string|\DateTime $currentTime Relative calculation date
|
||||
* @param int $nth Number of matches to skip before returning
|
||||
* @param bool $allowCurrentDate Set to TRUE to return the
|
||||
* current date if it matches the cron expression
|
||||
* @param null|string $timeZone TimeZone to use instead of the system default
|
||||
*
|
||||
* @return \DateTime
|
||||
* @throws \RuntimeException on too many iterations
|
||||
* @see \Cron\CronExpression::getNextRunDate
|
||||
*/
|
||||
public function getPreviousRunDate($currentTime = 'now', $nth = 0, $allowCurrentDate = false, $timeZone = null)
|
||||
{
|
||||
return $this->getRunDate($currentTime, $nth, true, $allowCurrentDate, $timeZone);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get multiple run dates starting at the current date or a specific date
|
||||
*
|
||||
* @param int $total Set the total number of dates to calculate
|
||||
* @param string|\DateTime $currentTime Relative calculation date
|
||||
* @param bool $invert Set to TRUE to retrieve previous dates
|
||||
* @param bool $allowCurrentDate Set to TRUE to return the
|
||||
* current date if it matches the cron expression
|
||||
* @param null|string $timeZone TimeZone to use instead of the system default
|
||||
*
|
||||
* @return array Returns an array of run dates
|
||||
*/
|
||||
public function getMultipleRunDates($total, $currentTime = 'now', $invert = false, $allowCurrentDate = false, $timeZone = null)
|
||||
{
|
||||
$matches = array();
|
||||
for ($i = 0; $i < max(0, $total); $i++) {
|
||||
try {
|
||||
$matches[] = $this->getRunDate($currentTime, $i, $invert, $allowCurrentDate, $timeZone);
|
||||
} catch (RuntimeException $e) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $matches;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all or part of the CRON expression
|
||||
*
|
||||
* @param string $part Specify the part to retrieve or NULL to get the full
|
||||
* cron schedule string.
|
||||
*
|
||||
* @return string|null Returns the CRON expression, a part of the
|
||||
* CRON expression, or NULL if the part was specified but not found
|
||||
*/
|
||||
public function getExpression($part = null)
|
||||
{
|
||||
if (null === $part) {
|
||||
return implode(' ', $this->cronParts);
|
||||
} elseif (array_key_exists($part, $this->cronParts)) {
|
||||
return $this->cronParts[$part];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to output the full expression.
|
||||
*
|
||||
* @return string Full CRON expression
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return $this->getExpression();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the cron is due to run based on the current date or a
|
||||
* specific date. This method assumes that the current number of
|
||||
* seconds are irrelevant, and should be called once per minute.
|
||||
*
|
||||
* @param string|\DateTime $currentTime Relative calculation date
|
||||
* @param null|string $timeZone TimeZone to use instead of the system default
|
||||
*
|
||||
* @return bool Returns TRUE if the cron is due to run or FALSE if not
|
||||
*/
|
||||
public function isDue($currentTime = 'now', $timeZone = null)
|
||||
{
|
||||
$timeZone = $this->determineTimeZone($currentTime, $timeZone);
|
||||
|
||||
if ('now' === $currentTime) {
|
||||
$currentTime = new DateTime();
|
||||
} elseif ($currentTime instanceof DateTime) {
|
||||
//
|
||||
} elseif ($currentTime instanceof DateTimeImmutable) {
|
||||
$currentTime = DateTime::createFromFormat('U', $currentTime->format('U'));
|
||||
} else {
|
||||
$currentTime = new DateTime($currentTime);
|
||||
}
|
||||
$currentTime->setTimeZone(new DateTimeZone($timeZone));
|
||||
|
||||
// drop the seconds to 0
|
||||
$currentTime = DateTime::createFromFormat('Y-m-d H:i', $currentTime->format('Y-m-d H:i'));
|
||||
|
||||
try {
|
||||
return $this->getNextRunDate($currentTime, 0, true)->getTimestamp() === $currentTime->getTimestamp();
|
||||
} catch (Exception $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next or previous run date of the expression relative to a date
|
||||
*
|
||||
* @param string|\DateTime $currentTime Relative calculation date
|
||||
* @param int $nth Number of matches to skip before returning
|
||||
* @param bool $invert Set to TRUE to go backwards in time
|
||||
* @param bool $allowCurrentDate Set to TRUE to return the
|
||||
* current date if it matches the cron expression
|
||||
* @param string|null $timeZone TimeZone to use instead of the system default
|
||||
*
|
||||
* @return \DateTime
|
||||
* @throws \RuntimeException on too many iterations
|
||||
*/
|
||||
protected function getRunDate($currentTime = null, $nth = 0, $invert = false, $allowCurrentDate = false, $timeZone = null)
|
||||
{
|
||||
$timeZone = $this->determineTimeZone($currentTime, $timeZone);
|
||||
|
||||
if ($currentTime instanceof DateTime) {
|
||||
$currentDate = clone $currentTime;
|
||||
} elseif ($currentTime instanceof DateTimeImmutable) {
|
||||
$currentDate = DateTime::createFromFormat('U', $currentTime->format('U'));
|
||||
} else {
|
||||
$currentDate = new DateTime($currentTime ?: 'now');
|
||||
}
|
||||
|
||||
$currentDate->setTimeZone(new DateTimeZone($timeZone));
|
||||
$currentDate->setTime($currentDate->format('H'), $currentDate->format('i'), 0);
|
||||
$nextRun = clone $currentDate;
|
||||
$nth = (int) $nth;
|
||||
|
||||
// We don't have to satisfy * or null fields
|
||||
$parts = array();
|
||||
$fields = array();
|
||||
foreach (self::$order as $position) {
|
||||
$part = $this->getExpression($position);
|
||||
if (null === $part || '*' === $part) {
|
||||
continue;
|
||||
}
|
||||
$parts[$position] = $part;
|
||||
$fields[$position] = $this->fieldFactory->getField($position);
|
||||
}
|
||||
|
||||
// Set a hard limit to bail on an impossible date
|
||||
for ($i = 0; $i < $this->maxIterationCount; $i++) {
|
||||
|
||||
foreach ($parts as $position => $part) {
|
||||
$satisfied = false;
|
||||
// Get the field object used to validate this part
|
||||
$field = $fields[$position];
|
||||
// Check if this is singular or a list
|
||||
if (strpos($part, ',') === false) {
|
||||
$satisfied = $field->isSatisfiedBy($nextRun, $part);
|
||||
} else {
|
||||
foreach (array_map('trim', explode(',', $part)) as $listPart) {
|
||||
if ($field->isSatisfiedBy($nextRun, $listPart)) {
|
||||
$satisfied = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If the field is not satisfied, then start over
|
||||
if (!$satisfied) {
|
||||
$field->increment($nextRun, $invert, $part);
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
|
||||
// Skip this match if needed
|
||||
if ((!$allowCurrentDate && $nextRun == $currentDate) || --$nth > -1) {
|
||||
$this->fieldFactory->getField(0)->increment($nextRun, $invert, isset($parts[0]) ? $parts[0] : null);
|
||||
continue;
|
||||
}
|
||||
|
||||
return $nextRun;
|
||||
}
|
||||
|
||||
// @codeCoverageIgnoreStart
|
||||
throw new RuntimeException('Impossible CRON expression');
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
/**
|
||||
* Workout what timeZone should be used.
|
||||
*
|
||||
* @param string|\DateTime $currentTime Relative calculation date
|
||||
* @param string|null $timeZone TimeZone to use instead of the system default
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function determineTimeZone($currentTime, $timeZone)
|
||||
{
|
||||
if (! is_null($timeZone)) {
|
||||
return $timeZone;
|
||||
}
|
||||
|
||||
if ($currentTime instanceOf Datetime) {
|
||||
return $currentTime->getTimeZone()->getName();
|
||||
}
|
||||
|
||||
return date_default_timezone_get();
|
||||
}
|
||||
}
|
131
vendor/dragonmantank/cron-expression/src/Cron/DayOfMonthField.php
vendored
Normal file
131
vendor/dragonmantank/cron-expression/src/Cron/DayOfMonthField.php
vendored
Normal file
@@ -0,0 +1,131 @@
|
||||
<?php
|
||||
|
||||
namespace Cron;
|
||||
|
||||
use DateTime;
|
||||
|
||||
/**
|
||||
* Day of month field. Allows: * , / - ? L W
|
||||
*
|
||||
* 'L' stands for "last" and specifies the last day of the month.
|
||||
*
|
||||
* The 'W' character is used to specify the weekday (Monday-Friday) nearest the
|
||||
* given day. As an example, if you were to specify "15W" as the value for the
|
||||
* day-of-month field, the meaning is: "the nearest weekday to the 15th of the
|
||||
* month". So if the 15th is a Saturday, the trigger will fire on Friday the
|
||||
* 14th. If the 15th is a Sunday, the trigger will fire on Monday the 16th. If
|
||||
* the 15th is a Tuesday, then it will fire on Tuesday the 15th. However if you
|
||||
* specify "1W" as the value for day-of-month, and the 1st is a Saturday, the
|
||||
* trigger will fire on Monday the 3rd, as it will not 'jump' over the boundary
|
||||
* of a month's days. The 'W' character can only be specified when the
|
||||
* day-of-month is a single day, not a range or list of days.
|
||||
*
|
||||
* @author Michael Dowling <mtdowling@gmail.com>
|
||||
*/
|
||||
class DayOfMonthField extends AbstractField
|
||||
{
|
||||
protected $rangeStart = 1;
|
||||
protected $rangeEnd = 31;
|
||||
|
||||
/**
|
||||
* Get the nearest day of the week for a given day in a month
|
||||
*
|
||||
* @param int $currentYear Current year
|
||||
* @param int $currentMonth Current month
|
||||
* @param int $targetDay Target day of the month
|
||||
*
|
||||
* @return \DateTime Returns the nearest date
|
||||
*/
|
||||
private static function getNearestWeekday($currentYear, $currentMonth, $targetDay)
|
||||
{
|
||||
$tday = str_pad($targetDay, 2, '0', STR_PAD_LEFT);
|
||||
$target = DateTime::createFromFormat('Y-m-d', "$currentYear-$currentMonth-$tday");
|
||||
$currentWeekday = (int) $target->format('N');
|
||||
|
||||
if ($currentWeekday < 6) {
|
||||
return $target;
|
||||
}
|
||||
|
||||
$lastDayOfMonth = $target->format('t');
|
||||
|
||||
foreach (array(-1, 1, -2, 2) as $i) {
|
||||
$adjusted = $targetDay + $i;
|
||||
if ($adjusted > 0 && $adjusted <= $lastDayOfMonth) {
|
||||
$target->setDate($currentYear, $currentMonth, $adjusted);
|
||||
if ($target->format('N') < 6 && $target->format('m') == $currentMonth) {
|
||||
return $target;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function isSatisfiedBy(DateTime $date, $value)
|
||||
{
|
||||
// ? states that the field value is to be skipped
|
||||
if ($value == '?') {
|
||||
return true;
|
||||
}
|
||||
|
||||
$fieldValue = $date->format('d');
|
||||
|
||||
// Check to see if this is the last day of the month
|
||||
if ($value == 'L') {
|
||||
return $fieldValue == $date->format('t');
|
||||
}
|
||||
|
||||
// Check to see if this is the nearest weekday to a particular value
|
||||
if (strpos($value, 'W')) {
|
||||
// Parse the target day
|
||||
$targetDay = substr($value, 0, strpos($value, 'W'));
|
||||
// Find out if the current day is the nearest day of the week
|
||||
return $date->format('j') == self::getNearestWeekday(
|
||||
$date->format('Y'),
|
||||
$date->format('m'),
|
||||
$targetDay
|
||||
)->format('j');
|
||||
}
|
||||
|
||||
return $this->isSatisfied($date->format('d'), $value);
|
||||
}
|
||||
|
||||
public function increment(DateTime $date, $invert = false)
|
||||
{
|
||||
if ($invert) {
|
||||
$date->modify('previous day');
|
||||
$date->setTime(23, 59);
|
||||
} else {
|
||||
$date->modify('next day');
|
||||
$date->setTime(0, 0);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function validate($value)
|
||||
{
|
||||
$basicChecks = parent::validate($value);
|
||||
|
||||
// Validate that a list don't have W or L
|
||||
if (strpos($value, ',') !== false && (strpos($value, 'W') !== false || strpos($value, 'L') !== false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$basicChecks) {
|
||||
|
||||
if ($value === 'L') {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (preg_match('/^(.*)W$/', $value, $matches)) {
|
||||
return $this->validate($matches[1]);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return $basicChecks;
|
||||
}
|
||||
}
|
170
vendor/dragonmantank/cron-expression/src/Cron/DayOfWeekField.php
vendored
Normal file
170
vendor/dragonmantank/cron-expression/src/Cron/DayOfWeekField.php
vendored
Normal file
@@ -0,0 +1,170 @@
|
||||
<?php
|
||||
|
||||
namespace Cron;
|
||||
|
||||
use DateTime;
|
||||
use InvalidArgumentException;
|
||||
|
||||
|
||||
/**
|
||||
* Day of week field. Allows: * / , - ? L #
|
||||
*
|
||||
* Days of the week can be represented as a number 0-7 (0|7 = Sunday)
|
||||
* or as a three letter string: SUN, MON, TUE, WED, THU, FRI, SAT.
|
||||
*
|
||||
* 'L' stands for "last". It allows you to specify constructs such as
|
||||
* "the last Friday" of a given month.
|
||||
*
|
||||
* '#' is allowed for the day-of-week field, and must be followed by a
|
||||
* number between one and five. It allows you to specify constructs such as
|
||||
* "the second Friday" of a given month.
|
||||
*/
|
||||
class DayOfWeekField extends AbstractField
|
||||
{
|
||||
protected $rangeStart = 0;
|
||||
protected $rangeEnd = 7;
|
||||
|
||||
protected $nthRange;
|
||||
|
||||
protected $literals = [1 => 'MON', 2 => 'TUE', 3 => 'WED', 4 => 'THU', 5 => 'FRI', 6 => 'SAT', 7 => 'SUN'];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->nthRange = range(1, 5);
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public function isSatisfiedBy(DateTime $date, $value)
|
||||
{
|
||||
if ($value == '?') {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Convert text day of the week values to integers
|
||||
$value = $this->convertLiterals($value);
|
||||
|
||||
$currentYear = $date->format('Y');
|
||||
$currentMonth = $date->format('m');
|
||||
$lastDayOfMonth = $date->format('t');
|
||||
|
||||
// Find out if this is the last specific weekday of the month
|
||||
if (strpos($value, 'L')) {
|
||||
$weekday = str_replace('7', '0', substr($value, 0, strpos($value, 'L')));
|
||||
$tdate = clone $date;
|
||||
$tdate->setDate($currentYear, $currentMonth, $lastDayOfMonth);
|
||||
while ($tdate->format('w') != $weekday) {
|
||||
$tdateClone = new DateTime();
|
||||
$tdate = $tdateClone
|
||||
->setTimezone($tdate->getTimezone())
|
||||
->setDate($currentYear, $currentMonth, --$lastDayOfMonth);
|
||||
}
|
||||
|
||||
return $date->format('j') == $lastDayOfMonth;
|
||||
}
|
||||
|
||||
// Handle # hash tokens
|
||||
if (strpos($value, '#')) {
|
||||
list($weekday, $nth) = explode('#', $value);
|
||||
|
||||
if (!is_numeric($nth)) {
|
||||
throw new InvalidArgumentException("Hashed weekdays must be numeric, {$nth} given");
|
||||
} else {
|
||||
$nth = (int) $nth;
|
||||
}
|
||||
|
||||
// 0 and 7 are both Sunday, however 7 matches date('N') format ISO-8601
|
||||
if ($weekday === '0') {
|
||||
$weekday = 7;
|
||||
}
|
||||
|
||||
$weekday = $this->convertLiterals($weekday);
|
||||
|
||||
// Validate the hash fields
|
||||
if ($weekday < 0 || $weekday > 7) {
|
||||
throw new InvalidArgumentException("Weekday must be a value between 0 and 7. {$weekday} given");
|
||||
}
|
||||
|
||||
if (!in_array($nth, $this->nthRange)) {
|
||||
throw new InvalidArgumentException("There are never more than 5 or less than 1 of a given weekday in a month, {$nth} given");
|
||||
}
|
||||
|
||||
// The current weekday must match the targeted weekday to proceed
|
||||
if ($date->format('N') != $weekday) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$tdate = clone $date;
|
||||
$tdate->setDate($currentYear, $currentMonth, 1);
|
||||
$dayCount = 0;
|
||||
$currentDay = 1;
|
||||
while ($currentDay < $lastDayOfMonth + 1) {
|
||||
if ($tdate->format('N') == $weekday) {
|
||||
if (++$dayCount >= $nth) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
$tdate->setDate($currentYear, $currentMonth, ++$currentDay);
|
||||
}
|
||||
|
||||
return $date->format('j') == $currentDay;
|
||||
}
|
||||
|
||||
// Handle day of the week values
|
||||
if (strpos($value, '-')) {
|
||||
$parts = explode('-', $value);
|
||||
if ($parts[0] == '7') {
|
||||
$parts[0] = '0';
|
||||
} elseif ($parts[1] == '0') {
|
||||
$parts[1] = '7';
|
||||
}
|
||||
$value = implode('-', $parts);
|
||||
}
|
||||
|
||||
// Test to see which Sunday to use -- 0 == 7 == Sunday
|
||||
$format = in_array(7, str_split($value)) ? 'N' : 'w';
|
||||
$fieldValue = $date->format($format);
|
||||
|
||||
return $this->isSatisfied($fieldValue, $value);
|
||||
}
|
||||
|
||||
public function increment(DateTime $date, $invert = false)
|
||||
{
|
||||
if ($invert) {
|
||||
$date->modify('-1 day');
|
||||
$date->setTime(23, 59, 0);
|
||||
} else {
|
||||
$date->modify('+1 day');
|
||||
$date->setTime(0, 0, 0);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function validate($value)
|
||||
{
|
||||
$basicChecks = parent::validate($value);
|
||||
|
||||
if (!$basicChecks) {
|
||||
// Handle the # value
|
||||
if (strpos($value, '#') !== false) {
|
||||
$chunks = explode('#', $value);
|
||||
$chunks[0] = $this->convertLiterals($chunks[0]);
|
||||
|
||||
if (parent::validate($chunks[0]) && is_numeric($chunks[1]) && in_array($chunks[1], $this->nthRange)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (preg_match('/^(.*)L$/', $value, $matches)) {
|
||||
return $this->validate($matches[1]);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return $basicChecks;
|
||||
}
|
||||
}
|
54
vendor/dragonmantank/cron-expression/src/Cron/FieldFactory.php
vendored
Normal file
54
vendor/dragonmantank/cron-expression/src/Cron/FieldFactory.php
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace Cron;
|
||||
|
||||
use InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* CRON field factory implementing a flyweight factory
|
||||
* @link http://en.wikipedia.org/wiki/Cron
|
||||
*/
|
||||
class FieldFactory
|
||||
{
|
||||
/**
|
||||
* @var array Cache of instantiated fields
|
||||
*/
|
||||
private $fields = array();
|
||||
|
||||
/**
|
||||
* Get an instance of a field object for a cron expression position
|
||||
*
|
||||
* @param int $position CRON expression position value to retrieve
|
||||
*
|
||||
* @return FieldInterface
|
||||
* @throws InvalidArgumentException if a position is not valid
|
||||
*/
|
||||
public function getField($position)
|
||||
{
|
||||
if (!isset($this->fields[$position])) {
|
||||
switch ($position) {
|
||||
case 0:
|
||||
$this->fields[$position] = new MinutesField();
|
||||
break;
|
||||
case 1:
|
||||
$this->fields[$position] = new HoursField();
|
||||
break;
|
||||
case 2:
|
||||
$this->fields[$position] = new DayOfMonthField();
|
||||
break;
|
||||
case 3:
|
||||
$this->fields[$position] = new MonthField();
|
||||
break;
|
||||
case 4:
|
||||
$this->fields[$position] = new DayOfWeekField();
|
||||
break;
|
||||
default:
|
||||
throw new InvalidArgumentException(
|
||||
$position . ' is not a valid position'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->fields[$position];
|
||||
}
|
||||
}
|
40
vendor/dragonmantank/cron-expression/src/Cron/FieldInterface.php
vendored
Normal file
40
vendor/dragonmantank/cron-expression/src/Cron/FieldInterface.php
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace Cron;
|
||||
use DateTime;
|
||||
|
||||
/**
|
||||
* CRON field interface
|
||||
*/
|
||||
interface FieldInterface
|
||||
{
|
||||
/**
|
||||
* Check if the respective value of a DateTime field satisfies a CRON exp
|
||||
*
|
||||
* @param DateTime $date DateTime object to check
|
||||
* @param string $value CRON expression to test against
|
||||
*
|
||||
* @return bool Returns TRUE if satisfied, FALSE otherwise
|
||||
*/
|
||||
public function isSatisfiedBy(DateTime $date, $value);
|
||||
|
||||
/**
|
||||
* When a CRON expression is not satisfied, this method is used to increment
|
||||
* or decrement a DateTime object by the unit of the cron field
|
||||
*
|
||||
* @param DateTime $date DateTime object to change
|
||||
* @param bool $invert (optional) Set to TRUE to decrement
|
||||
*
|
||||
* @return FieldInterface
|
||||
*/
|
||||
public function increment(DateTime $date, $invert = false);
|
||||
|
||||
/**
|
||||
* Validates a CRON expression for a given field
|
||||
*
|
||||
* @param string $value CRON expression value to validate
|
||||
*
|
||||
* @return bool Returns TRUE if valid, FALSE otherwise
|
||||
*/
|
||||
public function validate($value);
|
||||
}
|
69
vendor/dragonmantank/cron-expression/src/Cron/HoursField.php
vendored
Normal file
69
vendor/dragonmantank/cron-expression/src/Cron/HoursField.php
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
namespace Cron;
|
||||
use DateTime;
|
||||
use DateTimeZone;
|
||||
|
||||
|
||||
/**
|
||||
* Hours field. Allows: * , / -
|
||||
*/
|
||||
class HoursField extends AbstractField
|
||||
{
|
||||
protected $rangeStart = 0;
|
||||
protected $rangeEnd = 23;
|
||||
|
||||
public function isSatisfiedBy(DateTime $date, $value)
|
||||
{
|
||||
return $this->isSatisfied($date->format('H'), $value);
|
||||
}
|
||||
|
||||
public function increment(DateTime $date, $invert = false, $parts = null)
|
||||
{
|
||||
// Change timezone to UTC temporarily. This will
|
||||
// allow us to go back or forwards and hour even
|
||||
// if DST will be changed between the hours.
|
||||
if (is_null($parts) || $parts == '*') {
|
||||
$timezone = $date->getTimezone();
|
||||
$date->setTimezone(new DateTimeZone('UTC'));
|
||||
if ($invert) {
|
||||
$date->modify('-1 hour');
|
||||
} else {
|
||||
$date->modify('+1 hour');
|
||||
}
|
||||
$date->setTimezone($timezone);
|
||||
|
||||
$date->setTime($date->format('H'), $invert ? 59 : 0);
|
||||
return $this;
|
||||
}
|
||||
|
||||
$parts = strpos($parts, ',') !== false ? explode(',', $parts) : array($parts);
|
||||
$hours = array();
|
||||
foreach ($parts as $part) {
|
||||
$hours = array_merge($hours, $this->getRangeForExpression($part, 23));
|
||||
}
|
||||
|
||||
$current_hour = $date->format('H');
|
||||
$position = $invert ? count($hours) - 1 : 0;
|
||||
if (count($hours) > 1) {
|
||||
for ($i = 0; $i < count($hours) - 1; $i++) {
|
||||
if ((!$invert && $current_hour >= $hours[$i] && $current_hour < $hours[$i + 1]) ||
|
||||
($invert && $current_hour > $hours[$i] && $current_hour <= $hours[$i + 1])) {
|
||||
$position = $invert ? $i : $i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$hour = $hours[$position];
|
||||
if ((!$invert && $date->format('H') >= $hour) || ($invert && $date->format('H') <= $hour)) {
|
||||
$date->modify(($invert ? '-' : '+') . '1 day');
|
||||
$date->setTime($invert ? 23 : 0, $invert ? 59 : 0);
|
||||
}
|
||||
else {
|
||||
$date->setTime($hour, $invert ? 59 : 0);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
60
vendor/dragonmantank/cron-expression/src/Cron/MinutesField.php
vendored
Normal file
60
vendor/dragonmantank/cron-expression/src/Cron/MinutesField.php
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
namespace Cron;
|
||||
|
||||
use DateTime;
|
||||
|
||||
|
||||
/**
|
||||
* Minutes field. Allows: * , / -
|
||||
*/
|
||||
class MinutesField extends AbstractField
|
||||
{
|
||||
protected $rangeStart = 0;
|
||||
protected $rangeEnd = 59;
|
||||
|
||||
public function isSatisfiedBy(DateTime $date, $value)
|
||||
{
|
||||
return $this->isSatisfied($date->format('i'), $value);
|
||||
}
|
||||
|
||||
public function increment(DateTime $date, $invert = false, $parts = null)
|
||||
{
|
||||
if (is_null($parts)) {
|
||||
if ($invert) {
|
||||
$date->modify('-1 minute');
|
||||
} else {
|
||||
$date->modify('+1 minute');
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
$parts = strpos($parts, ',') !== false ? explode(',', $parts) : array($parts);
|
||||
$minutes = array();
|
||||
foreach ($parts as $part) {
|
||||
$minutes = array_merge($minutes, $this->getRangeForExpression($part, 59));
|
||||
}
|
||||
|
||||
$current_minute = $date->format('i');
|
||||
$position = $invert ? count($minutes) - 1 : 0;
|
||||
if (count($minutes) > 1) {
|
||||
for ($i = 0; $i < count($minutes) - 1; $i++) {
|
||||
if ((!$invert && $current_minute >= $minutes[$i] && $current_minute < $minutes[$i + 1]) ||
|
||||
($invert && $current_minute > $minutes[$i] && $current_minute <= $minutes[$i + 1])) {
|
||||
$position = $invert ? $i : $i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((!$invert && $current_minute >= $minutes[$position]) || ($invert && $current_minute <= $minutes[$position])) {
|
||||
$date->modify(($invert ? '-' : '+') . '1 hour');
|
||||
$date->setTime($date->format('H'), $invert ? 59 : 0);
|
||||
}
|
||||
else {
|
||||
$date->setTime($date->format('H'), $minutes[$position]);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
38
vendor/dragonmantank/cron-expression/src/Cron/MonthField.php
vendored
Normal file
38
vendor/dragonmantank/cron-expression/src/Cron/MonthField.php
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace Cron;
|
||||
|
||||
use DateTime;
|
||||
|
||||
/**
|
||||
* Month field. Allows: * , / -
|
||||
*/
|
||||
class MonthField extends AbstractField
|
||||
{
|
||||
protected $rangeStart = 1;
|
||||
protected $rangeEnd = 12;
|
||||
protected $literals = [1 => 'JAN', 2 => 'FEB', 3 => 'MAR', 4 => 'APR', 5 => 'MAY', 6 => 'JUN', 7 => 'JUL',
|
||||
8 => 'AUG', 9 => 'SEP', 10 => 'OCT', 11 => 'NOV', 12 => 'DEC'];
|
||||
|
||||
public function isSatisfiedBy(DateTime $date, $value)
|
||||
{
|
||||
$value = $this->convertLiterals($value);
|
||||
|
||||
return $this->isSatisfied($date->format('m'), $value);
|
||||
}
|
||||
|
||||
public function increment(DateTime $date, $invert = false)
|
||||
{
|
||||
if ($invert) {
|
||||
$date->modify('last day of previous month');
|
||||
$date->setTime(23, 59);
|
||||
} else {
|
||||
$date->modify('first day of next month');
|
||||
$date->setTime(0, 0);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
}
|
139
vendor/dragonmantank/cron-expression/tests/Cron/AbstractFieldTest.php
vendored
Normal file
139
vendor/dragonmantank/cron-expression/tests/Cron/AbstractFieldTest.php
vendored
Normal file
@@ -0,0 +1,139 @@
|
||||
<?php
|
||||
|
||||
namespace Cron\Tests;
|
||||
|
||||
use Cron\DayOfWeekField;
|
||||
use Cron\HoursField;
|
||||
use Cron\MinutesField;
|
||||
use Cron\MonthField;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @author Michael Dowling <mtdowling@gmail.com>
|
||||
*/
|
||||
class AbstractFieldTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers \Cron\AbstractField::isRange
|
||||
*/
|
||||
public function testTestsIfRange()
|
||||
{
|
||||
$f = new DayOfWeekField();
|
||||
$this->assertTrue($f->isRange('1-2'));
|
||||
$this->assertFalse($f->isRange('2'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Cron\AbstractField::isIncrementsOfRanges
|
||||
*/
|
||||
public function testTestsIfIncrementsOfRanges()
|
||||
{
|
||||
$f = new DayOfWeekField();
|
||||
$this->assertFalse($f->isIncrementsOfRanges('1-2'));
|
||||
$this->assertTrue($f->isIncrementsOfRanges('1/2'));
|
||||
$this->assertTrue($f->isIncrementsOfRanges('*/2'));
|
||||
$this->assertTrue($f->isIncrementsOfRanges('3-12/2'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Cron\AbstractField::isInRange
|
||||
*/
|
||||
public function testTestsIfInRange()
|
||||
{
|
||||
$f = new DayOfWeekField();
|
||||
$this->assertTrue($f->isInRange('1', '1-2'));
|
||||
$this->assertTrue($f->isInRange('2', '1-2'));
|
||||
$this->assertTrue($f->isInRange('5', '4-12'));
|
||||
$this->assertFalse($f->isInRange('3', '4-12'));
|
||||
$this->assertFalse($f->isInRange('13', '4-12'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Cron\AbstractField::isInIncrementsOfRanges
|
||||
*/
|
||||
public function testTestsIfInIncrementsOfRangesOnZeroStartRange()
|
||||
{
|
||||
$f = new MinutesField();
|
||||
$this->assertTrue($f->isInIncrementsOfRanges('3', '3-59/2'));
|
||||
$this->assertTrue($f->isInIncrementsOfRanges('13', '3-59/2'));
|
||||
$this->assertTrue($f->isInIncrementsOfRanges('15', '3-59/2'));
|
||||
$this->assertTrue($f->isInIncrementsOfRanges('14', '*/2'));
|
||||
$this->assertFalse($f->isInIncrementsOfRanges('2', '3-59/13'));
|
||||
$this->assertFalse($f->isInIncrementsOfRanges('14', '*/13'));
|
||||
$this->assertFalse($f->isInIncrementsOfRanges('14', '3-59/2'));
|
||||
$this->assertFalse($f->isInIncrementsOfRanges('3', '2-59'));
|
||||
$this->assertFalse($f->isInIncrementsOfRanges('3', '2'));
|
||||
$this->assertFalse($f->isInIncrementsOfRanges('3', '*'));
|
||||
$this->assertFalse($f->isInIncrementsOfRanges('0', '*/0'));
|
||||
$this->assertFalse($f->isInIncrementsOfRanges('1', '*/0'));
|
||||
|
||||
$this->assertTrue($f->isInIncrementsOfRanges('4', '4/1'));
|
||||
$this->assertFalse($f->isInIncrementsOfRanges('14', '4/1'));
|
||||
$this->assertFalse($f->isInIncrementsOfRanges('34', '4/1'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Cron\AbstractField::isInIncrementsOfRanges
|
||||
*/
|
||||
public function testTestsIfInIncrementsOfRangesOnOneStartRange()
|
||||
{
|
||||
$f = new MonthField();
|
||||
$this->assertTrue($f->isInIncrementsOfRanges('3', '3-12/2'));
|
||||
$this->assertFalse($f->isInIncrementsOfRanges('13', '3-12/2'));
|
||||
$this->assertFalse($f->isInIncrementsOfRanges('15', '3-12/2'));
|
||||
$this->assertTrue($f->isInIncrementsOfRanges('3', '*/2'));
|
||||
$this->assertFalse($f->isInIncrementsOfRanges('3', '*/3'));
|
||||
$this->assertTrue($f->isInIncrementsOfRanges('7', '*/3'));
|
||||
$this->assertFalse($f->isInIncrementsOfRanges('14', '3-12/2'));
|
||||
$this->assertFalse($f->isInIncrementsOfRanges('3', '2-12'));
|
||||
$this->assertFalse($f->isInIncrementsOfRanges('3', '2'));
|
||||
$this->assertFalse($f->isInIncrementsOfRanges('3', '*'));
|
||||
$this->assertFalse($f->isInIncrementsOfRanges('0', '*/0'));
|
||||
$this->assertFalse($f->isInIncrementsOfRanges('1', '*/0'));
|
||||
|
||||
$this->assertTrue($f->isInIncrementsOfRanges('4', '4/1'));
|
||||
$this->assertFalse($f->isInIncrementsOfRanges('14', '4/1'));
|
||||
$this->assertFalse($f->isInIncrementsOfRanges('34', '4/1'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Cron\AbstractField::isSatisfied
|
||||
*/
|
||||
public function testTestsIfSatisfied()
|
||||
{
|
||||
$f = new DayOfWeekField();
|
||||
$this->assertTrue($f->isSatisfied('12', '3-13'));
|
||||
$this->assertFalse($f->isSatisfied('15', '3-7/2'));
|
||||
$this->assertTrue($f->isSatisfied('12', '*'));
|
||||
$this->assertTrue($f->isSatisfied('12', '12'));
|
||||
$this->assertFalse($f->isSatisfied('12', '3-11'));
|
||||
$this->assertFalse($f->isSatisfied('12', '3-7/2'));
|
||||
$this->assertFalse($f->isSatisfied('12', '11'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows ranges and lists to coexist in the same expression
|
||||
*
|
||||
* @see https://github.com/dragonmantank/cron-expression/issues/5
|
||||
*/
|
||||
public function testAllowRangesAndLists()
|
||||
{
|
||||
$expression = '5-7,11-13';
|
||||
$f = new HoursField();
|
||||
$this->assertTrue($f->validate($expression));
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes sure that various types of ranges expand out properly
|
||||
*
|
||||
* @see https://github.com/dragonmantank/cron-expression/issues/5
|
||||
*/
|
||||
public function testGetRangeForExpressionExpandsCorrectly()
|
||||
{
|
||||
$f = new HoursField();
|
||||
$this->assertSame([5, 6, 7, 11, 12, 13], $f->getRangeForExpression('5-7,11-13', 23));
|
||||
$this->assertSame(['5', '6', '7', '11', '12', '13'], $f->getRangeForExpression('5,6,7,11,12,13', 23));
|
||||
$this->assertSame([0, 6, 12, 18], $f->getRangeForExpression('*/6', 23));
|
||||
$this->assertSame([5, 11], $f->getRangeForExpression('5-13/6', 23));
|
||||
}
|
||||
}
|
560
vendor/dragonmantank/cron-expression/tests/Cron/CronExpressionTest.php
vendored
Normal file
560
vendor/dragonmantank/cron-expression/tests/Cron/CronExpressionTest.php
vendored
Normal file
@@ -0,0 +1,560 @@
|
||||
<?php
|
||||
|
||||
namespace Cron\Tests;
|
||||
|
||||
use Cron\CronExpression;
|
||||
use Cron\MonthField;
|
||||
use DateTime;
|
||||
use DateTimeZone;
|
||||
use InvalidArgumentException;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @author Michael Dowling <mtdowling@gmail.com>
|
||||
*/
|
||||
class CronExpressionTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers \Cron\CronExpression::factory
|
||||
*/
|
||||
public function testFactoryRecognizesTemplates()
|
||||
{
|
||||
$this->assertSame('0 0 1 1 *', CronExpression::factory('@annually')->getExpression());
|
||||
$this->assertSame('0 0 1 1 *', CronExpression::factory('@yearly')->getExpression());
|
||||
$this->assertSame('0 0 * * 0', CronExpression::factory('@weekly')->getExpression());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Cron\CronExpression::__construct
|
||||
* @covers \Cron\CronExpression::getExpression
|
||||
* @covers \Cron\CronExpression::__toString
|
||||
*/
|
||||
public function testParsesCronSchedule()
|
||||
{
|
||||
// '2010-09-10 12:00:00'
|
||||
$cron = CronExpression::factory('1 2-4 * 4,5,6 */3');
|
||||
$this->assertSame('1', $cron->getExpression(CronExpression::MINUTE));
|
||||
$this->assertSame('2-4', $cron->getExpression(CronExpression::HOUR));
|
||||
$this->assertSame('*', $cron->getExpression(CronExpression::DAY));
|
||||
$this->assertSame('4,5,6', $cron->getExpression(CronExpression::MONTH));
|
||||
$this->assertSame('*/3', $cron->getExpression(CronExpression::WEEKDAY));
|
||||
$this->assertSame('1 2-4 * 4,5,6 */3', $cron->getExpression());
|
||||
$this->assertSame('1 2-4 * 4,5,6 */3', (string) $cron);
|
||||
$this->assertNull($cron->getExpression('foo'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Cron\CronExpression::__construct
|
||||
* @covers \Cron\CronExpression::getExpression
|
||||
* @covers \Cron\CronExpression::__toString
|
||||
* @expectedException \InvalidArgumentException
|
||||
* @expectedExceptionMessage Invalid CRON field value A at position 0
|
||||
*/
|
||||
public function testParsesCronScheduleThrowsAnException()
|
||||
{
|
||||
CronExpression::factory('A 1 2 3 4');
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Cron\CronExpression::__construct
|
||||
* @covers \Cron\CronExpression::getExpression
|
||||
* @dataProvider scheduleWithDifferentSeparatorsProvider
|
||||
*/
|
||||
public function testParsesCronScheduleWithAnySpaceCharsAsSeparators($schedule, array $expected)
|
||||
{
|
||||
$cron = CronExpression::factory($schedule);
|
||||
$this->assertSame($expected[0], $cron->getExpression(CronExpression::MINUTE));
|
||||
$this->assertSame($expected[1], $cron->getExpression(CronExpression::HOUR));
|
||||
$this->assertSame($expected[2], $cron->getExpression(CronExpression::DAY));
|
||||
$this->assertSame($expected[3], $cron->getExpression(CronExpression::MONTH));
|
||||
$this->assertSame($expected[4], $cron->getExpression(CronExpression::WEEKDAY));
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testParsesCronScheduleWithAnySpaceCharsAsSeparators
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function scheduleWithDifferentSeparatorsProvider()
|
||||
{
|
||||
return array(
|
||||
array("*\t*\t*\t*\t*\t", array('*', '*', '*', '*', '*', '*')),
|
||||
array("* * * * * ", array('*', '*', '*', '*', '*', '*')),
|
||||
array("* \t * \t * \t * \t * \t", array('*', '*', '*', '*', '*', '*')),
|
||||
array("*\t \t*\t \t*\t \t*\t \t*\t \t", array('*', '*', '*', '*', '*', '*')),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Cron\CronExpression::__construct
|
||||
* @covers \Cron\CronExpression::setExpression
|
||||
* @covers \Cron\CronExpression::setPart
|
||||
* @expectedException InvalidArgumentException
|
||||
*/
|
||||
public function testInvalidCronsWillFail()
|
||||
{
|
||||
// Only four values
|
||||
$cron = CronExpression::factory('* * * 1');
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Cron\CronExpression::setPart
|
||||
* @expectedException InvalidArgumentException
|
||||
*/
|
||||
public function testInvalidPartsWillFail()
|
||||
{
|
||||
// Only four values
|
||||
$cron = CronExpression::factory('* * * * *');
|
||||
$cron->setPart(1, 'abc');
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for cron schedule
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function scheduleProvider()
|
||||
{
|
||||
return array(
|
||||
array('*/2 */2 * * *', '2015-08-10 21:47:27', '2015-08-10 22:00:00', false),
|
||||
array('* * * * *', '2015-08-10 21:50:37', '2015-08-10 21:50:00', true),
|
||||
array('* 20,21,22 * * *', '2015-08-10 21:50:00', '2015-08-10 21:50:00', true),
|
||||
// Handles CSV values
|
||||
array('* 20,22 * * *', '2015-08-10 21:50:00', '2015-08-10 22:00:00', false),
|
||||
// CSV values can be complex
|
||||
array('7-9 * */9 * *', '2015-08-10 22:02:33', '2015-08-10 22:07:00', false),
|
||||
// 15th minute, of the second hour, every 15 days, in January, every Friday
|
||||
array('1 * * * 7', '2015-08-10 21:47:27', '2015-08-16 00:01:00', false),
|
||||
// Test with exact times
|
||||
array('47 21 * * *', strtotime('2015-08-10 21:47:30'), '2015-08-10 21:47:00', true),
|
||||
// Test Day of the week (issue #1)
|
||||
// According cron implementation, 0|7 = sunday, 1 => monday, etc
|
||||
array('* * * * 0', strtotime('2011-06-15 23:09:00'), '2011-06-19 00:00:00', false),
|
||||
array('* * * * 7', strtotime('2011-06-15 23:09:00'), '2011-06-19 00:00:00', false),
|
||||
array('* * * * 1', strtotime('2011-06-15 23:09:00'), '2011-06-20 00:00:00', false),
|
||||
// Should return the sunday date as 7 equals 0
|
||||
array('0 0 * * MON,SUN', strtotime('2011-06-15 23:09:00'), '2011-06-19 00:00:00', false),
|
||||
array('0 0 * * 1,7', strtotime('2011-06-15 23:09:00'), '2011-06-19 00:00:00', false),
|
||||
array('0 0 * * 0-4', strtotime('2011-06-15 23:09:00'), '2011-06-16 00:00:00', false),
|
||||
array('0 0 * * 7-4', strtotime('2011-06-15 23:09:00'), '2011-06-16 00:00:00', false),
|
||||
array('0 0 * * 4-7', strtotime('2011-06-15 23:09:00'), '2011-06-16 00:00:00', false),
|
||||
array('0 0 * * 7-3', strtotime('2011-06-15 23:09:00'), '2011-06-19 00:00:00', false),
|
||||
array('0 0 * * 3-7', strtotime('2011-06-15 23:09:00'), '2011-06-16 00:00:00', false),
|
||||
array('0 0 * * 3-7', strtotime('2011-06-18 23:09:00'), '2011-06-19 00:00:00', false),
|
||||
// Test lists of values and ranges (Abhoryo)
|
||||
array('0 0 * * 2-7', strtotime('2011-06-20 23:09:00'), '2011-06-21 00:00:00', false),
|
||||
array('0 0 * * 2-7', strtotime('2011-06-18 23:09:00'), '2011-06-19 00:00:00', false),
|
||||
array('0 0 * * 4-7', strtotime('2011-07-19 00:00:00'), '2011-07-21 00:00:00', false),
|
||||
// Test increments of ranges
|
||||
array('0-12/4 * * * *', strtotime('2011-06-20 12:04:00'), '2011-06-20 12:04:00', true),
|
||||
array('4-59/2 * * * *', strtotime('2011-06-20 12:04:00'), '2011-06-20 12:04:00', true),
|
||||
array('4-59/2 * * * *', strtotime('2011-06-20 12:06:00'), '2011-06-20 12:06:00', true),
|
||||
array('4-59/3 * * * *', strtotime('2011-06-20 12:06:00'), '2011-06-20 12:07:00', false),
|
||||
// Test Day of the Week and the Day of the Month (issue #1)
|
||||
array('0 0 1 1 0', strtotime('2011-06-15 23:09:00'), '2012-01-01 00:00:00', false),
|
||||
array('0 0 1 JAN 0', strtotime('2011-06-15 23:09:00'), '2012-01-01 00:00:00', false),
|
||||
array('0 0 1 * 0', strtotime('2011-06-15 23:09:00'), '2012-01-01 00:00:00', false),
|
||||
// Test the W day of the week modifier for day of the month field
|
||||
array('0 0 2W * *', strtotime('2011-07-01 00:00:00'), '2011-07-01 00:00:00', true),
|
||||
array('0 0 1W * *', strtotime('2011-05-01 00:00:00'), '2011-05-02 00:00:00', false),
|
||||
array('0 0 1W * *', strtotime('2011-07-01 00:00:00'), '2011-07-01 00:00:00', true),
|
||||
array('0 0 3W * *', strtotime('2011-07-01 00:00:00'), '2011-07-04 00:00:00', false),
|
||||
array('0 0 16W * *', strtotime('2011-07-01 00:00:00'), '2011-07-15 00:00:00', false),
|
||||
array('0 0 28W * *', strtotime('2011-07-01 00:00:00'), '2011-07-28 00:00:00', false),
|
||||
array('0 0 30W * *', strtotime('2011-07-01 00:00:00'), '2011-07-29 00:00:00', false),
|
||||
array('0 0 31W * *', strtotime('2011-07-01 00:00:00'), '2011-07-29 00:00:00', false),
|
||||
// Test the last weekday of a month
|
||||
array('* * * * 5L', strtotime('2011-07-01 00:00:00'), '2011-07-29 00:00:00', false),
|
||||
array('* * * * 6L', strtotime('2011-07-01 00:00:00'), '2011-07-30 00:00:00', false),
|
||||
array('* * * * 7L', strtotime('2011-07-01 00:00:00'), '2011-07-31 00:00:00', false),
|
||||
array('* * * * 1L', strtotime('2011-07-24 00:00:00'), '2011-07-25 00:00:00', false),
|
||||
array('* * * 1 5L', strtotime('2011-12-25 00:00:00'), '2012-01-27 00:00:00', false),
|
||||
// Test the hash symbol for the nth weekday of a given month
|
||||
array('* * * * 5#2', strtotime('2011-07-01 00:00:00'), '2011-07-08 00:00:00', false),
|
||||
array('* * * * 5#1', strtotime('2011-07-01 00:00:00'), '2011-07-01 00:00:00', true),
|
||||
array('* * * * 3#4', strtotime('2011-07-01 00:00:00'), '2011-07-27 00:00:00', false),
|
||||
|
||||
// Issue #7, documented example failed
|
||||
['3-59/15 6-12 */15 1 2-5', strtotime('2017-01-08 00:00:00'), '2017-01-31 06:03:00', false],
|
||||
|
||||
// https://github.com/laravel/framework/commit/07d160ac3cc9764d5b429734ffce4fa311385403
|
||||
['* * * * MON-FRI', strtotime('2017-01-08 00:00:00'), strtotime('2017-01-09 00:00:00'), false],
|
||||
['* * * * TUE', strtotime('2017-01-08 00:00:00'), strtotime('2017-01-10 00:00:00'), false],
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Cron\CronExpression::isDue
|
||||
* @covers \Cron\CronExpression::getNextRunDate
|
||||
* @covers \Cron\DayOfMonthField
|
||||
* @covers \Cron\DayOfWeekField
|
||||
* @covers \Cron\MinutesField
|
||||
* @covers \Cron\HoursField
|
||||
* @covers \Cron\MonthField
|
||||
* @covers \Cron\CronExpression::getRunDate
|
||||
* @dataProvider scheduleProvider
|
||||
*/
|
||||
public function testDeterminesIfCronIsDue($schedule, $relativeTime, $nextRun, $isDue)
|
||||
{
|
||||
$relativeTimeString = is_int($relativeTime) ? date('Y-m-d H:i:s', $relativeTime) : $relativeTime;
|
||||
|
||||
// Test next run date
|
||||
$cron = CronExpression::factory($schedule);
|
||||
if (is_string($relativeTime)) {
|
||||
$relativeTime = new DateTime($relativeTime);
|
||||
} elseif (is_int($relativeTime)) {
|
||||
$relativeTime = date('Y-m-d H:i:s', $relativeTime);
|
||||
}
|
||||
|
||||
if (is_string($nextRun)) {
|
||||
$nextRunDate = new DateTime($nextRun);
|
||||
} elseif (is_int($nextRun)) {
|
||||
$nextRunDate = new DateTime();
|
||||
$nextRunDate->setTimestamp($nextRun);
|
||||
}
|
||||
$this->assertSame($isDue, $cron->isDue($relativeTime));
|
||||
$next = $cron->getNextRunDate($relativeTime, 0, true);
|
||||
|
||||
$this->assertEquals($nextRunDate, $next);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Cron\CronExpression::isDue
|
||||
*/
|
||||
public function testIsDueHandlesDifferentDates()
|
||||
{
|
||||
$cron = CronExpression::factory('* * * * *');
|
||||
$this->assertTrue($cron->isDue());
|
||||
$this->assertTrue($cron->isDue('now'));
|
||||
$this->assertTrue($cron->isDue(new DateTime('now')));
|
||||
$this->assertTrue($cron->isDue(date('Y-m-d H:i')));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Cron\CronExpression::isDue
|
||||
*/
|
||||
public function testIsDueHandlesDifferentDefaultTimezones()
|
||||
{
|
||||
$originalTimezone = date_default_timezone_get();
|
||||
$cron = CronExpression::factory('0 15 * * 3'); //Wednesday at 15:00
|
||||
$date = '2014-01-01 15:00'; //Wednesday
|
||||
|
||||
date_default_timezone_set('UTC');
|
||||
$this->assertTrue($cron->isDue(new DateTime($date), 'UTC'));
|
||||
$this->assertFalse($cron->isDue(new DateTime($date), 'Europe/Amsterdam'));
|
||||
$this->assertFalse($cron->isDue(new DateTime($date), 'Asia/Tokyo'));
|
||||
|
||||
date_default_timezone_set('Europe/Amsterdam');
|
||||
$this->assertFalse($cron->isDue(new DateTime($date), 'UTC'));
|
||||
$this->assertTrue($cron->isDue(new DateTime($date), 'Europe/Amsterdam'));
|
||||
$this->assertFalse($cron->isDue(new DateTime($date), 'Asia/Tokyo'));
|
||||
|
||||
date_default_timezone_set('Asia/Tokyo');
|
||||
$this->assertFalse($cron->isDue(new DateTime($date), 'UTC'));
|
||||
$this->assertFalse($cron->isDue(new DateTime($date), 'Europe/Amsterdam'));
|
||||
$this->assertTrue($cron->isDue(new DateTime($date), 'Asia/Tokyo'));
|
||||
|
||||
date_default_timezone_set($originalTimezone);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Cron\CronExpression::isDue
|
||||
*/
|
||||
public function testIsDueHandlesDifferentSuppliedTimezones()
|
||||
{
|
||||
$cron = CronExpression::factory('0 15 * * 3'); //Wednesday at 15:00
|
||||
$date = '2014-01-01 15:00'; //Wednesday
|
||||
|
||||
$this->assertTrue($cron->isDue(new DateTime($date, new DateTimeZone('UTC')), 'UTC'));
|
||||
$this->assertFalse($cron->isDue(new DateTime($date, new DateTimeZone('UTC')), 'Europe/Amsterdam'));
|
||||
$this->assertFalse($cron->isDue(new DateTime($date, new DateTimeZone('UTC')), 'Asia/Tokyo'));
|
||||
|
||||
$this->assertFalse($cron->isDue(new DateTime($date, new DateTimeZone('Europe/Amsterdam')), 'UTC'));
|
||||
$this->assertTrue($cron->isDue(new DateTime($date, new DateTimeZone('Europe/Amsterdam')), 'Europe/Amsterdam'));
|
||||
$this->assertFalse($cron->isDue(new DateTime($date, new DateTimeZone('Europe/Amsterdam')), 'Asia/Tokyo'));
|
||||
|
||||
$this->assertFalse($cron->isDue(new DateTime($date, new DateTimeZone('Asia/Tokyo')), 'UTC'));
|
||||
$this->assertFalse($cron->isDue(new DateTime($date, new DateTimeZone('Asia/Tokyo')), 'Europe/Amsterdam'));
|
||||
$this->assertTrue($cron->isDue(new DateTime($date, new DateTimeZone('Asia/Tokyo')), 'Asia/Tokyo'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Cron\CronExpression::isDue
|
||||
*/
|
||||
public function testIsDueHandlesDifferentTimezonesAsArgument()
|
||||
{
|
||||
$cron = CronExpression::factory('0 15 * * 3'); //Wednesday at 15:00
|
||||
$date = '2014-01-01 15:00'; //Wednesday
|
||||
$utc = new \DateTimeZone('UTC');
|
||||
$amsterdam = new \DateTimeZone('Europe/Amsterdam');
|
||||
$tokyo = new \DateTimeZone('Asia/Tokyo');
|
||||
$this->assertTrue($cron->isDue(new DateTime($date, $utc), 'UTC'));
|
||||
$this->assertFalse($cron->isDue(new DateTime($date, $amsterdam), 'UTC'));
|
||||
$this->assertFalse($cron->isDue(new DateTime($date, $tokyo), 'UTC'));
|
||||
$this->assertFalse($cron->isDue(new DateTime($date, $utc), 'Europe/Amsterdam'));
|
||||
$this->assertTrue($cron->isDue(new DateTime($date, $amsterdam), 'Europe/Amsterdam'));
|
||||
$this->assertFalse($cron->isDue(new DateTime($date, $tokyo), 'Europe/Amsterdam'));
|
||||
$this->assertFalse($cron->isDue(new DateTime($date, $utc), 'Asia/Tokyo'));
|
||||
$this->assertFalse($cron->isDue(new DateTime($date, $amsterdam), 'Asia/Tokyo'));
|
||||
$this->assertTrue($cron->isDue(new DateTime($date, $tokyo), 'Asia/Tokyo'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Cron\CronExpression::isDue
|
||||
*/
|
||||
public function testRecognisesTimezonesAsPartOfDateTime()
|
||||
{
|
||||
$cron = CronExpression::factory("0 7 * * *");
|
||||
$tzCron = "America/New_York";
|
||||
$tzServer = new \DateTimeZone("Europe/London");
|
||||
|
||||
$dtCurrent = \DateTime::createFromFormat("!Y-m-d H:i:s", "2017-10-17 10:00:00", $tzServer);
|
||||
$dtPrev = $cron->getPreviousRunDate($dtCurrent, 0, true, $tzCron);
|
||||
$this->assertEquals('1508151600 : 2017-10-16T07:00:00-04:00 : America/New_York', $dtPrev->format("U \: c \: e"));
|
||||
|
||||
$dtCurrent = \DateTimeImmutable::createFromFormat("!Y-m-d H:i:s", "2017-10-17 10:00:00", $tzServer);
|
||||
$dtPrev = $cron->getPreviousRunDate($dtCurrent, 0, true, $tzCron);
|
||||
$this->assertEquals('1508151600 : 2017-10-16T07:00:00-04:00 : America/New_York', $dtPrev->format("U \: c \: e"));
|
||||
|
||||
$dtCurrent = \DateTimeImmutable::createFromFormat("!Y-m-d H:i:s", "2017-10-17 10:00:00", $tzServer);
|
||||
$dtPrev = $cron->getPreviousRunDate($dtCurrent->format("c"), 0, true, $tzCron);
|
||||
$this->assertEquals('1508151600 : 2017-10-16T07:00:00-04:00 : America/New_York', $dtPrev->format("U \: c \: e"));
|
||||
|
||||
$dtCurrent = \DateTimeImmutable::createFromFormat("!Y-m-d H:i:s", "2017-10-17 10:00:00", $tzServer);
|
||||
$dtPrev = $cron->getPreviousRunDate($dtCurrent->format("\@U"), 0, true, $tzCron);
|
||||
$this->assertEquals('1508151600 : 2017-10-16T07:00:00-04:00 : America/New_York', $dtPrev->format("U \: c \: e"));
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @covers \Cron\CronExpression::getPreviousRunDate
|
||||
*/
|
||||
public function testCanGetPreviousRunDates()
|
||||
{
|
||||
$cron = CronExpression::factory('* * * * *');
|
||||
$next = $cron->getNextRunDate('now');
|
||||
$two = $cron->getNextRunDate('now', 1);
|
||||
$this->assertEquals($next, $cron->getPreviousRunDate($two));
|
||||
|
||||
$cron = CronExpression::factory('* */2 * * *');
|
||||
$next = $cron->getNextRunDate('now');
|
||||
$two = $cron->getNextRunDate('now', 1);
|
||||
$this->assertEquals($next, $cron->getPreviousRunDate($two));
|
||||
|
||||
$cron = CronExpression::factory('* * * */2 *');
|
||||
$next = $cron->getNextRunDate('now');
|
||||
$two = $cron->getNextRunDate('now', 1);
|
||||
$this->assertEquals($next, $cron->getPreviousRunDate($two));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Cron\CronExpression::getMultipleRunDates
|
||||
*/
|
||||
public function testProvidesMultipleRunDates()
|
||||
{
|
||||
$cron = CronExpression::factory('*/2 * * * *');
|
||||
$this->assertEquals(array(
|
||||
new DateTime('2008-11-09 00:00:00'),
|
||||
new DateTime('2008-11-09 00:02:00'),
|
||||
new DateTime('2008-11-09 00:04:00'),
|
||||
new DateTime('2008-11-09 00:06:00')
|
||||
), $cron->getMultipleRunDates(4, '2008-11-09 00:00:00', false, true));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Cron\CronExpression::getMultipleRunDates
|
||||
* @covers \Cron\CronExpression::setMaxIterationCount
|
||||
*/
|
||||
public function testProvidesMultipleRunDatesForTheFarFuture() {
|
||||
// Fails with the default 1000 iteration limit
|
||||
$cron = CronExpression::factory('0 0 12 1 *');
|
||||
$cron->setMaxIterationCount(2000);
|
||||
$this->assertEquals(array(
|
||||
new DateTime('2016-01-12 00:00:00'),
|
||||
new DateTime('2017-01-12 00:00:00'),
|
||||
new DateTime('2018-01-12 00:00:00'),
|
||||
new DateTime('2019-01-12 00:00:00'),
|
||||
new DateTime('2020-01-12 00:00:00'),
|
||||
new DateTime('2021-01-12 00:00:00'),
|
||||
new DateTime('2022-01-12 00:00:00'),
|
||||
new DateTime('2023-01-12 00:00:00'),
|
||||
new DateTime('2024-01-12 00:00:00'),
|
||||
), $cron->getMultipleRunDates(9, '2015-04-28 00:00:00', false, true));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Cron\CronExpression
|
||||
*/
|
||||
public function testCanIterateOverNextRuns()
|
||||
{
|
||||
$cron = CronExpression::factory('@weekly');
|
||||
$nextRun = $cron->getNextRunDate("2008-11-09 08:00:00");
|
||||
$this->assertEquals($nextRun, new DateTime("2008-11-16 00:00:00"));
|
||||
|
||||
// true is cast to 1
|
||||
$nextRun = $cron->getNextRunDate("2008-11-09 00:00:00", true, true);
|
||||
$this->assertEquals($nextRun, new DateTime("2008-11-16 00:00:00"));
|
||||
|
||||
// You can iterate over them
|
||||
$nextRun = $cron->getNextRunDate($cron->getNextRunDate("2008-11-09 00:00:00", 1, true), 1, true);
|
||||
$this->assertEquals($nextRun, new DateTime("2008-11-23 00:00:00"));
|
||||
|
||||
// You can skip more than one
|
||||
$nextRun = $cron->getNextRunDate("2008-11-09 00:00:00", 2, true);
|
||||
$this->assertEquals($nextRun, new DateTime("2008-11-23 00:00:00"));
|
||||
$nextRun = $cron->getNextRunDate("2008-11-09 00:00:00", 3, true);
|
||||
$this->assertEquals($nextRun, new DateTime("2008-11-30 00:00:00"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Cron\CronExpression::getRunDate
|
||||
*/
|
||||
public function testSkipsCurrentDateByDefault()
|
||||
{
|
||||
$cron = CronExpression::factory('* * * * *');
|
||||
$current = new DateTime('now');
|
||||
$next = $cron->getNextRunDate($current);
|
||||
$nextPrev = $cron->getPreviousRunDate($next);
|
||||
$this->assertSame($current->format('Y-m-d H:i:00'), $nextPrev->format('Y-m-d H:i:s'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Cron\CronExpression::getRunDate
|
||||
* @ticket 7
|
||||
*/
|
||||
public function testStripsForSeconds()
|
||||
{
|
||||
$cron = CronExpression::factory('* * * * *');
|
||||
$current = new DateTime('2011-09-27 10:10:54');
|
||||
$this->assertSame('2011-09-27 10:11:00', $cron->getNextRunDate($current)->format('Y-m-d H:i:s'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Cron\CronExpression::getRunDate
|
||||
*/
|
||||
public function testFixesPhpBugInDateIntervalMonth()
|
||||
{
|
||||
$cron = CronExpression::factory('0 0 27 JAN *');
|
||||
$this->assertSame('2011-01-27 00:00:00', $cron->getPreviousRunDate('2011-08-22 00:00:00')->format('Y-m-d H:i:s'));
|
||||
}
|
||||
|
||||
public function testIssue29()
|
||||
{
|
||||
$cron = CronExpression::factory('@weekly');
|
||||
$this->assertSame(
|
||||
'2013-03-10 00:00:00',
|
||||
$cron->getPreviousRunDate('2013-03-17 00:00:00')->format('Y-m-d H:i:s')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see https://github.com/mtdowling/cron-expression/issues/20
|
||||
*/
|
||||
public function testIssue20() {
|
||||
$e = CronExpression::factory('* * * * MON#1');
|
||||
$this->assertTrue($e->isDue(new DateTime('2014-04-07 00:00:00')));
|
||||
$this->assertFalse($e->isDue(new DateTime('2014-04-14 00:00:00')));
|
||||
$this->assertFalse($e->isDue(new DateTime('2014-04-21 00:00:00')));
|
||||
|
||||
$e = CronExpression::factory('* * * * SAT#2');
|
||||
$this->assertFalse($e->isDue(new DateTime('2014-04-05 00:00:00')));
|
||||
$this->assertTrue($e->isDue(new DateTime('2014-04-12 00:00:00')));
|
||||
$this->assertFalse($e->isDue(new DateTime('2014-04-19 00:00:00')));
|
||||
|
||||
$e = CronExpression::factory('* * * * SUN#3');
|
||||
$this->assertFalse($e->isDue(new DateTime('2014-04-13 00:00:00')));
|
||||
$this->assertTrue($e->isDue(new DateTime('2014-04-20 00:00:00')));
|
||||
$this->assertFalse($e->isDue(new DateTime('2014-04-27 00:00:00')));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Cron\CronExpression::getRunDate
|
||||
*/
|
||||
public function testKeepOriginalTime()
|
||||
{
|
||||
$now = new \DateTime;
|
||||
$strNow = $now->format(DateTime::ISO8601);
|
||||
$cron = CronExpression::factory('0 0 * * *');
|
||||
$cron->getPreviousRunDate($now);
|
||||
$this->assertSame($strNow, $now->format(DateTime::ISO8601));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Cron\CronExpression::__construct
|
||||
* @covers \Cron\CronExpression::factory
|
||||
* @covers \Cron\CronExpression::isValidExpression
|
||||
* @covers \Cron\CronExpression::setExpression
|
||||
* @covers \Cron\CronExpression::setPart
|
||||
*/
|
||||
public function testValidationWorks()
|
||||
{
|
||||
// Invalid. Only four values
|
||||
$this->assertFalse(CronExpression::isValidExpression('* * * 1'));
|
||||
// Valid
|
||||
$this->assertTrue(CronExpression::isValidExpression('* * * * 1'));
|
||||
|
||||
// Issue #156, 13 is an invalid month
|
||||
$this->assertFalse(CronExpression::isValidExpression("* * * 13 * "));
|
||||
|
||||
// Issue #155, 90 is an invalid second
|
||||
$this->assertFalse(CronExpression::isValidExpression('90 * * * *'));
|
||||
|
||||
// Issue #154, 24 is an invalid hour
|
||||
$this->assertFalse(CronExpression::isValidExpression("0 24 1 12 0"));
|
||||
|
||||
// Issue #125, this is just all sorts of wrong
|
||||
$this->assertFalse(CronExpression::isValidExpression('990 14 * * mon-fri0345345'));
|
||||
|
||||
// see https://github.com/dragonmantank/cron-expression/issues/5
|
||||
$this->assertTrue(CronExpression::isValidExpression('2,17,35,47 5-7,11-13 * * *'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes sure that 00 is considered a valid value for 0-based fields
|
||||
* cronie allows numbers with a leading 0, so adding support for this as well
|
||||
*
|
||||
* @see https://github.com/dragonmantank/cron-expression/issues/12
|
||||
*/
|
||||
public function testDoubleZeroIsValid()
|
||||
{
|
||||
$this->assertTrue(CronExpression::isValidExpression('00 * * * *'));
|
||||
$this->assertTrue(CronExpression::isValidExpression('01 * * * *'));
|
||||
$this->assertTrue(CronExpression::isValidExpression('* 00 * * *'));
|
||||
$this->assertTrue(CronExpression::isValidExpression('* 01 * * *'));
|
||||
|
||||
$e = CronExpression::factory('00 * * * *');
|
||||
$this->assertTrue($e->isDue(new DateTime('2014-04-07 00:00:00')));
|
||||
$e = CronExpression::factory('01 * * * *');
|
||||
$this->assertTrue($e->isDue(new DateTime('2014-04-07 00:01:00')));
|
||||
|
||||
$e = CronExpression::factory('* 00 * * *');
|
||||
$this->assertTrue($e->isDue(new DateTime('2014-04-07 00:00:00')));
|
||||
$e = CronExpression::factory('* 01 * * *');
|
||||
$this->assertTrue($e->isDue(new DateTime('2014-04-07 01:00:00')));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Ranges with large steps should "wrap around" to the appropriate value
|
||||
* cronie allows for steps that are larger than the range of a field, with it wrapping around like a ring buffer. We
|
||||
* should do the same.
|
||||
*
|
||||
* @see https://github.com/dragonmantank/cron-expression/issues/6
|
||||
*/
|
||||
public function testRangesWrapAroundWithLargeSteps()
|
||||
{
|
||||
$f = new MonthField();
|
||||
$this->assertTrue($f->validate('*/123'));
|
||||
$this->assertSame([4], $f->getRangeForExpression('*/123', 12));
|
||||
|
||||
$e = CronExpression::factory('* * * */123 *');
|
||||
$this->assertTrue($e->isDue(new DateTime('2014-04-07 00:00:00')));
|
||||
|
||||
$nextRunDate = $e->getNextRunDate(new DateTime('2014-04-07 00:00:00'));
|
||||
$this->assertSame('2014-04-07 00:01:00', $nextRunDate->format('Y-m-d H:i:s'));
|
||||
|
||||
$nextRunDate = $e->getNextRunDate(new DateTime('2014-05-07 00:00:00'));
|
||||
$this->assertSame('2015-04-01 00:00:00', $nextRunDate->format('Y-m-d H:i:s'));
|
||||
}
|
||||
}
|
64
vendor/dragonmantank/cron-expression/tests/Cron/DayOfMonthFieldTest.php
vendored
Normal file
64
vendor/dragonmantank/cron-expression/tests/Cron/DayOfMonthFieldTest.php
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace Cron\Tests;
|
||||
|
||||
use Cron\DayOfMonthField;
|
||||
use DateTime;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @author Michael Dowling <mtdowling@gmail.com>
|
||||
*/
|
||||
class DayOfMonthFieldTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers \Cron\DayOfMonthField::validate
|
||||
*/
|
||||
public function testValidatesField()
|
||||
{
|
||||
$f = new DayOfMonthField();
|
||||
$this->assertTrue($f->validate('1'));
|
||||
$this->assertTrue($f->validate('*'));
|
||||
$this->assertTrue($f->validate('L'));
|
||||
$this->assertTrue($f->validate('5W'));
|
||||
$this->assertTrue($f->validate('01'));
|
||||
$this->assertFalse($f->validate('5W,L'));
|
||||
$this->assertFalse($f->validate('1.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Cron\DayOfMonthField::isSatisfiedBy
|
||||
*/
|
||||
public function testChecksIfSatisfied()
|
||||
{
|
||||
$f = new DayOfMonthField();
|
||||
$this->assertTrue($f->isSatisfiedBy(new DateTime(), '?'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Cron\DayOfMonthField::increment
|
||||
*/
|
||||
public function testIncrementsDate()
|
||||
{
|
||||
$d = new DateTime('2011-03-15 11:15:00');
|
||||
$f = new DayOfMonthField();
|
||||
$f->increment($d);
|
||||
$this->assertSame('2011-03-16 00:00:00', $d->format('Y-m-d H:i:s'));
|
||||
|
||||
$d = new DateTime('2011-03-15 11:15:00');
|
||||
$f->increment($d, true);
|
||||
$this->assertSame('2011-03-14 23:59:00', $d->format('Y-m-d H:i:s'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Day of the month cannot accept a 0 value, it must be between 1 and 31
|
||||
* See Github issue #120
|
||||
*
|
||||
* @since 2017-01-22
|
||||
*/
|
||||
public function testDoesNotAccept0Date()
|
||||
{
|
||||
$f = new DayOfMonthField();
|
||||
$this->assertFalse($f->validate(0));
|
||||
}
|
||||
}
|
129
vendor/dragonmantank/cron-expression/tests/Cron/DayOfWeekFieldTest.php
vendored
Normal file
129
vendor/dragonmantank/cron-expression/tests/Cron/DayOfWeekFieldTest.php
vendored
Normal file
@@ -0,0 +1,129 @@
|
||||
<?php
|
||||
|
||||
namespace Cron\Tests;
|
||||
|
||||
use Cron\DayOfWeekField;
|
||||
use DateTime;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @author Michael Dowling <mtdowling@gmail.com>
|
||||
*/
|
||||
class DayOfWeekFieldTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers \Cron\DayOfWeekField::validate
|
||||
*/
|
||||
public function testValidatesField()
|
||||
{
|
||||
$f = new DayOfWeekField();
|
||||
$this->assertTrue($f->validate('1'));
|
||||
$this->assertTrue($f->validate('01'));
|
||||
$this->assertTrue($f->validate('00'));
|
||||
$this->assertTrue($f->validate('*'));
|
||||
$this->assertFalse($f->validate('*/3,1,1-12'));
|
||||
$this->assertTrue($f->validate('SUN-2'));
|
||||
$this->assertFalse($f->validate('1.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Cron\DayOfWeekField::isSatisfiedBy
|
||||
*/
|
||||
public function testChecksIfSatisfied()
|
||||
{
|
||||
$f = new DayOfWeekField();
|
||||
$this->assertTrue($f->isSatisfiedBy(new DateTime(), '?'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Cron\DayOfWeekField::increment
|
||||
*/
|
||||
public function testIncrementsDate()
|
||||
{
|
||||
$d = new DateTime('2011-03-15 11:15:00');
|
||||
$f = new DayOfWeekField();
|
||||
$f->increment($d);
|
||||
$this->assertSame('2011-03-16 00:00:00', $d->format('Y-m-d H:i:s'));
|
||||
|
||||
$d = new DateTime('2011-03-15 11:15:00');
|
||||
$f->increment($d, true);
|
||||
$this->assertSame('2011-03-14 23:59:00', $d->format('Y-m-d H:i:s'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Cron\DayOfWeekField::isSatisfiedBy
|
||||
* @expectedException InvalidArgumentException
|
||||
* @expectedExceptionMessage Weekday must be a value between 0 and 7. 12 given
|
||||
*/
|
||||
public function testValidatesHashValueWeekday()
|
||||
{
|
||||
$f = new DayOfWeekField();
|
||||
$this->assertTrue($f->isSatisfiedBy(new DateTime(), '12#1'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Cron\DayOfWeekField::isSatisfiedBy
|
||||
* @expectedException InvalidArgumentException
|
||||
* @expectedExceptionMessage There are never more than 5 or less than 1 of a given weekday in a month
|
||||
*/
|
||||
public function testValidatesHashValueNth()
|
||||
{
|
||||
$f = new DayOfWeekField();
|
||||
$this->assertTrue($f->isSatisfiedBy(new DateTime(), '3#6'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Cron\DayOfWeekField::validate
|
||||
*/
|
||||
public function testValidateWeekendHash()
|
||||
{
|
||||
$f = new DayOfWeekField();
|
||||
$this->assertTrue($f->validate('MON#1'));
|
||||
$this->assertTrue($f->validate('TUE#2'));
|
||||
$this->assertTrue($f->validate('WED#3'));
|
||||
$this->assertTrue($f->validate('THU#4'));
|
||||
$this->assertTrue($f->validate('FRI#5'));
|
||||
$this->assertTrue($f->validate('SAT#1'));
|
||||
$this->assertTrue($f->validate('SUN#3'));
|
||||
$this->assertTrue($f->validate('MON#1,MON#3'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Cron\DayOfWeekField::isSatisfiedBy
|
||||
*/
|
||||
public function testHandlesZeroAndSevenDayOfTheWeekValues()
|
||||
{
|
||||
$f = new DayOfWeekField();
|
||||
$this->assertTrue($f->isSatisfiedBy(new DateTime('2011-09-04 00:00:00'), '0-2'));
|
||||
$this->assertTrue($f->isSatisfiedBy(new DateTime('2011-09-04 00:00:00'), '6-0'));
|
||||
|
||||
$this->assertTrue($f->isSatisfiedBy(new DateTime('2014-04-20 00:00:00'), 'SUN'));
|
||||
$this->assertTrue($f->isSatisfiedBy(new DateTime('2014-04-20 00:00:00'), 'SUN#3'));
|
||||
$this->assertTrue($f->isSatisfiedBy(new DateTime('2014-04-20 00:00:00'), '0#3'));
|
||||
$this->assertTrue($f->isSatisfiedBy(new DateTime('2014-04-20 00:00:00'), '7#3'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see https://github.com/mtdowling/cron-expression/issues/47
|
||||
*/
|
||||
public function testIssue47() {
|
||||
$f = new DayOfWeekField();
|
||||
$this->assertFalse($f->validate('mon,'));
|
||||
$this->assertFalse($f->validate('mon-'));
|
||||
$this->assertFalse($f->validate('*/2,'));
|
||||
$this->assertFalse($f->validate('-mon'));
|
||||
$this->assertFalse($f->validate(',1'));
|
||||
$this->assertFalse($f->validate('*-'));
|
||||
$this->assertFalse($f->validate(',-'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see https://github.com/laravel/framework/commit/07d160ac3cc9764d5b429734ffce4fa311385403
|
||||
*/
|
||||
public function testLiteralsExpandProperly()
|
||||
{
|
||||
$f = new DayOfWeekField();
|
||||
$this->assertTrue($f->validate('MON-FRI'));
|
||||
$this->assertSame([1,2,3,4,5], $f->getRangeForExpression('MON-FRI', 7));
|
||||
}
|
||||
}
|
42
vendor/dragonmantank/cron-expression/tests/Cron/FieldFactoryTest.php
vendored
Normal file
42
vendor/dragonmantank/cron-expression/tests/Cron/FieldFactoryTest.php
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace Cron\Tests;
|
||||
|
||||
use Cron\FieldFactory;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @author Michael Dowling <mtdowling@gmail.com>
|
||||
*/
|
||||
class FieldFactoryTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers \Cron\FieldFactory::getField
|
||||
*/
|
||||
public function testRetrievesFieldInstances()
|
||||
{
|
||||
$mappings = array(
|
||||
0 => 'Cron\MinutesField',
|
||||
1 => 'Cron\HoursField',
|
||||
2 => 'Cron\DayOfMonthField',
|
||||
3 => 'Cron\MonthField',
|
||||
4 => 'Cron\DayOfWeekField',
|
||||
);
|
||||
|
||||
$f = new FieldFactory();
|
||||
|
||||
foreach ($mappings as $position => $class) {
|
||||
$this->assertSame($class, get_class($f->getField($position)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Cron\FieldFactory::getField
|
||||
* @expectedException InvalidArgumentException
|
||||
*/
|
||||
public function testValidatesFieldPosition()
|
||||
{
|
||||
$f = new FieldFactory();
|
||||
$f->getField(-1);
|
||||
}
|
||||
}
|
77
vendor/dragonmantank/cron-expression/tests/Cron/HoursFieldTest.php
vendored
Normal file
77
vendor/dragonmantank/cron-expression/tests/Cron/HoursFieldTest.php
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
namespace Cron\Tests;
|
||||
|
||||
use Cron\HoursField;
|
||||
use DateTime;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @author Michael Dowling <mtdowling@gmail.com>
|
||||
*/
|
||||
class HoursFieldTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers \Cron\HoursField::validate
|
||||
*/
|
||||
public function testValidatesField()
|
||||
{
|
||||
$f = new HoursField();
|
||||
$this->assertTrue($f->validate('1'));
|
||||
$this->assertTrue($f->validate('00'));
|
||||
$this->assertTrue($f->validate('01'));
|
||||
$this->assertTrue($f->validate('*'));
|
||||
$this->assertFalse($f->validate('*/3,1,1-12'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Cron\HoursField::increment
|
||||
*/
|
||||
public function testIncrementsDate()
|
||||
{
|
||||
$d = new DateTime('2011-03-15 11:15:00');
|
||||
$f = new HoursField();
|
||||
$f->increment($d);
|
||||
$this->assertSame('2011-03-15 12:00:00', $d->format('Y-m-d H:i:s'));
|
||||
|
||||
$d->setTime(11, 15, 0);
|
||||
$f->increment($d, true);
|
||||
$this->assertSame('2011-03-15 10:59:00', $d->format('Y-m-d H:i:s'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Cron\HoursField::increment
|
||||
*/
|
||||
public function testIncrementsDateWithThirtyMinuteOffsetTimezone()
|
||||
{
|
||||
$tz = date_default_timezone_get();
|
||||
date_default_timezone_set('America/St_Johns');
|
||||
$d = new DateTime('2011-03-15 11:15:00');
|
||||
$f = new HoursField();
|
||||
$f->increment($d);
|
||||
$this->assertSame('2011-03-15 12:00:00', $d->format('Y-m-d H:i:s'));
|
||||
|
||||
$d->setTime(11, 15, 0);
|
||||
$f->increment($d, true);
|
||||
$this->assertSame('2011-03-15 10:59:00', $d->format('Y-m-d H:i:s'));
|
||||
date_default_timezone_set($tz);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Cron\HoursField::increment
|
||||
*/
|
||||
public function testIncrementDateWithFifteenMinuteOffsetTimezone()
|
||||
{
|
||||
$tz = date_default_timezone_get();
|
||||
date_default_timezone_set('Asia/Kathmandu');
|
||||
$d = new DateTime('2011-03-15 11:15:00');
|
||||
$f = new HoursField();
|
||||
$f->increment($d);
|
||||
$this->assertSame('2011-03-15 12:00:00', $d->format('Y-m-d H:i:s'));
|
||||
|
||||
$d->setTime(11, 15, 0);
|
||||
$f->increment($d, true);
|
||||
$this->assertSame('2011-03-15 10:59:00', $d->format('Y-m-d H:i:s'));
|
||||
date_default_timezone_set($tz);
|
||||
}
|
||||
}
|
51
vendor/dragonmantank/cron-expression/tests/Cron/MinutesFieldTest.php
vendored
Normal file
51
vendor/dragonmantank/cron-expression/tests/Cron/MinutesFieldTest.php
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace Cron\Tests;
|
||||
|
||||
use Cron\MinutesField;
|
||||
use DateTime;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @author Michael Dowling <mtdowling@gmail.com>
|
||||
*/
|
||||
class MinutesFieldTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers \Cron\MinutesField::validate
|
||||
*/
|
||||
public function testValidatesField()
|
||||
{
|
||||
$f = new MinutesField();
|
||||
$this->assertTrue($f->validate('1'));
|
||||
$this->assertTrue($f->validate('*'));
|
||||
$this->assertFalse($f->validate('*/3,1,1-12'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Cron\MinutesField::increment
|
||||
*/
|
||||
public function testIncrementsDate()
|
||||
{
|
||||
$d = new DateTime('2011-03-15 11:15:00');
|
||||
$f = new MinutesField();
|
||||
$f->increment($d);
|
||||
$this->assertSame('2011-03-15 11:16:00', $d->format('Y-m-d H:i:s'));
|
||||
$f->increment($d, true);
|
||||
$this->assertSame('2011-03-15 11:15:00', $d->format('Y-m-d H:i:s'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Various bad syntaxes that are reported to work, but shouldn't.
|
||||
*
|
||||
* @author Chris Tankersley
|
||||
* @since 2017-08-18
|
||||
*/
|
||||
public function testBadSyntaxesShouldNotValidate()
|
||||
{
|
||||
$f = new MinutesField();
|
||||
$this->assertFalse($f->validate('*-1'));
|
||||
$this->assertFalse($f->validate('1-2-3'));
|
||||
$this->assertFalse($f->validate('-1'));
|
||||
}
|
||||
}
|
81
vendor/dragonmantank/cron-expression/tests/Cron/MonthFieldTest.php
vendored
Normal file
81
vendor/dragonmantank/cron-expression/tests/Cron/MonthFieldTest.php
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
namespace Cron\Tests;
|
||||
|
||||
use Cron\MonthField;
|
||||
use DateTime;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @author Michael Dowling <mtdowling@gmail.com>
|
||||
*/
|
||||
class MonthFieldTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers \Cron\MonthField::validate
|
||||
*/
|
||||
public function testValidatesField()
|
||||
{
|
||||
$f = new MonthField();
|
||||
$this->assertTrue($f->validate('12'));
|
||||
$this->assertTrue($f->validate('*'));
|
||||
$this->assertFalse($f->validate('*/10,2,1-12'));
|
||||
$this->assertFalse($f->validate('1.fix-regexp'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Cron\MonthField::increment
|
||||
*/
|
||||
public function testIncrementsDate()
|
||||
{
|
||||
$d = new DateTime('2011-03-15 11:15:00');
|
||||
$f = new MonthField();
|
||||
$f->increment($d);
|
||||
$this->assertSame('2011-04-01 00:00:00', $d->format('Y-m-d H:i:s'));
|
||||
|
||||
$d = new DateTime('2011-03-15 11:15:00');
|
||||
$f->increment($d, true);
|
||||
$this->assertSame('2011-02-28 23:59:00', $d->format('Y-m-d H:i:s'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Cron\MonthField::increment
|
||||
*/
|
||||
public function testIncrementsDateWithThirtyMinuteTimezone()
|
||||
{
|
||||
$tz = date_default_timezone_get();
|
||||
date_default_timezone_set('America/St_Johns');
|
||||
$d = new DateTime('2011-03-31 11:59:59');
|
||||
$f = new MonthField();
|
||||
$f->increment($d);
|
||||
$this->assertSame('2011-04-01 00:00:00', $d->format('Y-m-d H:i:s'));
|
||||
|
||||
$d = new DateTime('2011-03-15 11:15:00');
|
||||
$f->increment($d, true);
|
||||
$this->assertSame('2011-02-28 23:59:00', $d->format('Y-m-d H:i:s'));
|
||||
date_default_timezone_set($tz);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @covers \Cron\MonthField::increment
|
||||
*/
|
||||
public function testIncrementsYearAsNeeded()
|
||||
{
|
||||
$f = new MonthField();
|
||||
$d = new DateTime('2011-12-15 00:00:00');
|
||||
$f->increment($d);
|
||||
$this->assertSame('2012-01-01 00:00:00', $d->format('Y-m-d H:i:s'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Cron\MonthField::increment
|
||||
*/
|
||||
public function testDecrementsYearAsNeeded()
|
||||
{
|
||||
$f = new MonthField();
|
||||
$d = new DateTime('2011-01-15 00:00:00');
|
||||
$f->increment($d, true);
|
||||
$this->assertSame('2010-12-31 23:59:00', $d->format('Y-m-d H:i:s'));
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user