schedule monitor
This commit is contained in:
42
vendor/lorisleiva/cron-translator/.github/workflows/tests.yml
vendored
Normal file
42
vendor/lorisleiva/cron-translator/.github/workflows/tests.yml
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
name: Tests
|
||||
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
phpunit73:
|
||||
name: "Tests on PHP 7.3"
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: lorisleiva/laravel-docker:7.3
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Validate composer.json and composer.lock
|
||||
run: composer validate
|
||||
- name: Cache dependencies
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: /composer/cache/files
|
||||
key: dependencies-composer-${{ hashFiles('composer.json') }}
|
||||
- name: Install dependencies
|
||||
run: composer install --prefer-dist --no-progress --no-suggest
|
||||
- name: Run tests
|
||||
run: phpunit
|
||||
|
||||
phpunit74:
|
||||
name: "Tests on PHP 7.4"
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: lorisleiva/laravel-docker:7.4
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Validate composer.json and composer.lock
|
||||
run: composer validate
|
||||
- name: Cache dependencies
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: /composer/cache/files
|
||||
key: dependencies-composer-${{ hashFiles('composer.json') }}
|
||||
- name: Install dependencies
|
||||
run: composer install --prefer-dist --no-progress --no-suggest
|
||||
- name: Run tests
|
||||
run: phpunit
|
||||
4
vendor/lorisleiva/cron-translator/.gitignore
vendored
Normal file
4
vendor/lorisleiva/cron-translator/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
vendor
|
||||
composer.lock
|
||||
.phpunit.result.cache
|
||||
build
|
||||
21
vendor/lorisleiva/cron-translator/LICENSE
vendored
Normal file
21
vendor/lorisleiva/cron-translator/LICENSE
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 Loris Leiva
|
||||
|
||||
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.
|
||||
31
vendor/lorisleiva/cron-translator/README.md
vendored
Normal file
31
vendor/lorisleiva/cron-translator/README.md
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
# CRON Translator
|
||||
⏰️ Makes CRON expressions human-readable
|
||||
|
||||

|
||||
|
||||
## Installation
|
||||
|
||||
```sh
|
||||
composer require lorisleiva/cron-translator
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```php
|
||||
use Lorisleiva\CronTranslator\CronTranslator;
|
||||
|
||||
CronTranslator::translate('* * * * *'); // => Every minute
|
||||
CronTranslator::translate('30 22 * * *'); // => Every day at 10:30pm
|
||||
CronTranslator::translate('0 16 * * 1'); // => Every Monday at 4:00pm
|
||||
CronTranslator::translate('0 0 1 1 *'); // => Every year on January the 1st at 12:00am
|
||||
CronTranslator::translate('0 0 1 * *'); // => The 1st of every month at 12:00am
|
||||
CronTranslator::translate('0 * * * 1'); // => Once an hour on Mondays
|
||||
CronTranslator::translate('* 1-20 * * *'); // => Every minute 20 hours a day
|
||||
CronTranslator::translate('0,30 * * * *'); // => Twice an hour
|
||||
CronTranslator::translate('0 1-5 * * *'); // => 5 times a day
|
||||
CronTranslator::translate('0 1 1-5 * *'); // => 5 days a month at 1:00am
|
||||
CronTranslator::translate('*/2 * * * *'); // => Every 2 minutes
|
||||
CronTranslator::translate('* 1/3 2 * *'); // => Every minute of every 3 hours on the 2nd of every month
|
||||
CronTranslator::translate('1-3/5 * * * *'); // => 3 times every 5 minutes
|
||||
CronTranslator::translate('1,2 0 */2 1,2 *'); // => Twice an hour every 2 days 2 months a year at 12am
|
||||
```
|
||||
33
vendor/lorisleiva/cron-translator/composer.json
vendored
Normal file
33
vendor/lorisleiva/cron-translator/composer.json
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"name": "lorisleiva/cron-translator",
|
||||
"description": "Makes CRON expressions human-readable",
|
||||
"keywords": [
|
||||
"cron",
|
||||
"expression",
|
||||
"human"
|
||||
],
|
||||
"homepage": "https://github.com/lorisleiva/cron-translator",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Loris LEIVA",
|
||||
"email": "loris.leiva@gmail.com",
|
||||
"homepage": "https://lorisleiva.com"
|
||||
}
|
||||
],
|
||||
"require-dev": {
|
||||
"phpunit/phpunit" : "^8.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Lorisleiva\\CronTranslator\\": "src"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Lorisleiva\\CronTranslator\\Tests\\": "tests"
|
||||
}
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"prefer-stable": true
|
||||
}
|
||||
21
vendor/lorisleiva/cron-translator/phpunit.xml
vendored
Normal file
21
vendor/lorisleiva/cron-translator/phpunit.xml
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit backupGlobals="false"
|
||||
backupStaticAttributes="false"
|
||||
bootstrap="vendor/autoload.php"
|
||||
colors="true"
|
||||
convertErrorsToExceptions="true"
|
||||
convertNoticesToExceptions="true"
|
||||
convertWarningsToExceptions="true"
|
||||
processIsolation="false"
|
||||
stopOnFailure="false">
|
||||
<testsuites>
|
||||
<testsuite name="Test Suite">
|
||||
<directory suffix="Test.php">./tests</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
<filter>
|
||||
<whitelist processUncoveredFilesFromWhitelist="true">
|
||||
<directory suffix=".php">./src</directory>
|
||||
</whitelist>
|
||||
</filter>
|
||||
</phpunit>
|
||||
13
vendor/lorisleiva/cron-translator/src/CronParsingException.php
vendored
Normal file
13
vendor/lorisleiva/cron-translator/src/CronParsingException.php
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace Lorisleiva\CronTranslator;
|
||||
|
||||
use Exception;
|
||||
|
||||
class CronParsingException extends Exception
|
||||
{
|
||||
public function __construct($cron)
|
||||
{
|
||||
parent::__construct("Failed to parse the following CRON expression: {$cron}");
|
||||
}
|
||||
}
|
||||
98
vendor/lorisleiva/cron-translator/src/CronTranslator.php
vendored
Normal file
98
vendor/lorisleiva/cron-translator/src/CronTranslator.php
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
namespace Lorisleiva\CronTranslator;
|
||||
|
||||
class CronTranslator
|
||||
{
|
||||
private static $extendedMap = [
|
||||
'@yearly' => '0 0 1 1 *',
|
||||
'@annually' => '0 0 1 1 *',
|
||||
'@monthly' => '0 0 1 * *',
|
||||
'@weekly' => '0 0 * * 0',
|
||||
'@daily' => '0 0 * * *',
|
||||
'@hourly' => '0 * * * *'
|
||||
];
|
||||
|
||||
public static function translate($cron)
|
||||
{
|
||||
if (isset(self::$extendedMap[$cron])) {
|
||||
$cron = self::$extendedMap[$cron];
|
||||
}
|
||||
|
||||
try {
|
||||
$fields = static::parseFields($cron);
|
||||
$orderedFields = static::orderFields($fields);
|
||||
$fieldsAsObject = static::getFieldsAsObject($fields);
|
||||
|
||||
$translations = array_map(function ($field) use ($fieldsAsObject) {
|
||||
return $field->translate($fieldsAsObject);
|
||||
}, $orderedFields);
|
||||
|
||||
return ucfirst(implode(' ', array_filter($translations)));
|
||||
} catch (\Throwable $th) {
|
||||
throw new CronParsingException($cron);
|
||||
}
|
||||
}
|
||||
|
||||
protected static function parseFields($cron)
|
||||
{
|
||||
$fields = explode(' ', $cron);
|
||||
|
||||
return [
|
||||
new MinutesField($fields[0]),
|
||||
new HoursField($fields[1]),
|
||||
new DaysOfMonthField($fields[2]),
|
||||
new MonthsField($fields[3]),
|
||||
new DaysOfWeekField($fields[4]),
|
||||
];
|
||||
}
|
||||
|
||||
protected static function orderFields($fields)
|
||||
{
|
||||
// Group fields by CRON types.
|
||||
$onces = static::filterType($fields, 'Once');
|
||||
$everys = static::filterType($fields, 'Every');
|
||||
$incrementsAndMultiples = static::filterType($fields, 'Increment', 'Multiple');
|
||||
|
||||
// Decide whether to keep one or zero CRON type "Every".
|
||||
$firstEvery = reset($everys)->position ?? PHP_INT_MIN;
|
||||
$firstIncrementOrMultiple = reset($incrementsAndMultiples)->position ?? PHP_INT_MAX;
|
||||
$numberOfEverysKept = $firstIncrementOrMultiple < $firstEvery ? 0 : 1;
|
||||
|
||||
// Mark fields that will not be displayed as dropped.
|
||||
// This allows other fields to check whether some
|
||||
// information is missing and adapt their translation.
|
||||
foreach (array_slice($everys, $numberOfEverysKept) as $field) {
|
||||
$field->dropped = true;
|
||||
}
|
||||
|
||||
return array_merge(
|
||||
// Place one or zero "Every" field at the beginning.
|
||||
array_slice($everys, 0, $numberOfEverysKept),
|
||||
|
||||
// Place all "Increment" and "Multiple" fields in the middle.
|
||||
$incrementsAndMultiples,
|
||||
|
||||
// Finish with the "Once" fields reversed (i.e. from months to minutes).
|
||||
array_reverse($onces)
|
||||
);
|
||||
}
|
||||
|
||||
protected static function filterType($fields, ...$types)
|
||||
{
|
||||
return array_filter($fields, function ($field) use ($types) {
|
||||
return $field->hasType(...$types);
|
||||
});
|
||||
}
|
||||
|
||||
protected static function getFieldsAsObject($fields)
|
||||
{
|
||||
return (object) [
|
||||
'minute' => $fields[0],
|
||||
'hour' => $fields[1],
|
||||
'day' => $fields[2],
|
||||
'month' => $fields[3],
|
||||
'weekday' => $fields[4],
|
||||
];
|
||||
}
|
||||
}
|
||||
88
vendor/lorisleiva/cron-translator/src/CronType.php
vendored
Normal file
88
vendor/lorisleiva/cron-translator/src/CronType.php
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
namespace Lorisleiva\CronTranslator;
|
||||
|
||||
class CronType
|
||||
{
|
||||
const TYPES = [
|
||||
'Every', 'Increment', 'Multiple', 'Once',
|
||||
];
|
||||
|
||||
public $type;
|
||||
public $value;
|
||||
public $count;
|
||||
public $increment;
|
||||
|
||||
private function __construct($type, $value = null, $count = null, $increment = null)
|
||||
{
|
||||
$this->type = $type;
|
||||
$this->value = $value;
|
||||
$this->count = $count;
|
||||
$this->increment = $increment;
|
||||
}
|
||||
|
||||
public static function every()
|
||||
{
|
||||
return new static('Every');
|
||||
}
|
||||
|
||||
public static function increment($increment, $count = 1)
|
||||
{
|
||||
return new static('Increment', null, $count, $increment);
|
||||
}
|
||||
|
||||
public static function multiple($count)
|
||||
{
|
||||
return new static('Multiple', null, $count);
|
||||
}
|
||||
|
||||
public static function once($value)
|
||||
{
|
||||
return new static('Once', $value);
|
||||
}
|
||||
|
||||
public static function parse($expression)
|
||||
{
|
||||
// Parse "*".
|
||||
if ($expression === '*') {
|
||||
return static::every();
|
||||
}
|
||||
|
||||
// Parse fixed values like "1".
|
||||
if (preg_match("/^[0-9]+$/", $expression)) {
|
||||
return static::once((int) $expression);
|
||||
}
|
||||
|
||||
// Parse multiple selected values like "1,2,5".
|
||||
if (preg_match("/^[0-9]+(,[0-9]+)+$/", $expression)) {
|
||||
return static::multiple(count(explode(',', $expression)));
|
||||
}
|
||||
|
||||
// Parse ranges of selected values like "1-5".
|
||||
if (preg_match("/^([0-9]+)\-([0-9]+)$/", $expression, $matches)) {
|
||||
$count = $matches[2] - $matches[1] + 1;
|
||||
return $count > 1
|
||||
? static::multiple($count)
|
||||
: static::once((int) $matches[1]);
|
||||
}
|
||||
|
||||
// Parse incremental expressions like "*/2", "1-4/10" or "1,3/4".
|
||||
if (preg_match("/(.+)\/([0-9]+)$/", $expression, $matches)) {
|
||||
$range = static::parse($matches[1]);
|
||||
if ($range->hasType('Once', 'Every')) {
|
||||
return static::Increment($matches[2]);
|
||||
}
|
||||
if ($range->hasType('Multiple')) {
|
||||
return static::Increment($matches[2], $range->count);
|
||||
}
|
||||
}
|
||||
|
||||
// Unsupported expressions throw exceptions.
|
||||
throw new CronParsingException($expression);
|
||||
}
|
||||
|
||||
public function hasType()
|
||||
{
|
||||
return in_array($this->type, func_get_args());
|
||||
}
|
||||
}
|
||||
65
vendor/lorisleiva/cron-translator/src/DaysOfMonthField.php
vendored
Normal file
65
vendor/lorisleiva/cron-translator/src/DaysOfMonthField.php
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
namespace Lorisleiva\CronTranslator;
|
||||
|
||||
class DaysOfMonthField extends Field
|
||||
{
|
||||
public $position = 2;
|
||||
|
||||
public function translateEvery($fields)
|
||||
{
|
||||
if ($fields->weekday->hasType('Once')) {
|
||||
return "every {$fields->weekday->format()}";
|
||||
}
|
||||
|
||||
return 'every day';
|
||||
}
|
||||
|
||||
public function translateIncrement()
|
||||
{
|
||||
if ($this->count > 1) {
|
||||
return "{$this->count} days out of {$this->increment}";
|
||||
}
|
||||
|
||||
return "every {$this->increment} days";
|
||||
}
|
||||
|
||||
public function translateMultiple()
|
||||
{
|
||||
return "{$this->count} days a month";
|
||||
}
|
||||
|
||||
public function translateOnce($fields)
|
||||
{
|
||||
if ($fields->month->hasType('Once')) {
|
||||
return; // MonthsField adapts to "On January the 1st".
|
||||
}
|
||||
|
||||
if ($fields->month->hasType('Every') && ! $fields->month->dropped) {
|
||||
return; // MonthsField adapts to "The 1st of every month".
|
||||
}
|
||||
|
||||
if ($fields->month->hasType('Every') && $fields->month->dropped) {
|
||||
return 'on the ' . $this->format() . ' of every month';
|
||||
}
|
||||
|
||||
return 'on the ' . $this->format();
|
||||
}
|
||||
|
||||
public function format()
|
||||
{
|
||||
if (in_array($this->value, [1, 21, 31])) {
|
||||
return $this->value . 'st';
|
||||
}
|
||||
|
||||
if (in_array($this->value, [2, 22])) {
|
||||
return $this->value . 'nd';
|
||||
}
|
||||
|
||||
if (in_array($this->value, [3, 23])) {
|
||||
return $this->value . 'rd';
|
||||
}
|
||||
|
||||
return $this->value . 'th';
|
||||
}
|
||||
}
|
||||
54
vendor/lorisleiva/cron-translator/src/DaysOfWeekField.php
vendored
Normal file
54
vendor/lorisleiva/cron-translator/src/DaysOfWeekField.php
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace Lorisleiva\CronTranslator;
|
||||
|
||||
class DaysOfWeekField extends Field
|
||||
{
|
||||
public $position = 4;
|
||||
|
||||
public function translateEvery()
|
||||
{
|
||||
return 'every year';
|
||||
}
|
||||
|
||||
public function translateIncrement()
|
||||
{
|
||||
if ($this->count > 1) {
|
||||
return "{$this->count} days of the week out of {$this->increment}";
|
||||
}
|
||||
|
||||
return "every {$this->increment} days of the week";
|
||||
}
|
||||
|
||||
public function translateMultiple()
|
||||
{
|
||||
return "{$this->count} days a week";
|
||||
}
|
||||
|
||||
public function translateOnce($fields)
|
||||
{
|
||||
if ($fields->day->hasType('Every') && ! $fields->day->dropped) {
|
||||
return; // DaysOfMonthField adapts to "Every Sunday".
|
||||
}
|
||||
|
||||
return "on {$this->format()}s";
|
||||
}
|
||||
|
||||
public function format()
|
||||
{
|
||||
if ($this->value < 0 || $this->value > 7) {
|
||||
throw new \Exception();
|
||||
}
|
||||
|
||||
return [
|
||||
0 => 'Sunday',
|
||||
1 => 'Monday',
|
||||
2 => 'Tuesday',
|
||||
3 => 'Wednesday',
|
||||
4 => 'Thursday',
|
||||
5 => 'Friday',
|
||||
6 => 'Saturday',
|
||||
7 => 'Sunday',
|
||||
][$this->value];
|
||||
}
|
||||
}
|
||||
47
vendor/lorisleiva/cron-translator/src/Field.php
vendored
Normal file
47
vendor/lorisleiva/cron-translator/src/Field.php
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace Lorisleiva\CronTranslator;
|
||||
|
||||
abstract class Field
|
||||
{
|
||||
public $expression;
|
||||
public $type;
|
||||
public $value;
|
||||
public $count;
|
||||
public $increment;
|
||||
public $dropped = false;
|
||||
public $position;
|
||||
|
||||
public function __construct($expression)
|
||||
{
|
||||
$this->expression = $expression;
|
||||
$cronType = CronType::parse($expression);
|
||||
$this->type = $cronType->type;
|
||||
$this->value = $cronType->value;
|
||||
$this->count = $cronType->count;
|
||||
$this->increment = $cronType->increment;
|
||||
}
|
||||
|
||||
public function translate($fields)
|
||||
{
|
||||
foreach (CronType::TYPES as $type) {
|
||||
if ($this->hasType($type) && method_exists($this, "translate{$type}")) {
|
||||
return $this->{"translate{$type}"}($fields);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function hasType()
|
||||
{
|
||||
return in_array($this->type, func_get_args());
|
||||
}
|
||||
|
||||
public function times($count)
|
||||
{
|
||||
switch ($count) {
|
||||
case 1: return 'once';
|
||||
case 2: return 'twice';
|
||||
default: return "{$count} times";
|
||||
}
|
||||
}
|
||||
}
|
||||
61
vendor/lorisleiva/cron-translator/src/HoursField.php
vendored
Normal file
61
vendor/lorisleiva/cron-translator/src/HoursField.php
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
namespace Lorisleiva\CronTranslator;
|
||||
|
||||
class HoursField extends Field
|
||||
{
|
||||
public $position = 1;
|
||||
|
||||
public function translateEvery($fields)
|
||||
{
|
||||
if ($fields->minute->hasType('Once')) {
|
||||
return 'once an hour';
|
||||
}
|
||||
|
||||
return 'every hour';
|
||||
}
|
||||
|
||||
public function translateIncrement($fields)
|
||||
{
|
||||
if ($fields->minute->hasType('Once')) {
|
||||
return $this->times($this->count) . " every {$this->increment} hours";
|
||||
}
|
||||
|
||||
if ($this->count > 1) {
|
||||
return "{$this->count} hours out of {$this->increment}";
|
||||
}
|
||||
|
||||
if ($fields->minute->hasType('Every')) {
|
||||
return "of every {$this->increment} hours";
|
||||
}
|
||||
|
||||
return "every {$this->increment} hours";
|
||||
}
|
||||
|
||||
public function translateMultiple($fields)
|
||||
{
|
||||
if ($fields->minute->hasType('Once')) {
|
||||
return $this->times($this->count) . " a day";
|
||||
}
|
||||
|
||||
return "{$this->count} hours a day";
|
||||
}
|
||||
|
||||
public function translateOnce($fields)
|
||||
{
|
||||
return 'at ' . $this->format(
|
||||
$fields->minute->hasType('Once') ? $fields->minute : null
|
||||
);
|
||||
}
|
||||
|
||||
public function format($minute = null)
|
||||
{
|
||||
$amOrPm = $this->value < 12 ? 'am' : 'pm';
|
||||
$hour = $this->value === 0 ? 12 : $this->value;
|
||||
$hour = $hour > 12 ? $hour - 12 : $hour;
|
||||
|
||||
return $minute
|
||||
? "{$hour}:{$minute->format()}{$amOrPm}"
|
||||
: "{$hour}{$amOrPm}";
|
||||
}
|
||||
}
|
||||
32
vendor/lorisleiva/cron-translator/src/MinutesField.php
vendored
Normal file
32
vendor/lorisleiva/cron-translator/src/MinutesField.php
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace Lorisleiva\CronTranslator;
|
||||
|
||||
class MinutesField extends Field
|
||||
{
|
||||
public $position = 0;
|
||||
|
||||
public function translateEvery()
|
||||
{
|
||||
return 'every minute';
|
||||
}
|
||||
|
||||
public function translateIncrement()
|
||||
{
|
||||
if ($this->count > 1) {
|
||||
return $this->times($this->count) . " every {$this->increment} minutes";
|
||||
}
|
||||
|
||||
return "every {$this->increment} minutes";
|
||||
}
|
||||
|
||||
public function translateMultiple()
|
||||
{
|
||||
return $this->times($this->count) . " an hour";
|
||||
}
|
||||
|
||||
public function format()
|
||||
{
|
||||
return ($this->value < 10 ? '0' : '') . $this->value;
|
||||
}
|
||||
}
|
||||
62
vendor/lorisleiva/cron-translator/src/MonthsField.php
vendored
Normal file
62
vendor/lorisleiva/cron-translator/src/MonthsField.php
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
namespace Lorisleiva\CronTranslator;
|
||||
|
||||
class MonthsField extends Field
|
||||
{
|
||||
public $position = 3;
|
||||
|
||||
public function translateEvery($fields)
|
||||
{
|
||||
if ($fields->day->hasType('Once')) {
|
||||
return 'the ' . $fields->day->format() . ' of every month';
|
||||
}
|
||||
|
||||
return 'every month';
|
||||
}
|
||||
|
||||
public function translateIncrement()
|
||||
{
|
||||
if ($this->count > 1) {
|
||||
return "{$this->count} months out of {$this->increment}";
|
||||
}
|
||||
|
||||
return "every {$this->increment} months";
|
||||
}
|
||||
|
||||
public function translateMultiple()
|
||||
{
|
||||
return "{$this->count} months a year";
|
||||
}
|
||||
|
||||
public function translateOnce($fields)
|
||||
{
|
||||
if ($fields->day->hasType('Once')) {
|
||||
return "on {$this->format()} the {$fields->day->format()}";
|
||||
}
|
||||
|
||||
return "on {$this->format()}";
|
||||
}
|
||||
|
||||
public function format()
|
||||
{
|
||||
if ($this->value < 1 || $this->value > 12) {
|
||||
throw new \Exception();
|
||||
}
|
||||
|
||||
return [
|
||||
1 => 'January',
|
||||
2 => 'February',
|
||||
3 => 'March',
|
||||
4 => 'April',
|
||||
5 => 'May',
|
||||
6 => 'June',
|
||||
7 => 'July',
|
||||
8 => 'August',
|
||||
9 => 'September',
|
||||
10 => 'October',
|
||||
11 => 'November',
|
||||
12 => 'December',
|
||||
][$this->value];
|
||||
}
|
||||
}
|
||||
142
vendor/lorisleiva/cron-translator/tests/CronTranslatorTest.php
vendored
Normal file
142
vendor/lorisleiva/cron-translator/tests/CronTranslatorTest.php
vendored
Normal file
@@ -0,0 +1,142 @@
|
||||
<?php
|
||||
|
||||
namespace Lorisleiva\CronTranslator\Tests;
|
||||
|
||||
class CronTranslatorTest extends TestCase
|
||||
{
|
||||
/** @test */
|
||||
public function it_translates_expressions_with_every_and_once()
|
||||
{
|
||||
// All 32 (2^5) combinations of Every/Once.
|
||||
$this->assertCronTranslateTo('Every minute', '* * * * *');
|
||||
$this->assertCronTranslateTo('Every minute on Sundays', '* * * * 0');
|
||||
$this->assertCronTranslateTo('Every minute on January', '* * * 1 *');
|
||||
$this->assertCronTranslateTo('Every minute on Sundays on January', '* * * 1 0');
|
||||
$this->assertCronTranslateTo('Every minute on the 1st of every month', '* * 1 * *');
|
||||
$this->assertCronTranslateTo('Every minute on Sundays on the 1st of every month', '* * 1 * 0');
|
||||
$this->assertCronTranslateTo('Every minute on January the 1st', '* * 1 1 *');
|
||||
$this->assertCronTranslateTo('Every minute on Sundays on January the 1st', '* * 1 1 0');
|
||||
$this->assertCronTranslateTo('Every minute at 12am', '* 0 * * *');
|
||||
$this->assertCronTranslateTo('Every minute on Sundays at 12am', '* 0 * * 0');
|
||||
$this->assertCronTranslateTo('Every minute on January at 12am', '* 0 * 1 *');
|
||||
$this->assertCronTranslateTo('Every minute on Sundays on January at 12am', '* 0 * 1 0');
|
||||
$this->assertCronTranslateTo('Every minute on the 1st of every month at 12am', '* 0 1 * *');
|
||||
$this->assertCronTranslateTo('Every minute on Sundays on the 1st of every month at 12am', '* 0 1 * 0');
|
||||
$this->assertCronTranslateTo('Every minute on January the 1st at 12am', '* 0 1 1 *');
|
||||
$this->assertCronTranslateTo('Every minute on Sundays on January the 1st at 12am', '* 0 1 1 0');
|
||||
$this->assertCronTranslateTo('Once an hour', '0 * * * *');
|
||||
$this->assertCronTranslateTo('Once an hour on Sundays', '0 * * * 0');
|
||||
$this->assertCronTranslateTo('Once an hour on January', '0 * * 1 *');
|
||||
$this->assertCronTranslateTo('Once an hour on Sundays on January', '0 * * 1 0');
|
||||
$this->assertCronTranslateTo('Once an hour on the 1st of every month', '0 * 1 * *');
|
||||
$this->assertCronTranslateTo('Once an hour on Sundays on the 1st of every month', '0 * 1 * 0');
|
||||
$this->assertCronTranslateTo('Once an hour on January the 1st', '0 * 1 1 *');
|
||||
$this->assertCronTranslateTo('Once an hour on Sundays on January the 1st', '0 * 1 1 0');
|
||||
$this->assertCronTranslateTo('Every day at 12:00am', '0 0 * * *');
|
||||
$this->assertCronTranslateTo('Every Sunday at 12:00am', '0 0 * * 0');
|
||||
$this->assertCronTranslateTo('Every day on January at 12:00am', '0 0 * 1 *');
|
||||
$this->assertCronTranslateTo('Every Sunday on January at 12:00am', '0 0 * 1 0');
|
||||
$this->assertCronTranslateTo('The 1st of every month at 12:00am', '0 0 1 * *');
|
||||
$this->assertCronTranslateTo('The 1st of every month on Sundays at 12:00am', '0 0 1 * 0');
|
||||
$this->assertCronTranslateTo('Every year on January the 1st at 12:00am', '0 0 1 1 *');
|
||||
$this->assertCronTranslateTo('On Sundays on January the 1st at 12:00am', '0 0 1 1 0');
|
||||
|
||||
// More realistic examples.
|
||||
$this->assertCronTranslateTo('Every year on January the 1st at 12:00pm', '0 12 1 1 *');
|
||||
$this->assertCronTranslateTo('Every minute on Mondays at 3pm', '* 15 * * 1');
|
||||
$this->assertCronTranslateTo('Every minute on January the 3rd', '* * 3 1 *');
|
||||
$this->assertCronTranslateTo('Every minute on Mondays on April', '* * * 4 1');
|
||||
$this->assertCronTranslateTo('On Mondays on April the 22nd at 3:10pm', '10 15 22 4 1');
|
||||
|
||||
// Paparazzi examples.
|
||||
$this->assertCronTranslateTo('Every day at 10:00pm', '0 22 * * *');
|
||||
$this->assertCronTranslateTo('Every day at 9:00am', '0 9 * * *');
|
||||
$this->assertCronTranslateTo('Every Monday at 4:00pm', '0 16 * * 1');
|
||||
$this->assertCronTranslateTo('Every year on January the 1st at 12:00am', '0 0 1 1 *');
|
||||
$this->assertCronTranslateTo('The 1st of every month at 12:00am', '0 0 1 * *');
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function it_translate_expressions_with_multiple()
|
||||
{
|
||||
$this->assertCronTranslateTo('Every minute 2 hours a day', '* 8,18 * * *');
|
||||
$this->assertCronTranslateTo('Every minute 3 hours a day', '* 8,18,20 * * *');
|
||||
$this->assertCronTranslateTo('Every minute 20 hours a day', '* 1-20 * * *');
|
||||
$this->assertCronTranslateTo('Twice an hour', '0,30 * * * *');
|
||||
$this->assertCronTranslateTo('Twice an hour 5 hours a day', '0,30 1-5 * * *');
|
||||
$this->assertCronTranslateTo('5 times a day', '0 1-5 * * *');
|
||||
$this->assertCronTranslateTo('Every minute 5 hours a day', '* 1-5 * * *');
|
||||
$this->assertCronTranslateTo('5 days a month at 1:00am', '0 1 1-5 * *');
|
||||
$this->assertCronTranslateTo('5 days a month 2 months a year at 1:00am', '0 1 1-5 5,6 *');
|
||||
$this->assertCronTranslateTo('2 months a year on the 5th at 1:00am', '0 1 5 5,6 *');
|
||||
$this->assertCronTranslateTo('The 5th of every month 4 days a week at 1:00am', '0 1 5 * 1-4');
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function it_translate_expressions_with_increment()
|
||||
{
|
||||
$this->assertCronTranslateTo('Every 2 minutes', '*/2 * * * *');
|
||||
$this->assertCronTranslateTo('Every 2 minutes', '1/2 * * * *');
|
||||
$this->assertCronTranslateTo('Twice every 4 minutes', '1,3/4 * * * *');
|
||||
$this->assertCronTranslateTo('3 times every 5 minutes', '1-3/5 * * * *');
|
||||
$this->assertCronTranslateTo('Every 2 minutes at 2pm', '*/2 14 * * *');
|
||||
$this->assertCronTranslateTo('Once an hour every 2 days', '0 * */2 * *');
|
||||
$this->assertCronTranslateTo('Every minute every 2 days', '* * */2 * *');
|
||||
$this->assertCronTranslateTo('Once every 2 hours', '0 */2 * * *');
|
||||
$this->assertCronTranslateTo('Twice every 5 hours', '0 1,2/5 * * *');
|
||||
$this->assertCronTranslateTo('Every minute 2 hours out of 5', '* 1,2/5 * * *');
|
||||
$this->assertCronTranslateTo('Every day every 4 months at 12:00am', '0 0 * */4 *');
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function it_adds_junctions_to_certain_combinations_of_cron_types()
|
||||
{
|
||||
$this->assertCronTranslateTo('Every minute of every 2 hours', '* */2 * * *');
|
||||
$this->assertCronTranslateTo('Every minute of every 3 hours on the 2nd of every month', '* 1/3 2 * *');
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function it_converts_ranges_of_one_into_once_cron_types()
|
||||
{
|
||||
$this->assertCronTranslateTo('Every minute at 8am', '* 8-8 * * *');
|
||||
$this->assertCronTranslateTo('Every minute on January', '* * * 1-1 *');
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function it_handles_extended_cron_syntax()
|
||||
{
|
||||
$this->assertCronTranslateTo('Once an hour', '@hourly');
|
||||
$this->assertCronTranslateTo('Every day at 12:00am', '@daily');
|
||||
$this->assertCronTranslateTo('Every Sunday at 12:00am', '@weekly');
|
||||
$this->assertCronTranslateTo('The 1st of every month at 12:00am', '@monthly');
|
||||
$this->assertCronTranslateTo('Every year on January the 1st at 12:00am', '@yearly');
|
||||
$this->assertCronTranslateTo('Every year on January the 1st at 12:00am', '@annually');
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function it_returns_parsing_errors_when_something_goes_wrong()
|
||||
{
|
||||
$this->assertCronThrowsParsingError('I_AM_NOT_A_CRON_EXPRESSION');
|
||||
$this->assertCronThrowsParsingError('A * * * *');
|
||||
$this->assertCronThrowsParsingError('1,2-3 * * * *');
|
||||
$this->assertCronThrowsParsingError('1/2/3 * * * *');
|
||||
$this->assertCronThrowsParsingError('* * * 0 *');
|
||||
$this->assertCronThrowsParsingError('* * * 13 *');
|
||||
$this->assertCronThrowsParsingError('* * * * 8');
|
||||
}
|
||||
|
||||
/**
|
||||
* @skip
|
||||
* @doesNotPerformAssertions
|
||||
*/
|
||||
public function result_generator()
|
||||
{
|
||||
$this->generateCombinationsFromMatrix([
|
||||
['*', '0', '1,2', '*/2'],
|
||||
['*', '0', '1,2', '*/2'],
|
||||
['*', '1', '1,2', '*/2'],
|
||||
['*', '1', '1,2', '*/2'],
|
||||
['*', '0', '1,2', '*/2'],
|
||||
]);
|
||||
}
|
||||
}
|
||||
48
vendor/lorisleiva/cron-translator/tests/TestCase.php
vendored
Normal file
48
vendor/lorisleiva/cron-translator/tests/TestCase.php
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace Lorisleiva\CronTranslator\Tests;
|
||||
|
||||
use Lorisleiva\CronTranslator\CronTranslator;
|
||||
use PHPUnit\Framework\TestCase as BaseTestCase;
|
||||
use Lorisleiva\CronTranslator\CronParsingException;
|
||||
|
||||
class TestCase extends BaseTestCase
|
||||
{
|
||||
public function assertCronTranslateTo($expected, $actual)
|
||||
{
|
||||
$this->assertEquals($expected, CronTranslator::translate($actual));
|
||||
}
|
||||
|
||||
public function assertCronThrowsParsingError($cron)
|
||||
{
|
||||
try {
|
||||
CronTranslator::translate($cron);
|
||||
} catch (CronParsingException $expression) {
|
||||
return $this->addToAssertionCount(1);
|
||||
}
|
||||
|
||||
$this->fail("Expected CronParsingError exception for [$cron]");
|
||||
}
|
||||
|
||||
public function generateCombinationsFromMatrix($matrix)
|
||||
{
|
||||
function combinations($matrix, $acc = []) {
|
||||
if (empty($matrix)) {
|
||||
return [implode(' ', $acc)];
|
||||
}
|
||||
|
||||
$current = array_shift($matrix);
|
||||
$results = [];
|
||||
|
||||
foreach ($current as $value) {
|
||||
$results[] = combinations($matrix, array_merge($acc, [$value]));
|
||||
}
|
||||
|
||||
return array_merge(...$results);
|
||||
}
|
||||
|
||||
foreach (combinations($matrix) as $cron) {
|
||||
echo "\n" . $cron . "\t=> " . CronTranslator::translate($cron);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user