upgrade to laravel 8.x

This commit is contained in:
2021-05-30 08:20:41 +00:00
parent 41b78a0599
commit 3ad6ed8bfa
2333 changed files with 113904 additions and 59058 deletions

2
.env
View File

@@ -1,7 +1,7 @@
APP_NAME='W4RP Services' APP_NAME='W4RP Services'
APP_ENV=local APP_ENV=local
APP_KEY=base64:PBOxrGFJAtwj9SDF4F0DZ1J+6MjrJmRiPZJQwRdy3XQ= APP_KEY=base64:PBOxrGFJAtwj9SDF4F0DZ1J+6MjrJmRiPZJQwRdy3XQ=
APP_DEBUG=true APP_DEBUG=false
APP_URL=https://services.w4rp.space APP_URL=https://services.w4rp.space
LOG_CHANNEL=daily LOG_CHANNEL=daily

View File

@@ -4,6 +4,7 @@ namespace App\Providers;
use Illuminate\Support\ServiceProvider; use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Schema; use Illuminate\Support\Facades\Schema;
use Illuminate\Pagination\Paginator;
class AppServiceProvider extends ServiceProvider class AppServiceProvider extends ServiceProvider
{ {
@@ -15,6 +16,7 @@ class AppServiceProvider extends ServiceProvider
public function boot() public function boot()
{ {
Schema::defaultStringLength(191); Schema::defaultStringLength(191);
Paginator::useBootstrap();
} }
/** /**

View File

@@ -5,21 +5,21 @@
"license": "MIT", "license": "MIT",
"type": "project", "type": "project",
"require": { "require": {
"php": "^7.1.3", "php": "^7.4.0",
"ext-redis": "^5.3", "ext-redis": "^5.3",
"eveseat/eseye": "^2.3", "eveseat/eseye": "^2.3",
"fideloper/proxy": "^4.0", "fideloper/proxy": "^4.0",
"guzzlehttp/guzzle": "^6.3", "guzzlehttp/guzzle": "^7.0.1",
"khill/lavacharts": "^3.1.14", "khill/lavacharts": "^3.1.14",
"laravel/framework": "^7.0", "laravel/framework": "^8.0",
"laravel/helpers": "^1.4", "laravel/helpers": "^1.4",
"laravel/horizon": "^4.0", "laravel/horizon": "^5.0",
"laravel/socialite": "^5.1", "laravel/socialite": "^5.1",
"laravel/ui": "^2.0", "laravel/ui": "^3.0",
"laravelcollective/html": "^6.0", "laravelcollective/html": "^6.0",
"socialiteproviders/manager": "^4.0", "socialiteproviders/manager": "^4.0",
"spatie/laravel-rate-limited-job-middleware": "^1.5", "spatie/laravel-rate-limited-job-middleware": "^1.5",
"spatie/laravel-schedule-monitor": "2.0.1", "spatie/laravel-schedule-monitor": "2.3.0",
"twbs/bootstrap": "^4.5", "twbs/bootstrap": "^4.5",
"web-token/jwt-easy": "^2.2", "web-token/jwt-easy": "^2.2",
"web-token/jwt-signature-algorithm-ecdsa": "^2.2", "web-token/jwt-signature-algorithm-ecdsa": "^2.2",
@@ -31,8 +31,8 @@
"filp/whoops": "^2.0", "filp/whoops": "^2.0",
"fzaninotto/faker": "^1.4", "fzaninotto/faker": "^1.4",
"mockery/mockery": "^1.0", "mockery/mockery": "^1.0",
"phpunit/phpunit": "^8.5", "phpunit/phpunit": "^9.0",
"nunomaduro/collision": "^4.1" "nunomaduro/collision": "^5.0"
}, },
"autoload": { "autoload": {
"classmap": [ "classmap": [

1679
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,50 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateScheduleMonitorTables extends Migration
{
public function up()
{
Schema::create('monitored_scheduled_tasks', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->string('type')->nullable();
$table->string('cron_expression');
$table->string('timezone')->nullable();
$table->string('ping_url')->nullable();
$table->dateTime('last_started_at')->nullable();
$table->dateTime('last_finished_at')->nullable();
$table->dateTime('last_failed_at')->nullable();
$table->dateTime('last_skipped_at')->nullable();
$table->dateTime('registered_on_oh_dear_at')->nullable();
$table->dateTime('last_pinged_at')->nullable();
$table->integer('grace_time_in_minutes');
$table->timestamps();
});
Schema::create('monitored_scheduled_task_log_items', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('monitored_scheduled_task_id');
$table
->foreign('monitored_scheduled_task_id', 'fk_scheduled_task_id')
->references('id')
->on('monitored_scheduled_tasks')
->cascadeOnDelete();
$table->string('type');
$table->json('meta')->nullable();
$table->timestamps();
});
}
}

View File

@@ -0,0 +1,50 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateScheduleMonitorTables extends Migration
{
public function up()
{
Schema::create('monitored_scheduled_tasks', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->string('type')->nullable();
$table->string('cron_expression');
$table->string('timezone')->nullable();
$table->string('ping_url')->nullable();
$table->dateTime('last_started_at')->nullable();
$table->dateTime('last_finished_at')->nullable();
$table->dateTime('last_failed_at')->nullable();
$table->dateTime('last_skipped_at')->nullable();
$table->dateTime('registered_on_oh_dear_at')->nullable();
$table->dateTime('last_pinged_at')->nullable();
$table->integer('grace_time_in_minutes');
$table->timestamps();
});
Schema::create('monitored_scheduled_task_log_items', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('monitored_scheduled_task_id');
$table
->foreign('monitored_scheduled_task_id', 'fk_scheduled_task_id')
->references('id')
->on('monitored_scheduled_tasks')
->cascadeOnDelete();
$table->string('type');
$table->json('meta')->nullable();
$table->timestamps();
});
}
}

View File

@@ -0,0 +1,50 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateScheduleMonitorTables extends Migration
{
public function up()
{
Schema::create('monitored_scheduled_tasks', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->string('type')->nullable();
$table->string('cron_expression');
$table->string('timezone')->nullable();
$table->string('ping_url')->nullable();
$table->dateTime('last_started_at')->nullable();
$table->dateTime('last_finished_at')->nullable();
$table->dateTime('last_failed_at')->nullable();
$table->dateTime('last_skipped_at')->nullable();
$table->dateTime('registered_on_oh_dear_at')->nullable();
$table->dateTime('last_pinged_at')->nullable();
$table->integer('grace_time_in_minutes');
$table->timestamps();
});
Schema::create('monitored_scheduled_task_log_items', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('monitored_scheduled_task_id');
$table
->foreign('monitored_scheduled_task_id', 'fk_scheduled_task_id')
->references('id')
->on('monitored_scheduled_tasks')
->cascadeOnDelete();
$table->string('type');
$table->json('meta')->nullable();
$table->timestamps();
});
}
}

View File

@@ -0,0 +1,50 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateScheduleMonitorTables extends Migration
{
public function up()
{
Schema::create('monitored_scheduled_tasks', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->string('type')->nullable();
$table->string('cron_expression');
$table->string('timezone')->nullable();
$table->string('ping_url')->nullable();
$table->dateTime('last_started_at')->nullable();
$table->dateTime('last_finished_at')->nullable();
$table->dateTime('last_failed_at')->nullable();
$table->dateTime('last_skipped_at')->nullable();
$table->dateTime('registered_on_oh_dear_at')->nullable();
$table->dateTime('last_pinged_at')->nullable();
$table->integer('grace_time_in_minutes');
$table->timestamps();
});
Schema::create('monitored_scheduled_task_log_items', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('monitored_scheduled_task_id');
$table
->foreign('monitored_scheduled_task_id', 'fk_scheduled_task_id')
->references('id')
->on('monitored_scheduled_tasks')
->cascadeOnDelete();
$table->string('type');
$table->json('meta')->nullable();
$table->timestamps();
});
}
}

1810
public/alliance_moons.txt Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -8,6 +8,9 @@
*/ */
define('LARAVEL_START', microtime(true)); define('LARAVEL_START', microtime(true));
if(file_exists(__DIR__.'/../storage/framework/maintenance.php')) {
require __DIR__.'/../storage/framework/maintenance.php';
}
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------

1
vendor/bin/php-parse vendored Symbolic link
View File

@@ -0,0 +1 @@
../nikic/php-parser/bin/php-parse

View File

@@ -1,10 +0,0 @@
# Basic docker based environment
# Necessary to trick dokku into building the documentation
# using dockerfile instead of herokuish
FROM php:7.3
WORKDIR /code
VOLUME ["/code"]
CMD [ '/bin/bash' ]

View File

@@ -1,150 +0,0 @@
# CakePHP Chronos
[![Build Status](https://img.shields.io/travis/com/cakephp/chronos/master?style=flat-square)](https://travis-ci.com/cakephp/chronos)
[![Latest Stable Version](https://img.shields.io/github/v/release/cakephp/chronos?sort=semver&style=flat-square)](https://packagist.org/packages/cakephp/chronos)
[![Total Downloads](https://img.shields.io/packagist/dt/cakephp/chronos?style=flat-square)](https://packagist.org/packages/cakephp/chronos/stats)
[![Code Coverage](https://img.shields.io/coveralls/cakephp/chronos/master.svg?style=flat-square)](https://coveralls.io/r/cakephp/chronos?branch=master)
[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE)
Chronos aims to be a drop-in replacement for `nesbot/carbon`. It focuses on providing
immutable date/datetime objects. Immutable objects help ensure that datetime objects
aren't accidentally modified keeping data more predictable.
# Installation
Installing with composer:
```
$ composer require cakephp/chronos
```
You can then use Chronos:
```php
<?php
require 'vendor/autoload.php';
use Cake\Chronos\Chronos;
printf("Now: %s", Chronos::now());
```
# Differences with nesbot/carbon
The biggest and main difference is that `Chronos` extends `DateTimeImmutable` instead of `DateTime`.
Immutability for date values has proven to be a great way of avoiding bugs and reduce the amount of code,
since developers don't have to manually copy the instance every time they need a change.
Another important feature it offers is the `Date` class, which is used for representing dates without time (calendar dates).
Any time method called on this type of object is basically a no-op.
There are other implementation changes, but one that users might not notice is ``Chronos`` considers Monday as
the start of the week instead of Sunday. This follows the ISO-8601 and current versions of PHP 5.6 and PHP 7.
A minor but still noticeable difference is that `Chronos` has no external dependencies, it is completely standalone.
Finally, Chronos is faster than Carbon as it has been optimized for the creation of hundreds of instances with minimal
overhead.
# Migrating from Carbon
First add `cakephp/chronos` to your `composer.json`:
```shell
php composer.phar require cakephp/chronos
```
By default Chronos includes a compatibility script that creates aliases for the
relevant Carbon classes. This will let most applications upgrade with very
little effort. If you'd like to permanently update your code, you will
need to update imports and typehints. Assuming `src` contains the files you
want to migrate, we could use the following to update files:
```
# Replace imports
find ./src -type f -name '*.php' -exec sed -i '' 's/use Carbon\\CarbonInterval/use Cake\\Chronos\\ChronosInterval/g' {} \;
find ./src -type f -name '*.php' -exec sed -i '' 's/use Carbon\\Carbon/use Cake\\Chronos\\Chronos/g' {} \;
# Replace typehints and extensions
find ./src -type f -name '*.php' -exec sed -i '' 's/CarbonInterval/ChronosInterval/g' {} \;
find ./src -type f -name '*.php' -exec sed -i '' 's/Carbon/Chronos/g' {} \;
```
At this point your code should mostly work as it did before. The biggest
difference is that Chronos instances are immutable.
## Immutable Object Changes
Immutable objects have a number of advantages:
1. Using immutable objects is always free of side-effects.
2. Dates and times don't accidentally change underneath other parts of your code.
With those benefits in mind, there are a few things you need to keep in mind
when modifying immutable objects:
```php
// This will lose modifications
$date = new Chronos('2015-10-21 16:29:00');
$date->modify('+2 hours');
// This will keep modifications
$date = new Chronos('2015-10-21 16:29:00');
$date = $date->modify('+2 hours');
```
## Getting Mutable Objects
In the case that you need a mutable instance you can get one:
```php
$time = new Chronos('2015-10-21 16:29:00');
$mutable = $time->toMutable();
$date = new Date('2015-10-21');
$mutable = $date->toMutable();
```
## Converting Mutable Objects into Immutable ones.
If you have a mutable object and want an immutable variant you can do the following:
```php
$time = new MutableDateTime('2015-10-21 16:29:00');
$fixed = $time->toImmutable();
$date = new MutableDate('2015-10-21');
$fixed = $date->toImmutable();
```
# Calendar Dates
PHP only offers datetime objects as part of the native extensions. Chronos adds
a number of conveniences to the traditional DateTime object and introduces
a `Date` object. `Date` instances offer compatibility with the
`ChronosInterface`, but have their time frozen to `00:00:00` and the timezone
set to the server default timezone. This makes them ideal when working with
calendar dates as the time components will always match.
```php
use Cake\Chronos\Date;
$today = new Date();
echo $today;
// Outputs '2015-10-21'
echo $today->modify('+3 hours');
// Outputs '2015-10-21'
```
Like instances of `Chronos`, `Date` objects are also *immutable*. The
`MutableDate` class provides a mutable variant of `Date`.
# Documentation
A more descriptive documentation can be found at [book.cakephp.org/chronos/2/en/](https://book.cakephp.org/chronos/2/en/).
# API Documentation
API documentation can be found on [api.cakephp.org/chronos](https://api.cakephp.org/chronos).

View File

@@ -1,63 +0,0 @@
{
"name": "cakephp/chronos",
"type": "library",
"description": "A simple API extension for DateTime.",
"keywords": [
"date",
"time",
"DateTime"
],
"homepage": "http://cakephp.org",
"license": "MIT",
"authors": [
{
"name": "Brian Nesbitt",
"email": "brian@nesbot.com",
"homepage": "http://nesbot.com"
},
{
"name": "The CakePHP Team",
"homepage": "http://cakephp.org"
}
],
"support": {
"issues": "https://github.com/cakephp/chronos/issues",
"irc": "irc://irc.freenode.org/cakephp",
"source": "https://github.com/cakephp/chronos"
},
"require": {
"php": ">=7.2"
},
"require-dev": {
"phpunit/phpunit": "^8.0 || ^9.0",
"cakephp/cakephp-codesniffer": "^4.0"
},
"autoload": {
"psr-4": {
"Cake\\Chronos\\": "src/"
},
"files": [
"src/carbon_compat.php"
]
},
"autoload-dev": {
"psr-4": {
"Cake\\Chronos\\Test\\": "tests/"
}
},
"scripts": {
"check": [
"@test",
"@cs-check",
"@phpstan"
],
"cs-check": "phpcs --colors --parallel=16 -p src/ tests/",
"cs-fix": "phpcbf --colors --parallel=16 -p src/ tests/",
"phpstan": "phpstan.phar analyse",
"stan": [
"@phpstan"
],
"stan-setup": "cp composer.json composer.backup && composer require --dev phpstan/phpstan:^0.12.54 && mv composer.backup composer.json",
"test": "phpunit"
}
}

View File

@@ -1,20 +0,0 @@
# Generate the HTML output.
FROM markstory/cakephp-docs-builder as builder
RUN pip install git+https://github.com/sphinx-contrib/video.git@master
COPY docs /data/docs
# build docs with sphinx
RUN cd /data/docs-builder && \
make website LANGS="en fr ja pt" SOURCE=/data/docs DEST=/data/website
# Build a small nginx container with just the static site in it.
FROM nginx:1.15-alpine
COPY --from=builder /data/website /data/website
COPY --from=builder /data/docs-builder/nginx.conf /etc/nginx/conf.d/default.conf
# Move docs into place.
RUN cp -R /data/website/html/* /usr/share/nginx/html \
&& rm -rf /data/website

View File

@@ -1,49 +0,0 @@
# Global configuration information used across all the
# translations of documentation.
#
# Import the base theme configuration
from cakephpsphinx.config.all import *
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The full version, including alpha/beta/rc tags.
release = '2.x'
# The search index version.
search_version = 'chronos-2'
# The marketing display name for the book.
version_name = ''
# Project name shown in the black header bar
project = 'Chronos'
# Other versions that display in the version picker menu.
version_list = [
{'name': '1.x', 'number': '/chronos/1', 'title': '1.x'},
{'name': '2.x', 'number': '/chronos/2', 'title': '2.x', 'current': True},
]
# Languages available.
languages = ['en', 'fr', 'ja', 'pt']
# The GitHub branch name for this version of the docs
# for edit links to point at.
branch = '2.x'
# Current version being built
version = '2.x'
# Language in use for this directory.
language = 'en'
show_root_link = True
repository = 'cakephp/chronos'
source_path = 'docs/'
hide_page_contents = ('search', '404', 'contents')

View File

@@ -1,9 +0,0 @@
import sys, os
# Append the top level directory of the docs, so we can import from the config dir.
sys.path.insert(0, os.path.abspath('..'))
# Pull in all the configuration options defined in the global config file..
from config.all import *
language = 'en'

View File

@@ -1,7 +0,0 @@
.. toctree::
:maxdepth: 2
:caption: CakePHP Chronos
/index
API <https://api.cakephp.org/chronos>

View File

@@ -1,321 +0,0 @@
Chronos
#######
Chronos provides a zero-dependency collection of extensions to the ``DateTime``
object. In addition to convenience methods, Chronos provides:
* ``Date`` objects for representing calendar dates.
* Immutable date and datetime objects.
* A pluggable translation system. Only English translations are included in the
library. However, ``cakephp/i18n`` can be used for full language support.
Installation
------------
To install Chronos, you should use ``composer``. From your
application's ROOT directory (where composer.json file is located) run the
following::
php composer.phar require "cakephp/chronos:^2.0"
Overview
--------
Chronos provides a number of extensions to the DateTime objects provided by PHP.
Chronos provides 5 classes that cover mutable and immutable date/time variants
and extensions to ``DateInterval``.
* ``Cake\Chronos\Chronos`` is an immutable *date and time* object.
* ``Cake\Chronos\Date`` is a immutable *date* object.
* ``Cake\Chronos\MutableDateTime`` is a mutable *date and time* object.
* ``Cake\Chronos\MutableDate`` is a mutable *date* object.
* ``Cake\Chronos\ChronosInterval`` is an extension to the ``DateInterval``
object.
Lastly, if you want to typehint against Chronos-provided date/time objects you
should use ``Cake\Chronos\ChronosInterface``. All of the date and time objects
implement this interface.
Creating Instances
------------------
There are many ways to get an instance of Chronos or Date. There are a number of
factory methods that work with different argument sets::
use Cake\Chronos\Chronos;
$now = Chronos::now();
$today = Chronos::today();
$yesterday = Chronos::yesterday();
$tomorrow = Chronos::tomorrow();
// Parse relative expressions
$date = Chronos::parse('+2 days, +3 hours');
// Date and time integer values.
$date = Chronos::create(2015, 12, 25, 4, 32, 58);
// Date or time integer values.
$date = Chronos::createFromDate(2015, 12, 25);
$date = Chronos::createFromTime(11, 45, 10);
// Parse formatted values.
$date = Chronos::createFromFormat('m/d/Y', '06/15/2015');
Working with Immutable Objects
------------------------------
If you've used PHP's ``DateTime`` objects, you're comfortable with *mutable*
objects. Chronos offers mutable objects, but it also provides *immutable*
objects. Immutable objects create copies of objects each time an object is
modified. Because modifier methods around datetimes are not always transparent,
data can be modified accidentally or without the developer knowing.
Immutable objects prevent accidental changes to
data, and make code free of order-based dependency issues. Immutability
does mean that you will need to remember to replace variables when using
modifiers::
// This code doesn't work with immutable objects
$time->addDay(1);
doSomething($time);
return $time;
// This works like you'd expect
$time = $time->addDay(1);
$time = doSomething($time);
return $time;
By capturing the return value of each modification your code will work as
expected. If you ever have an immutable object, and want to create a mutable
one, you can use ``toMutable()``::
$inplace = $time->toMutable();
Date Objects
------------
PHP only provides a single DateTime object. Representing calendar dates can be
a bit awkward with this class as it includes timezones, and time components that
don't really belong in the concept of a 'day'. Chronos provides a ``Date``
object that allows you to represent dates. The time and timezone for these
objects is always fixed to ``00:00:00 UTC`` and all formatting/difference
methods operate at the day resolution::
use Cake\Chronos\Date;
$today = Date::today();
// Changes to the time/timezone are ignored.
$today->modify('+1 hours');
// Outputs '2015-12-20'
echo $today;
Although ``Date`` uses a fixed time zone internally, you can specify which
time zone to use for current time such as ``now()`` or ``today()``::
use Cake\Chronos\Date:
// Takes the current date from Asia/Tokyo time zone
$today = Date::today('Asia/Tokyo');
Modifier Methods
----------------
Chronos objects provide modifier methods that let you modify the value in
a granular way::
// Set components of the datetime value.
$halloween = Chronos::create()
->year(2015)
->month(10)
->day(31)
->hour(20)
->minute(30);
You can also modify parts of the datetime relatively::
$future = Chronos::create()
->addYear(1)
->subMonth(2)
->addDays(15)
->addHours(20)
->subMinutes(2);
It is also possible to make big jumps to defined points in time::
$time = Chronos::create();
$time->startOfDay();
$time->endOfDay();
$time->startOfMonth();
$time->endOfMonth();
$time->startOfYear();
$time->endOfYear();
$time->startOfWeek();
$time->endOfWeek();
Or jump to specific days of the week::
$time->next(ChronosInterface::TUESDAY);
$time->previous(ChronosInterface::MONDAY);
When modifying dates/times across :abbr:`DST (Daylight Savings Time)` transitions
your operations may gain/lose an additional hours resulting in hour values that
don't add up. You can avoid these issues by first changing your timezone to
``UTC``, modifying the time::
// Additional hour gained.
$time = new Chronos('2014-03-30 00:00:00', 'Europe/London');
debug($time->modify('+24 hours')); // 2014-03-31 01:00:00
// First switch to UTC, and modify
$time = $time->setTimezone('UTC')
->modify('+24 hours');
Once you are done modifying the time you can add the original timezone to get
the localized time.
Comparison Methods
------------------
Once you have 2 instances of Chronos date/time objects you can compare them in
a variety of ways::
// Full suite of comparators exist
// ne, gt, lt, lte.
$first->eq($second);
$first->gte($second);
// See if the current object is between two others.
$now->between($start, $end);
// Find which argument is closest or farthest.
$now->closest($june, $november);
$now->farthest($june, $november);
You can also inquire about where a given value falls on the calendar::
$now->isToday();
$now->isYesterday();
$now->isFuture();
$now->isPast();
// Check the day of the week
$now->isWeekend();
// All other weekday methods exist too.
$now->isMonday();
You can also find out if a value was within a relative time period::
$time->wasWithinLast('3 days');
$time->isWithinNext('3 hours');
Generating Differences
----------------------
In addition to comparing datetimes, calculating differences or deltas between
two values is a common task::
// Get a DateInterval representing the difference
$first->diff($second);
// Get difference as a count of specific units.
$first->diffInHours($second);
$first->diffInDays($second);
$first->diffInWeeks($second);
$first->diffInYears($second);
You can generate human readable differences suitable for use in a feed or
timeline::
// Difference from now.
echo $date->diffForHumans();
// Difference from another point in time.
echo $date->diffForHumans($other); // 1 hour ago;
Formatting Strings
------------------
Chronos provides a number of methods for displaying our outputting datetime
objects::
// Uses the format controlled by setToStringFormat()
echo $date;
// Different standard formats
echo $time->toAtomString(); // 1975-12-25T14:15:16-05:00
echo $time->toCookieString(); // Thursday, 25-Dec-1975 14:15:16 EST
echo $time->toIso8601String(); // 1975-12-25T14:15:16-05:00
echo $time->toRfc822String(); // Thu, 25 Dec 75 14:15:16 -0500
echo $time->toRfc850String(); // Thursday, 25-Dec-75 14:15:16 EST
echo $time->toRfc1036String(); // Thu, 25 Dec 75 14:15:16 -0500
echo $time->toRfc1123String(); // Thu, 25 Dec 1975 14:15:16 -0500
echo $time->toRfc2822String(); // Thu, 25 Dec 1975 14:15:16 -0500
echo $time->toRfc3339String(); // 1975-12-25T14:15:16-05:00
echo $time->toRssString(); // Thu, 25 Dec 1975 14:15:16 -0500
echo $time->toW3cString(); // 1975-12-25T14:15:16-05:00
// Get the quarter/week
echo $time->toQuarter(); // 4
echo $time->toWeek(); // 52
// Generic formatting
echo $time->toTimeString(); // 14:15:16
echo $time->toDateString(); // 1975-12-25
echo $time->toDateTimeString(); // 1975-12-25 14:15:16
echo $time->toFormattedDateString(); // Dec 25, 1975
echo $time->toDayDateTimeString(); // Thu, Dec 25, 1975 2:15 PM
Extracting Date Components
--------------------------
Getting parts of a date object can be done by directly accessing properties::
$time = new Chronos('2015-12-31 23:59:58.123');
$time->year; // 2015
$time->month; // 12
$time->day; // 31
$time->hour // 23
$time->minute // 59
$time->second // 58
$time->micro // 123
Other properties that can be accessed are:
- timezone
- timezoneName
- dayOfWeek
- dayOfMonth
- dayOfYear
- daysInMonth
- timestamp
- quarter
Testing Aids
------------
When writing unit tests, it is helpful to fixate the current time. Chronos lets
you fix the current time for each class. As part of your test suite's bootstrap
process you can include the following::
Chronos::setTestNow(Chronos::now());
MutableDateTime::setTestNow(MutableDateTime::now());
Date::setTestNow(Date::now());
MutableDate::setTestNow(MutableDate::now());
This will fix the current time of all objects to be the point at which the test
suite started.
For example, if you fixate the ``Chronos`` to some moment in the past, any new
instance of ``Chronos`` created with ``now`` or a relative time string, will be
returned relative to the fixated time::
Chronos::setTestNow(new Chronos('1975-12-25 00:00:00'));
$time = new Chronos(); // 1975-12-25 00:00:00
$time = new Chronos('1 hour ago'); // 1975-12-24 23:00:00
To reset the fixation, simply call ``setTestNow()`` again with no parameter or
with ``null`` as a parameter.

View File

@@ -1,9 +0,0 @@
import sys, os
# Append the top level directory of the docs, so we can import from the config dir.
sys.path.insert(0, os.path.abspath('..'))
# Pull in all the configuration options defined in the global config file..
from config.all import *
language = 'fr'

View File

@@ -1,7 +0,0 @@
.. toctree::
:maxdepth: 2
:caption: CakePHP Chronos
/index
API <https://api.cakephp.org/chronos>

View File

@@ -1,306 +0,0 @@
Chronos
#######
Chronos fournit une collection d'extensions sans aucune dépendance pour l'objet
``DateTime``. En plus de méthodes pratiques, Chronos fournit:
* Des objets ``Date`` pour représenter les dates du calendrier.
* Des objets immutables pour les dates et les datetimes.
* Un système de traduction intégrable. Seules les traductions anglaises sont
inclues dans la librairie. Cependant, ``cakephp/i18n`` peut être utilisé
pour un support complet d'autres langues.
Installation
------------
Pour installer Chronos, vous devez utiliser ``composer``. A partir du répertoire
ROOT de votre application (où le fichier composer.json se trouve) exécutez ce
qui suit::
php composer.phar require cakephp/chronos "@stable"
Vue d'Ensemble
--------------
Chronos fournit un certain nombre d'extensions pour les objets DateTime fournis
par PHP. Chronos fournit 5 classes qui gèrent les variantes mutables et
immutables de date/time et les extensions de ``DateInterval``.
* ``Cake\Chronos\Chronos`` est un objet de *date et time* immutable.
* ``Cake\Chronos\Date`` est un objet de *date* immutable.
* ``Cake\Chronos\MutableDateTime`` est un objet de *date et time* mutable.
* ``Cake\Chronos\MutableDate`` est un objet de *date* mutable.
* ``Cake\Chronos\ChronosInterval`` est une extension pour l'objet
``DateInterval``.
Enfin si vous voulez typer selon les objets date/time fournis par Chronos,
vous devez utiliser ``Cake\Chronos\ChronosInterface``. Tous les objets date et
time implémentent cette interface.
Créer des Instances
-------------------
Il y a plusieurs façons d'obtenir une instance de Chronos ou de Date. Il y a
un certain nombre de méthodes factory qui fonctionnent avec des ensembles
ayant des arguments différents::
use Cake\Chronos\Chronos;
$now = Chronos::now();
$today = Chronos::today();
$yesterday = Chronos::yesterday();
$tomorrow = Chronos::tomorrow();
// Parse les expressions relatives
$date = Chronos::parse('+2 days, +3 hours');
// Les valeurs d'entier de Date et time.
$date = Chronos::create(2015, 12, 25, 4, 32, 58);
// Les valeurs d'entier pour Date ou time.
$date = Chronos::createFromDate(2015, 12, 25);
$date = Chronos::createFromTime(11, 45, 10);
// Parse les valeurs formatées.
$date = Chronos::createFromFormat('m/d/Y', '06/15/2015');
Travailler avec les Objets Immutables
-------------------------------------
Si vous avez utilisé les objets ``DateTime`` de PHP, vous êtes à l'aise avec
les objets *mutable*. Chronos offre des objets mutables, mais elle fournit
également des objets *immutables*. Les objets Immutables créent des copies des
objets à chaque fois qu'un objet est modifié. Puisque les méthodes de
modification autour des datetimes ne sont pas toujours transparentes, les
données peuvent être modifiées accidentellement ou sans que le développeur ne
le sache. Les objets immutables évitent les changements accidentels des
données et permettent de s'affranchir de tout problème lié à l'ordre d'appel
des fonctions ou des dépendances. L'immutabilité signifie que vous devez vous
souvenir de remplacer les variables quand vous utilisez les modificateurs::
// Ce code ne fonctionne pas avec les objets immutables
$time->addDay(1);
doSomething($time);
return $time;
// Ceci fonctionne comme vous le souhaitez
$time = $time->addDay(1);
$time = doSomething($time);
return $time;
En capturant la valeur de retour pour chaque modification, votre code
fonctionnera comme souhaité. Si vous avez déjà créé un objet immutable, et que
vous souhaitez un objet mutable, vous pouvez utiliser ``toMutable()``::
$inplace = $time->toMutable();
Objets Date
-----------
PHP fournit seulement un unique objet DateTime. Représenter les dates de
calendrier peut être un peu gênant avec cette classe puisqu'elle inclut les
timezones, et les composants de time qui n'appartiennent pas vraiment
dans le concept d'un 'jour'. Chronos fournit un objet ``Date`` qui vous permet
de représenter les dates. Les time et timezone pour ces objets sont toujours
fixés à ``00:00:00 UTC`` et toutes les méthodes de formatage/différence
fonctionnent au niveau du jour::
use Cake\Chronos\Date;
$today = Date::today();
// Changements selon le time/timezone sont ignorés.
$today->modify('+1 hours');
// Affiche '2015-12-20'
echo $today;
Méthodes de Modification
------------------------
Les objets Chronos fournissent des méthodes de modification qui vous laissent
modifier la valeur d'une façon assez précise::
// Définit les composants de la valeur du datetime.
$halloween = Chronos::create()
->year(2015)
->month(10)
->day(31)
->hour(20)
->minute(30);
Vous pouvez aussi modifier les parties de la date de façon relative::
$future = Chronos::create()
->addYear(1)
->subMonth(2)
->addDays(15)
->addHours(20)
->subMinutes(2);
Il est également possible de faire des sauts vers des points définis dans le
temps::
$time = Chronos::create();
$time->startOfDay();
$time->endOfDay();
$time->startOfMonth();
$time->endOfMonth();
$time->startOfYear();
$time->endOfYear();
$time->startOfWeek();
$time->endOfWeek();
Ou de sauter à un jour spécifique de la semaine::
$time->next(ChronosInterface::TUESDAY);
$time->previous(ChronosInterface::MONDAY);
Méthodes de Comparaison
-----------------------
Une fois que vous avez 2 instances d'objets date/time de Chronos, vous pouvez
les comparer de plusieurs façons::
// Suite complète de comparateurs existante
// ne, gt, lt, lte.
$first->eq($second);
$first->gte($second);
// Regardez si l'objet courant est entre deux autres.
$now->between($start, $end);
// Trouver l'argument le plus proche ou le plus éloigné.
$now->closest($june, $november);
$now->farthest($june, $november);
Vous pouvez aussi vous renseigner sur le moment où une valeur donnée tombe dans
le calendrier::
$now->isToday();
$now->isYesterday();
$now->isFuture();
$now->isPast();
// Vérifie le jour de la semaine
$now->isWeekend();
// Toutes les autres méthodes des jours de la semaine existent aussi.
$now->isMonday();
Vous pouvez aussi trouver si une valeur était dans une période de temps relative::
$time->wasWithinLast('3 days');
$time->isWithinNext('3 hours');
Générer des Différences
-----------------------
En plus de comparer les datetimes, calculer les différences ou les deltas entre
des valeurs est une tâche courante::
// Récupère un DateInterval représentant la différence
$first->diff($second);
// Récupère la différence en tant que nombre d'unités spécifiques.
$first->diffInHours($second);
$first->diffInDays($second);
$first->diffInWeeks($second);
$first->diffInYears($second);
Vous pouvez générer des différences lisibles qui peuvent vous servir pour
l'utilisation d'un feed ou d'une timeline::
// Différence à partir de maintenant.
echo $date->diffForHumans();
// Différence à partir d'un autre point du temps.
echo $date->diffForHumans($other); // 1 hour ago;
Formater les Chaînes
--------------------
Chronos fournit un certain nombre de méthodes pour afficher nos sorties d'objets
datetime::
// Utilise le format contrôlé par setToStringFormat()
echo $date;
// Différents formats standards
echo $time->toAtomString(); // 1975-12-25T14:15:16-05:00
echo $time->toCookieString(); // Thursday, 25-Dec-1975 14:15:16 EST
echo $time->toIso8601String(); // 1975-12-25T14:15:16-05:00
echo $time->toRfc822String(); // Thu, 25 Dec 75 14:15:16 -0500
echo $time->toRfc850String(); // Thursday, 25-Dec-75 14:15:16 EST
echo $time->toRfc1036String(); // Thu, 25 Dec 75 14:15:16 -0500
echo $time->toRfc1123String(); // Thu, 25 Dec 1975 14:15:16 -0500
echo $time->toRfc2822String(); // Thu, 25 Dec 1975 14:15:16 -0500
echo $time->toRfc3339String(); // 1975-12-25T14:15:16-05:00
echo $time->toRssString(); // Thu, 25 Dec 1975 14:15:16 -0500
echo $time->toW3cString(); // 1975-12-25T14:15:16-05:00
// Récupère le trimestre
echo $time->toQuarter(); // 4;
// Récupère la semaine
echo $time->toWeek(); // 52;
// Formatage générique
echo $time->toTimeString(); // 14:15:16
echo $time->toDateString(); // 1975-12-25
echo $time->toDateTimeString(); // 1975-12-25 14:15:16
echo $time->toFormattedDateString(); // Dec 25, 1975
echo $time->toDayDateTimeString(); // Thu, Dec 25, 1975 2:15 PM
Extraire des Fragments de Date
------------------------------
Il est possible de récupérer des parties d'un objet date en accédant directement
à ses propriétés::
$time = new Chronos('2015-12-31 23:59:58');
$time->year; // 2015
$time->month; // 12
$time->day; // 31
$time->hour // 23
$time->minute // 59
$time->second // 58
Les autres propriétés accessibles sont:
- timezone
- timezoneName
- micro
- dayOfWeek
- dayOfMonth
- dayOfYear
- daysInMonth
- timestamp
- quarter
Aides aux Tests
---------------
Quand vous écrivez des tests unitaires, il peut être utile de fixer le *time*
courant. Chronos vous permet de fixer le time courant pour chaque classe.
Pour l'intégrer dans votre processus de démarrage (bootstrap) de suite de tests,
vous pouvez inclure ce qui suit::
Chronos::setTestNow(Chronos::now());
MutableDateTime::setTestNow(MutableDateTime::now());
Date::setTestNow(Date::now());
MutableDate::setTestNow(MutableDate::now());
Ceci va fixer le time courant de tous les objets selon le moment où la suite de
tests a démarré.
Par exemple, si vous fixez le ``Chronos`` à un moment du passé, chaque nouvelle
instance de ``Chronos`` créée avec ``now`` ou une chaine de temps relative, sera
retournée relativement à la date fixée::
Chronos::setTestNow(new Chronos('1975-12-25 00:00:00'));
$time = new Chronos(); // 1975-12-25 00:00:00
$time = new Chronos('1 hour ago'); // 1975-12-24 23:00:00
Pour réinitialiser la "fixation" du temps, appelez simplement ``setTestNow()``
sans paramètre ou avec ``null`` comme paramètre.

View File

@@ -1,9 +0,0 @@
import sys, os
# Append the top level directory of the docs, so we can import from the config dir.
sys.path.insert(0, os.path.abspath('..'))
# Pull in all the configuration options defined in the global config file..
from config.all import *
language = 'ja'

View File

@@ -1,7 +0,0 @@
.. toctree::
:maxdepth: 2
:caption: CakePHP Chronos
/index
API <https://api.cakephp.org/chronos>

View File

@@ -1,304 +0,0 @@
Chronos
#######
Chronos (クロノス) は、 ``DateTime`` オブジェクトへの拡張の依存関係の無いコレクションを提供します。
便利なメソッドに加えて、Chronos は以下を提供します。
* カレンダー日付のための ``Date`` オブジェクト
* イミュータブルな日付と日時オブジェクト
* プラグインのような翻訳システム。ライブラリーは英語のみの翻訳を含んでいます。
しかし、全ての言語サポートのために、 ``cakephp/i18n`` を使うことができます。
インストール
------------
Chronos をインストールするためには、 ``composer`` を利用することができます。
アプリケーションの ROOT ディレクトリーcomposer.json ファイルのある場所)
で以下のように実行します。 ::
php composer.phar require cakephp/chronos "@stable"
概要
----
Chronos は PHP が提供する DateTime オブジェクトのいくつかの拡張を提供します。
Chronos は ``DateInterval`` の拡張機能および、ミュータブル(変更可能)と
イミュータブル(変更不可)な 日付/時刻 の派生系をカバーする5つのクラスを提供します。
* ``Cake\Chronos\Chronos`` はイミュータブルな *日付と時刻* オブジェクト。
* ``Cake\Chronos\Date`` はイミュータブルな *日付* オブジェクト。
* ``Cake\Chronos\MutableDateTime`` はミュータブルな *日付と時刻* オブジェクト。
* ``Cake\Chronos\MutableDate`` はミュータブルな *日付* オブジェクト。
* ``Cake\Chronos\ChronosInterval````DateInterval`` の拡張機能。
最後に、もしあなたが Chronos が提供する 日付/時刻 のオブジェクトに対して型宣言を行ないたい場合、
``Cake\Chronos\ChronosInterface`` を使用することができます。
全ての日付と時間のオブジェクトはこのインターフェイスを実装しています。
インスタンスの作成
------------------
Chronos または Date のインスタンスを取得するためには、多くの方法があります。
異なる引数セットで動作する多くのファクトリーメソッドがあります。 ::
use Cake\Chronos\Chronos;
$now = Chronos::now();
$today = Chronos::today();
$yesterday = Chronos::yesterday();
$tomorrow = Chronos::tomorrow();
// 相対式のパース
$date = Chronos::parse('+2 days, +3 hours');
// 日付と時間の整数値
$date = Chronos::create(2015, 12, 25, 4, 32, 58);
// 日付または時間の整数値
$date = Chronos::createFromDate(2015, 12, 25);
$date = Chronos::createFromTime(11, 45, 10);
// 整形した値にパース
$date = Chronos::createFromFormat('m/d/Y', '06/15/2015');
イミュータブルオブジェクトの動作
--------------------------------
もしあなたが、PHP の ``DateTime`` オブジェクトを使用したことがあるなら、
*ミュータブル* オブジェクトは簡単に使用できます。
Chronos はミュータブルオブジェクトを提供しますが、これは *イミュータブル* オブジェクトにもなります。
イミュータブルオブジェクトはオブジェクトが変更されるたびにオブジェクトのコピーを作ります。
なぜなら、日時周りの変更メソッドは必ずしも透明でないため、データが誤って、
または開発者が知らない内に変更してしまうからです。
イミュータブルオブジェクトはデータが誤って変更されることを防止し、
順序ベースの依存関係の問題の無いコードを作ります。
不変性は、変更時に忘れずに変数を置き換える必要があることを意味しています。 ::
// このコードはイミュータブルオブジェクトでは動作しません
$time->addDay(1);
doSomething($time);
return $time
// このコードは期待通りに動作します
$time = $time->addDay(1);
$time = doSomething($time);
return $time
各修正の戻り値をキャプチャーすることによって、コードは期待通りに動作します。
イミュータブルオブジェクトを持っていて、ミュータブルオブジェクトを作りたい場合、
``toMutable()`` が使用できます。 ::
$inplace = $time->toMutable();
日付オブジェクト
------------------
PHP は単純な DateTime オブジェクトだけを提供します。このクラスのカレンダー日付の表現で、
タイムゾーンおよび、本当に「日」の概念に属していないタイムコンポーネントを含むと、
少し厄介な可能性があります。
Chronos は日時表現のための ``Date`` オブジェクトを提供します。
これらのオブジェクトの時間とタイムゾーンは常に ``00:00:00 UTC`` に固定されており、
全ての書式/差分のメソッドは一日単位で動作します。 ::
use Cake\Chronos\Date;
$today = Date::today();
// 時間/タイムゾーンの変更は無視されます
$today->modify('+1 hours');
// 出力 '2015-12-20'
echo $today;
変更メソッド
------------
Chronos オブジェクトは細やかに値を変更できるメソッドを提供します。 ::
// 日時の値のコンポーネントを設定
$halloween = Chronos::create()
->year(2015)
->month(10)
->day(31)
->hour(20)
->minute(30);
また、日時の部分を相対的に変更することもできます。 ::
$future = Chronos::create()
->addYear(1)
->subMonth(2)
->addDays(15)
->addHours(20)
->subMinutes(2);
また、ある時間の中で、定義された時点に飛ぶことも可能です。 ::
$time = Chronos::create();
$time->startOfDay();
$time->endOfDay();
$time->startOfMonth();
$time->endOfMonth();
$time->startOfYear();
$time->endOfYear();
$time->startOfWeek();
$time->endOfWeek();
また、1週間中の特定の日にも飛べます。 ::
$time->next(ChronosInterface::TUESDAY);
$time->previous(ChronosInterface::MONDAY);
:abbr:`DST (夏時間)` の遷移の前後で日付/時間を変更すると、
あなたの操作で時間が増減するかもしれませんが、その結果、意図しない時間の値になります。
これらの問題を回避するには、最初にタイムゾーンを ``UTC`` に変更し、時間を変更します。 ::
// 余分な時間が追加されました
$time = new Chronos('2014-03-30 00:00:00', 'Europe/London');
debug($time->modify('+24 hours')); // 2014-03-31 01:00:00
// 最初に UTC に切り替え、そして更新
$time = $time->setTimezone('UTC')
->modify('+24 hours');
時間を変更すると、元のタイムゾーンを追加してローカライズされた時間を取得することができます。
比較メソッド
------------
Chronos の日付/時間オブジェクトの2つのインスタンスを様々な方法で比較することができます。 ::
// 比較のフルセットが存在します
// ne, gt, lt, lte.
$first->eq($second);
$first->gte($second);
// カレントオブジェクトが2つのオブジェクトの間にあるかどうかを確認します。
$now->between($start, $end);
// どちらの引数が最も近い (closest) か、または最も遠い (farthest) かを見つけます。
$now->closest($june, $november);
$now->farthest($june, $november);
また、与えられた値のカレンダーに当たる場所について問い合わせできます。 ::
$now->isToday();
$now->isYesterday();
$now->isFuture();
$now->isPast();
// 曜日をチェック
$now->isWeekend();
// 他の曜日のメソッドも全て存在します。
$now->isMonday();
また、値が相対的な期間内にあったかどうかを見つけることができます。 ::
$time->wasWithinLast('3 days');
$time->isWithinNext('3 hours');
差の生成
--------
日時比較に加えて、2つの値の差や変化の計算は一般的なタスクです。 ::
// 差をあらわす DateInterval を取得
$first->diff($second);
// 特定の単位での差を取得
$first->diffInHours($second);
$first->diffInDays($second);
$first->diffInWeeks($second);
$first->diffInYears($second);
フィードやタイムラインで使用するのに適した、人が読める形式の差を生成することができます。 ::
// 現在からの差
echo $date->diffForHumans();
// 別の時点からの差
echo $date->diffForHumans($other); // 1時間前;
フォーマットの設定
------------------
Chronos は、出力した日時オブジェクトを表示するための多くのメソッドを提供します。 ::
// setToStringFormat() が制御するフォーマットを使用します
echo $date;
// 別の標準フォーマット
echo $time->toAtomString(); // 1975-12-25T14:15:16-05:00
echo $time->toCookieString(); // Thursday, 25-Dec-1975 14:15:16 EST
echo $time->toIso8601String(); // 1975-12-25T14:15:16-05:00
echo $time->toRfc822String(); // Thu, 25 Dec 75 14:15:16 -0500
echo $time->toRfc850String(); // Thursday, 25-Dec-75 14:15:16 EST
echo $time->toRfc1036String(); // Thu, 25 Dec 75 14:15:16 -0500
echo $time->toRfc1123String(); // Thu, 25 Dec 1975 14:15:16 -0500
echo $time->toRfc2822String(); // Thu, 25 Dec 1975 14:15:16 -0500
echo $time->toRfc3339String(); // 1975-12-25T14:15:16-05:00
echo $time->toRssString(); // Thu, 25 Dec 1975 14:15:16 -0500
echo $time->toW3cString(); // 1975-12-25T14:15:16-05:00
// クォーター/週数を取得
echo $time->toQuarter(); // 4;
echo $time->toWeek(); // 52
// 一般的なフォーマット
echo $time->toTimeString(); // 14:15:16
echo $time->toDateString(); // 1975-12-25
echo $time->toDateTimeString(); // 1975-12-25 14:15:16
echo $time->toFormattedDateString(); // Dec 25, 1975
echo $time->toDayDateTimeString(); // Thu, Dec 25, 1975 2:15 PM
日付要素の抽出
--------------
日付オブジェクトのプロパティーに直接アクセスして要素を取得することができます。 ::
$time = new Chronos('2015-12-31 23:59:58');
$time->year; // 2015
$time->month; // 12
$time->day; // 31
$time->hour // 23
$time->minute // 59
$time->second // 58
以下のプロパティーにもアクセスできます。 :
- timezone
- timezoneName
- micro
- dayOfWeek
- dayOfMonth
- dayOfYear
- daysInMonth
- timestamp
- quarter
テストの支援
------------
単体テストを書いている時、現在時刻を固定すると便利です。Chronos は、
各クラスの現在時刻を修正することができます。
テストスイートの bootstrap 処理に以下を含めることができます。 ::
Chronos::setTestNow(Chronos::now());
MutableDateTime::setTestNow(MutableDateTime::now());
Date::setTestNow(Date::now());
MutableDate::setTestNow(MutableDate::now());
これでテストスイートが開始された時点で全てのオブジェクトの現在時刻を修正します。
例えば、 ``Chronos`` を過去のある瞬間に固定した場合、新たな ``Chronos``
のインスタンスが生成する ``now`` または相対時刻の文字列は、
固定された時刻の相対を返却します。 ::
Chronos::setTestNow(new Chronos('1975-12-25 00:00:00'));
$time = new Chronos(); // 1975-12-25 00:00:00
$time = new Chronos('1 hour ago'); // 1975-12-24 23:00:00
固定をリセットするには、 ``setTestNow()`` をパラメーター無し、または ``null`` を設定して
再び呼び出してください。

View File

@@ -1,9 +0,0 @@
import sys, os
# Append the top level directory of the docs, so we can import from the config dir.
sys.path.insert(0, os.path.abspath('..'))
# Pull in all the configuration options defined in the global config file..
from config.all import *
language = 'pt'

View File

@@ -1,7 +0,0 @@
.. toctree::
:maxdepth: 2
:caption: CakePHP Chronos
/index
API <https://api.cakephp.org/chronos>

View File

@@ -1,285 +0,0 @@
Chronos
#######
O Chronos oferece uma coleção independente de extensões para lidar com o objeto
``DateTime``. Além de métodos de conveniência, o Chronos oferece:
* Objetos ``Date`` para representar datas de calendário.
* Objetos *date* e *datetime* imutáveis.
* Um sistema de tradução acoplável. Apenas traduções em inglês estão incluídas
na biblioteca. Todavia, ``cakephp/i18n`` pode ser usado para suporte completo
a idiomas.
Instalação
----------
Para instalar o Chronos, você deve usar o ``composer``. A partir do diretório
*ROOT* de sua aplicação (local onde o arquivo composer.json está localizado)
execute o seguinte comando::
php composer.phar require cakephp/chronos "@stable"
Visão geral
-----------
Chronos oferece extensões para lidar com objetos *DateTime* do PHP. 5 classes
cobrem variantes de data/hora mutáveis e imutáveis e uma extensão do objeto
``DateInterval``.
* ``Cake\Chronos\Chronos`` é um objeto *date & time* imutável.
* ``Cake\Chronos\Date`` é um objeto *date* imutável.
* ``Cake\Chronos\MutableDateTime`` é um objeto *date and time* mutável.
* ``Cake\Chronos\MutableDate`` é um objeto *date* mutável.
* ``Cake\Chronos\ChronosInterval`` é uma extensão do objeto ``DateInterval``.
Por último, se você quiser usar o *typehint* em objetos do Chronos, será preciso
usar a interface ``Cake\Chronos\ChronosInterface``. Todos os objetos de data e
hora implementam essa interface.
Criando instâncias
------------------
Existem várias maneiras de criar instâncias do Chronos ou mesmo, do objeto Date.
Um número considerável de métodos padrão que funcionam com conjuntos diferentes
de argumentos::
use Cake\Chronos\Chronos;
$now = Chronos::now();
$today = Chronos::today();
$yesterday = Chronos::yesterday();
$tomorrow = Chronos::tomorrow();
// Interpreta expressões relativas.
$date = Chronos::parse('+2 days, +3 hours');
// Valores inteiros de Date e Time.
$date = Chronos::create(2015, 12, 25, 4, 32, 58);
// Valores inteiros de Date ou Time.
$date = Chronos::createFromDate(2015, 12, 25);
$date = Chronos::createFromTime(11, 45, 10);
// Interpreta valores formatados.
$date = Chronos::createFromFormat('m/d/Y', '06/15/2015');
Trabalhando com objetos imutáveis
---------------------------------
Se você é familiarizado com os objetos ``DateTime`` do PHP, você se sentirá
confortável com objetos *mutáveis*. Além de objetos mutáveis o Chronos também
oferece objetos imutáveis que por sua vez criam cópias de objetos toda vez que
um objeto é modificado. Devido ao fato de que metodos modificadores relativos
a data e hora nem sempre serem transparentes, informações podem ser modificadas
acidentalmente ou sem que o desenvolvedor saiba. Objetos imutáveis previnem
essas alterações acidentais nos dados. Imutabilidade significa que você deverá
lembrar de substituir variáveis usando modificadores::
// Esse código não funciona com objetos imutáveis
$time->addDay(1);
doSomething($time);
return $time;
// Esse funciona como o esperado
$time = $time->addDay(1);
$time = doSomething($time);
return $time;
Ao capturar o valor de retorno de cada modificação, seu código funcionará como o
esperado. Se você tem um objeto imutável e quer criar um mutável a partir do
mesmo, use ``toMutable()``::
$inplace = $time->toMutable();
Objetos Date
------------
O PHP disponibiliza um único objeto DateTime. Representar datas de calendário
pode ser um pouco desconfortável por essa classe, uma vez que ela inclui
*timezones* e componentes de hora que realmente não se encaixam no conceito de
'dia'. O Chronos oferece um objeto ``Date`` para representar datas. A hora e a
zona desse objeto é sempre fixado em ``00:00:00 UTC`` e todos os métodos de
formatação/diferença operam sob a resolução de dia::
use Cake\Chronos\Date;
$today = Date::today();
// Mudanças na hora/timezone são ignoradas
$today->modify('+1 hours');
// Exibe '2016-08-15'
echo $today;
Métodos modificadores
---------------------
Objetos Chronos disponibilizam métodos que permitem a modificação de valores de
forma granular::
// Define componentes do valor datetime
$halloween = Chronos::create()
->year(2015)
->month(10)
->day(31)
->hour(20)
->minute(30);
Você também pode modificar partes da data relativamente::
$future = Chronos::create()
->addYear(1)
->subMonth(2)
->addDays(15)
->addHours(20)
->subMinutes(2);
Também é possível realizar grandes saltos para períodos definidos no tempo::
$time = Chronos::create();
$time->startOfDay();
$time->startOfMonth();
$time->endOfMonth();
$time->endOfYear();
$time->startOfWeek();
$time->endOfWeek();
Ou ainda para dias específicos da semana::
$time->next(ChronosInterface::TUESDAY);
$time->previous(ChronosInterface::MONDAY);
Métodos de comparação
---------------------
Uma vez que você possui 2 instâncias de objetos data/hora do Chronos, é possível
compará-los de várias maneiras::
// Coleção completa de comparadores
// ne, gt, lt, lte.
$first->eq($second);
$first->gte($second);
// Veja se o objeto atual está entre outros
$now->between($start, $end);
// Encontre qual argumento está mais perto ou mais longe
$now->closest($june, $november);
$now->farthest($june, $november);
Você também pode arguir sobre quando um determinado valor cai no calendário::
$now->isToday();
$now->isYesterday();
$now->isFuture();
$now->isPast();
// Verifica se o dia é no final de semana
$now->isWeekend();
// Todos os métodos para outros dias da semana existem também
$now->isMonday();
Você também pode verificar se um determinado valor está dentro de um período de
tempo relativo::
$time->wasWithinLast('3 days');
$time->isWithinNext('3 hours');
Gerando diferenças
------------------
Em adição à comparação de *datetimes*, calcular diferenças ou deltas entre
valores é uma tarefa simples::
// Recebe um DateInterval representando a diferença
$first->diff($second);
// Recebe a diferença como um contador de unidades específicas
$first->diffInHours($second);
$first->diffInDays($second);
$first->diffInWeeks($second);
$first->diffInYears($second);
Você pode gerar diferenças de fácil leitura para humanos para usar em um *feed*
ou *timeline*::
// Diferença em relação ao momento atual
echo $date->diffForHumans();
// Diferença em relação a outro período no tempo
echo $date->diffForHumans($other); // 1 hora atrás;
Formatando strings
------------------
O Chronos disponibiliza métodos para exibir nossos objetos *datetime*::
// Usa o formato controlado por setToStringFormat()
echo $date;
// Diferentes padrões de formato
echo $time->toAtomString(); // 1975-12-25T14:15:16-05:00
echo $time->toCookieString(); // Thursday, 25-Dec-1975 14:15:16 EST
echo $time->toIso8601String(); // 1975-12-25T14:15:16-05:00
echo $time->toRfc822String(); // Thu, 25 Dec 75 14:15:16 -0500
echo $time->toRfc850String(); // Thursday, 25-Dec-75 14:15:16 EST
echo $time->toRfc1036String(); // Thu, 25 Dec 75 14:15:16 -0500
echo $time->toRfc1123String(); // Thu, 25 Dec 1975 14:15:16 -0500
echo $time->toRfc2822String(); // Thu, 25 Dec 1975 14:15:16 -0500
echo $time->toRfc3339String(); // 1975-12-25T14:15:16-05:00
echo $time->toRssString(); // Thu, 25 Dec 1975 14:15:16 -0500
echo $time->toW3cString(); // 1975-12-25T14:15:16-05:00
// Recebe o trimestre
echo $time->toQuarter(); // 4;
Extraindo componentes de data
-----------------------------
Podemos receber partes de um objeto *date* acessando propriedades::
$time = new Chronos('2015-12-31 23:59:58');
$time->year; // 2015
$time->month; // 12
$time->day; // 31
$time->hour // 23
$time->minute // 59
$time->second // 58
Outras propriedades que podem ser acessadas são:
- timezone
- timezoneName
- micro
- dayOfWeek
- dayOfMonth
- dayOfYear
- daysInMonth
- timestamp
- quarter
Auxílio para testes
-------------------
Ao escrever testes unitários, fixar a hora atual é bastante útil. O Chronos
lhe permite fixar a hora atual para cada classe. Como parte das suas ferramentas
de testes, você pode incluir o seguinte::
Chronos::setTestNow(Chronos::now());
MutableDateTime::setTestNow(MutableDateTime::now());
Date::setTestNow(Date::now());
MutableDate::setTestNow(MutableDate::now());
Isso irá corrigir a hora atual de todos os objetos para o momento em que o
processo de testes foi iniciado.
Por exemplo, se você fixar o ``Chronos`` em algum momento no passado, qualquer
nova instância do ``Chronos`` criada com ``now`` ou uma *string* de tempo
relativa, teremos um retorno referente ao tempo fixado::
Chronos::setTestNow(new Chronos('1975-12-25 00:00:00'));
$time = new Chronos(); // 1975-12-25 00:00:00
$time = new Chronos('1 hour ago'); // 1975-12-24 23:00:00

View File

@@ -1,215 +0,0 @@
<?php
declare(strict_types=1);
/**
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @copyright Copyright (c) Brian Nesbitt <brian@nesbot.com>
* @link http://cakephp.org CakePHP(tm) Project
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Cake\Chronos;
use DateTimeImmutable;
use DateTimeZone;
/**
* An Immutable extension on the native DateTime object.
*
* Adds a number of convenience APIs methods and the ability
* to easily convert into a mutable object.
*
* @property-read int $year
* @property-read int $yearIso
* @property-read int $month
* @property-read int $day
* @property-read int $hour
* @property-read int $minute
* @property-read int $second
* @property-read int $micro
* @property-read int $microsecond
* @property-read int $timestamp seconds since the Unix Epoch
* @property-read \DateTimeZone $timezone the current timezone
* @property-read \DateTimeZone $tz alias of timezone
* @property-read int $dayOfWeek 1 (for Monday) through 7 (for Sunday)
* @property-read int $dayOfYear 0 through 365
* @property-read int $weekOfMonth 1 through 5
* @property-read int $weekOfYear ISO-8601 week number of year, weeks starting on Monday
* @property-read int $daysInMonth number of days in the given month
* @property-read int $age does a diffInYears() with default parameters
* @property-read int $quarter the quarter of this instance, 1 - 4
* @property-read int $offset the timezone offset in seconds from UTC
* @property-read int $offsetHours the timezone offset in hours from UTC
* @property-read bool $dst daylight savings time indicator, true if DST, false otherwise
* @property-read bool $local checks if the timezone is local, true if local, false otherwise
* @property-read bool $utc checks if the timezone is UTC, true if UTC, false otherwise
* @property-read string $timezoneName
* @property-read string $tzName
*/
class Chronos extends DateTimeImmutable implements ChronosInterface
{
use Traits\ComparisonTrait;
use Traits\DifferenceTrait;
use Traits\FactoryTrait;
use Traits\FormattingTrait;
use Traits\MagicPropertyTrait;
use Traits\ModifierTrait;
use Traits\RelativeKeywordTrait;
use Traits\TimezoneTrait;
/**
* A test ChronosInterface instance to be returned when now instances are created
*
* There is a single test now for all date/time classes provided by Chronos.
* This aims to emulate stubbing out 'now' which is a single global fact.
*
* @var \Cake\Chronos\ChronosInterface|null
*/
protected static $testNow;
/**
* Format to use for __toString method when type juggling occurs.
*
* @var string
*/
protected static $toStringFormat = ChronosInterface::DEFAULT_TO_STRING_FORMAT;
/**
* Create a new Chronos instance.
*
* Please see the testing aids section (specifically static::setTestNow())
* for more on the possibility of this constructor returning a test instance.
*
* @param \DateTimeInterface|string|int|null $time Fixed or relative time
* @param \DateTimeZone|string|null $tz The timezone for the instance
*/
public function __construct($time = 'now', $tz = null)
{
if (is_int($time)) {
parent::__construct('@' . $time);
return;
}
if ($tz !== null) {
$tz = $tz instanceof DateTimeZone ? $tz : new DateTimeZone($tz);
}
if ($time instanceof \DateTimeInterface) {
$time = $time->format('Y-m-d H:i:s.u');
}
static::$_lastErrors = [];
$testNow = static::getTestNow();
if ($testNow === null) {
parent::__construct($time ?? 'now', $tz);
return;
}
$relative = static::hasRelativeKeywords($time);
if (!empty($time) && $time !== 'now' && !$relative) {
parent::__construct($time, $tz);
return;
}
$testNow = clone $testNow;
$relativetime = static::isTimeExpression($time);
if (!$relativetime && $tz !== $testNow->getTimezone()) {
$testNow = $testNow->setTimezone($tz ?? date_default_timezone_get());
}
if ($relative) {
$testNow = $testNow->modify($time);
}
$time = $testNow->format('Y-m-d H:i:s.u');
parent::__construct($time, $tz);
}
/**
* Create a new mutable instance from current immutable instance.
*
* @return \Cake\Chronos\MutableDateTime
*/
public function toMutable(): MutableDateTime
{
return MutableDateTime::instance($this);
}
/**
* Get a copy of the instance
*
* @return static
*/
public function copy(): ChronosInterface
{
return clone $this;
}
/**
* Set a ChronosInterface instance (real or mock) to be returned when a "now"
* instance is created. The provided instance will be returned
* specifically under the following conditions:
* - A call to the static now() method, ex. ChronosInterface::now()
* - When a null (or blank string) is passed to the constructor or parse(), ex. new Chronos(null)
* - When the string "now" is passed to the constructor or parse(), ex. new Chronos('now')
* - When a string containing the desired time is passed to ChronosInterface::parse()
*
* Note the timezone parameter was left out of the examples above and
* has no affect as the mock value will be returned regardless of its value.
*
* To clear the test instance call this method using the default
* parameter of null.
*
* @param \Cake\Chronos\ChronosInterface|string|null $testNow The instance to use for all future instances.
* @return void
*/
public static function setTestNow($testNow = null): void
{
static::$testNow = is_string($testNow) ? static::parse($testNow) : $testNow;
}
/**
* Get the ChronosInterface instance (real or mock) to be returned when a "now"
* instance is created.
*
* @return \Cake\Chronos\ChronosInterface|null The current instance used for testing
*/
public static function getTestNow(): ?ChronosInterface
{
return static::$testNow;
}
/**
* Determine if there is a valid test instance set. A valid test instance
* is anything that is not null.
*
* @return bool True if there is a test instance, otherwise false
*/
public static function hasTestNow(): bool
{
return static::$testNow !== null;
}
/**
* Return properties for debugging.
*
* @return array
*/
public function __debugInfo(): array
{
$properties = [
'hasFixedNow' => static::hasTestNow(),
'time' => $this->format('Y-m-d H:i:s.u'),
'timezone' => $this->getTimezone()->getName(),
];
return $properties;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,550 +0,0 @@
<?php
declare(strict_types=1);
/**
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @copyright Copyright (c) Brian Nesbitt <brian@nesbot.com>
* @link http://cakephp.org CakePHP(tm) Project
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Cake\Chronos;
use BadMethodCallException;
use DateInterval;
use InvalidArgumentException;
/**
* A simple API extension for DateInterval.
* The implementation provides helpers to handle weeks but only days are saved.
* Weeks are calculated based on the total days of the current instance.
*
* @property int $years Total years of the current interval.
* @property int $months Total months of the current interval.
* @property int $weeks Total weeks of the current interval calculated from the days.
* @property int $dayz Total days of the current interval (weeks * 7 + days).
* @property int $hours Total hours of the current interval.
* @property int $minutes Total minutes of the current interval.
* @property int $seconds Total seconds of the current interval.
* @property int $microseconds Total microseconds of the current interval.
* @property-read int $dayzExcludeWeeks Total days remaining in the final week of the current instance (days % 7).
* @property-read int $daysExcludeWeeks alias of dayzExcludeWeeks
* @method static \Cake\Chronos\ChronosInterval years($years = 1) Create instance specifying a number of years.
* @method static \Cake\Chronos\ChronosInterval year($years = 1) Alias for years
* @method static \Cake\Chronos\ChronosInterval months($months = 1) Create instance specifying a number of months.
* @method static \Cake\Chronos\ChronosInterval month($months = 1) Alias for months
* @method static \Cake\Chronos\ChronosInterval weeks($weeks = 1) Create instance specifying a number of weeks.
* @method static \Cake\Chronos\ChronosInterval week($weeks = 1) Alias for weeks
* @method static \Cake\Chronos\ChronosInterval days($days = 1) Create instance specifying a number of days.
* @method static \Cake\Chronos\ChronosInterval dayz($days = 1) Alias for days
* @method static \Cake\Chronos\ChronosInterval day($days = 1) Alias for days
* @method static \Cake\Chronos\ChronosInterval hours($hours = 1) Create instance specifying a number of hours.
* @method static \Cake\Chronos\ChronosInterval hour($hours = 1) Alias for hours
* @method static \Cake\Chronos\ChronosInterval minutes($minutes = 1) Create instance specifying a number of minutes.
* @method static \Cake\Chronos\ChronosInterval minute($minutes = 1) Alias for minutes
* @method static \Cake\Chronos\ChronosInterval seconds($seconds = 1) Create instance specifying a number of seconds.
* @method static \Cake\Chronos\ChronosInterval second($seconds = 1) Alias for seconds
* @method static \Cake\Chronos\ChronosInterval microseconds($microseconds = 1) Create instance specifying a number of microseconds.
* @method static \Cake\Chronos\ChronosInterval microsecond($microseconds = 1) Alias for microseconds
*/
class ChronosInterval extends DateInterval
{
/**
* @var string
*/
public const PERIOD_PREFIX = 'P';
/**
* @var string
*/
public const PERIOD_YEARS = 'Y';
/**
* @var string
*/
public const PERIOD_MONTHS = 'M';
/**
* @var string
*/
public const PERIOD_DAYS = 'D';
/**
* @var string
*/
public const PERIOD_TIME_PREFIX = 'T';
/**
* @var string
*/
public const PERIOD_HOURS = 'H';
/**
* @var string
*/
public const PERIOD_MINUTES = 'M';
/**
* @var string
*/
public const PERIOD_SECONDS = 'S';
/**
* Determine if the interval was created via DateTime:diff() or not.
*
* @param \DateInterval $interval The interval to check.
* @return bool
*/
protected static function wasCreatedFromDiff(DateInterval $interval): bool
{
return $interval->days !== false;
}
/**
* Create a new ChronosInterval instance.
*
* @param int|null $years The year to use.
* @param int|null $months The month to use.
* @param int|null $weeks The week to use.
* @param int|null $days The day to use.
* @param int|null $hours The hours to use.
* @param int|null $minutes The minutes to use.
* @param int|null $seconds The seconds to use.
* @param int|null $microseconds The microseconds to use.
*/
public function __construct(
?int $years = 1,
?int $months = null,
?int $weeks = null,
?int $days = null,
?int $hours = null,
?int $minutes = null,
?int $seconds = null,
?int $microseconds = null
) {
$spec = static::PERIOD_PREFIX;
$spec .= $years > 0 ? $years . static::PERIOD_YEARS : '';
$spec .= $months > 0 ? $months . static::PERIOD_MONTHS : '';
$specDays = 0;
$specDays += $weeks > 0 ? $weeks * ChronosInterface::DAYS_PER_WEEK : 0;
$specDays += $days > 0 ? $days : 0;
$spec .= $specDays > 0 ? $specDays . static::PERIOD_DAYS : '';
if ($spec === static::PERIOD_PREFIX) {
$spec .= '0' . static::PERIOD_YEARS;
}
if ($hours > 0 || $minutes > 0 || $seconds > 0) {
$spec .= static::PERIOD_TIME_PREFIX;
$spec .= $hours > 0 ? $hours . static::PERIOD_HOURS : '';
$spec .= $minutes > 0 ? $minutes . static::PERIOD_MINUTES : '';
$spec .= $seconds > 0 ? $seconds . static::PERIOD_SECONDS : '';
}
parent::__construct($spec);
if ($microseconds > 0) {
$this->f = $microseconds / 1000000;
}
}
/**
* Create a new ChronosInterval instance from specific values.
* This is an alias for the constructor that allows better fluent
* syntax as it allows you to do ChronosInterval::create(1)->fn() rather than
* (new ChronosInterval(1))->fn().
*
* @param int|null $years The year to use.
* @param int|null $months The month to use.
* @param int|null $weeks The week to use.
* @param int|null $days The day to use.
* @param int|null $hours The hours to use.
* @param int|null $minutes The minutes to use.
* @param int|null $seconds The seconds to use.
* @param int|null $microseconds The microseconds to use.
* @return static
*/
public static function create(
?int $years = 1,
?int $months = null,
?int $weeks = null,
?int $days = null,
?int $hours = null,
?int $minutes = null,
?int $seconds = null,
?int $microseconds = null
): self {
return new static($years, $months, $weeks, $days, $hours, $minutes, $seconds, $microseconds);
}
/**
* Provide static helpers to create instances. Allows:
*
* ```
* ChronosInterval::years(3)
* // or
* ChronosInterval::month(1);
* ```
*
* Note: This is done using the magic method to allow static and instance methods to
* have the same names.
*
* @param string $name The property to configure. Accepts singular and plural forms.
* @param array $args Contains the value to use.
* @return static
*/
public static function __callStatic(string $name, array $args): self
{
$arg = count($args) === 0 ? 1 : $args[0];
switch ($name) {
case 'years':
case 'year':
return new static($arg);
case 'months':
case 'month':
return new static(null, $arg);
case 'weeks':
case 'week':
return new static(null, null, $arg);
case 'days':
case 'dayz':
case 'day':
return new static(null, null, null, $arg);
case 'hours':
case 'hour':
return new static(null, null, null, null, $arg);
case 'minutes':
case 'minute':
return new static(null, null, null, null, null, $arg);
case 'seconds':
case 'second':
return new static(null, null, null, null, null, null, $arg);
case 'microseconds':
case 'microsecond':
return new static(null, null, null, null, null, null, null, $arg);
}
throw new BadMethodCallException(sprintf('Cannot create interval with `%s` units', $name));
}
/**
* Create a ChronosInterval instance from a DateInterval one. Can not instance
* DateInterval objects created from DateTime::diff() as you can't externally
* set the $days field.
*
* @param \DateInterval $di The DateInterval instance to copy.
* @throws \InvalidArgumentException
* @return static
*/
public static function instance(DateInterval $di): self
{
if (static::wasCreatedFromDiff($di)) {
throw new InvalidArgumentException(
'Can not instance a DateInterval object created from DateTime::diff().'
);
}
$instance = new static($di->y, $di->m, 0, $di->d, $di->h, $di->i, $di->s);
$instance->f = $di->f;
$instance->invert = $di->invert;
$instance->days = $di->days;
return $instance;
}
/**
* Get a part of the ChronosInterval object
*
* @param string $name The property to read.
* @throws \InvalidArgumentException
* @return int
*/
public function __get(string $name)
{
switch ($name) {
case 'years':
return $this->y;
case 'months':
return $this->m;
case 'dayz':
return $this->d;
case 'hours':
return $this->h;
case 'minutes':
return $this->i;
case 'seconds':
return $this->s;
case 'microseconds':
return (int)($this->f * 1000000);
case 'weeks':
return (int)floor($this->d / ChronosInterface::DAYS_PER_WEEK);
case 'daysExcludeWeeks':
case 'dayzExcludeWeeks':
return $this->dayz % ChronosInterface::DAYS_PER_WEEK;
default:
throw new InvalidArgumentException(sprintf("Unknown getter '%s'", $name));
}
}
/**
* Set a part of the ChronosInterval object
*
* @param string $name The property to augment.
* @param int $val The value to change.
* @return void
* @throws \InvalidArgumentException
*/
public function __set(string $name, $val): void
{
switch ($name) {
case 'years':
$this->y = $val;
break;
case 'months':
$this->m = $val;
break;
case 'weeks':
$val = $val * ChronosInterface::DAYS_PER_WEEK;
$this->d = $val;
break;
case 'dayz':
$this->d = $val;
break;
case 'hours':
$this->h = $val;
break;
case 'minutes':
$this->i = $val;
break;
case 'seconds':
$this->s = $val;
break;
case 'microseconds':
$this->f = $val / 1000000;
break;
case 'invert':
$this->invert = $val;
break;
}
}
/**
* Allow setting of weeks and days to be cumulative.
*
* @param int $weeks Number of weeks to set
* @param int $days Number of days to set
* @return $this
*/
public function weeksAndDays(int $weeks, int $days)
{
$this->dayz = ($weeks * ChronosInterface::DAYS_PER_WEEK) + $days;
return $this;
}
/**
* Allow fluent calls on the setters... ChronosInterval::years(3)->months(5)->day().
*
* Note: This is done using the magic method to allow static and instance methods to
* have the same names.
*
* @param string $name The property name to augment. Accepts plural forms in addition
* to singular ones.
* @param array $args The value to set.
* @return $this
*/
public function __call(string $name, array $args)
{
$arg = count($args) === 0 ? 1 : $args[0];
switch ($name) {
case 'years':
case 'year':
$this->years = $arg;
break;
case 'months':
case 'month':
$this->months = $arg;
break;
case 'weeks':
case 'week':
$this->dayz = $arg * ChronosInterface::DAYS_PER_WEEK;
break;
case 'days':
case 'dayz':
case 'day':
$this->dayz = $arg;
break;
case 'hours':
case 'hour':
$this->hours = $arg;
break;
case 'minutes':
case 'minute':
$this->minutes = $arg;
break;
case 'seconds':
case 'second':
$this->seconds = $arg;
break;
case 'microseconds':
case 'microsecond':
$this->microseconds = $arg;
break;
}
return $this;
}
/**
* Add the passed interval to the current instance
*
* @param \DateInterval $interval The interval to add.
* @return $this
*/
public function add(DateInterval $interval)
{
$sign = $interval->invert === 1 ? -1 : 1;
if (static::wasCreatedFromDiff($interval)) {
$this->dayz = $this->dayz + ($interval->days * $sign);
} else {
$this->years = $this->years + ($interval->y * $sign);
$this->months = $this->months + ($interval->m * $sign);
$this->dayz = $this->dayz + ($interval->d * $sign);
$this->hours = $this->hours + ($interval->h * $sign);
$this->minutes = $this->minutes + ($interval->i * $sign);
$this->seconds = $this->seconds + ($interval->s * $sign);
$this->microseconds = $this->microseconds + (int)($interval->f * 1000000 * $sign);
}
return $this;
}
/**
* Returns the ISO 8601 interval string.
*
* @return string Interval as string representation
*/
public function __toString(): string
{
// equivalence
$oneMinuteInSeconds = 60;
$oneHourInSeconds = $oneMinuteInSeconds * 60;
$oneDayInSeconds = $oneHourInSeconds * 24;
$oneMonthInDays = 365 / 12;
$oneMonthInSeconds = $oneDayInSeconds * $oneMonthInDays;
$oneYearInSeconds = 12 * $oneMonthInSeconds;
// convert
$ySecs = $this->y * $oneYearInSeconds;
$mSecs = $this->m * $oneMonthInSeconds;
$dSecs = $this->d * $oneDayInSeconds;
$hSecs = $this->h * $oneHourInSeconds;
$iSecs = $this->i * $oneMinuteInSeconds;
$sSecs = $this->s;
$totalSecs = $ySecs + $mSecs + $dSecs + $hSecs + $iSecs + $sSecs;
$y = null;
$m = null;
$d = null;
$h = null;
$i = null;
// years
if ($totalSecs >= $oneYearInSeconds) {
$y = floor($totalSecs / $oneYearInSeconds);
$totalSecs = $totalSecs - $y * $oneYearInSeconds;
}
// months
if ($totalSecs >= $oneMonthInSeconds) {
$m = floor($totalSecs / $oneMonthInSeconds);
$totalSecs = $totalSecs - $m * $oneMonthInSeconds;
}
// days
if ($totalSecs >= $oneDayInSeconds) {
$d = floor($totalSecs / $oneDayInSeconds);
$totalSecs = $totalSecs - $d * $oneDayInSeconds;
}
// hours
if ($totalSecs >= $oneHourInSeconds) {
$h = floor($totalSecs / $oneHourInSeconds);
$totalSecs = $totalSecs - $h * $oneHourInSeconds;
}
// minutes
if ($totalSecs >= $oneMinuteInSeconds) {
$i = floor($totalSecs / $oneMinuteInSeconds);
$totalSecs = $totalSecs - $i * $oneMinuteInSeconds;
}
$s = $totalSecs;
$date = array_filter([
static::PERIOD_YEARS => $y,
static::PERIOD_MONTHS => $m,
static::PERIOD_DAYS => $d,
]);
$time = array_filter([
static::PERIOD_HOURS => $h,
static::PERIOD_MINUTES => $i,
static::PERIOD_SECONDS => $s,
]);
$specString = static::PERIOD_PREFIX;
foreach ($date as $key => $value) {
$specString .= $value . $key;
}
if (count($time) > 0) {
$specString .= static::PERIOD_TIME_PREFIX;
foreach ($time as $key => $value) {
$specString .= $value . $key;
}
}
if ($specString === static::PERIOD_PREFIX) {
return 'PT0S';
}
return $this->invert === 1 ? '-' . $specString : $specString;
}
}

View File

@@ -1,142 +0,0 @@
<?php
declare(strict_types=1);
/**
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Cake\Chronos;
use DateTimeImmutable;
use DateTimeZone;
/**
* An immutable date object that converts all time components into 00:00:00.
*
* This class is useful when you want to represent a calendar date and ignore times.
* This means that timezone changes take no effect as a calendar date exists in all timezones
* in each respective date.
*
* @property-read int $year
* @property-read int $yearIso
* @property-read int $month
* @property-read int $day
* @property-read int $hour
* @property-read int $minute
* @property-read int $second
* @property-read int $micro
* @property-read int $microsecond
* @property-read int $timestamp seconds since the Unix Epoch
* @property-read \DateTimeZone $timezone the current timezone
* @property-read \DateTimeZone $tz alias of timezone
* @property-read int $dayOfWeek 1 (for Monday) through 7 (for Sunday)
* @property-read int $dayOfYear 0 through 365
* @property-read int $weekOfMonth 1 through 5
* @property-read int $weekOfYear ISO-8601 week number of year, weeks starting on Monday
* @property-read int $daysInMonth number of days in the given month
* @property-read int $age does a diffInYears() with default parameters
* @property-read int $quarter the quarter of this instance, 1 - 4
* @property-read int $offset the timezone offset in seconds from UTC
* @property-read int $offsetHours the timezone offset in hours from UTC
* @property-read bool $dst daylight savings time indicator, true if DST, false otherwise
* @property-read bool $local checks if the timezone is local, true if local, false otherwise
* @property-read bool $utc checks if the timezone is UTC, true if UTC, false otherwise
* @property-read string $timezoneName
* @property-read string $tzName
*/
class Date extends DateTimeImmutable implements ChronosInterface
{
use Traits\ComparisonTrait;
use Traits\DifferenceTrait;
use Traits\FactoryTrait;
use Traits\FormattingTrait;
use Traits\FrozenTimeTrait;
use Traits\MagicPropertyTrait;
use Traits\ModifierTrait;
use Traits\TestingAidTrait;
/**
* Format to use for __toString method when type juggling occurs.
*
* @var string
*/
protected static $toStringFormat = 'Y-m-d';
/**
* Create a new Immutable Date instance.
*
* You can specify the timezone for the $time parameter. This timezone will
* not be used in any future modifications to the Date instance.
*
* The $timezone parameter is ignored if $time is a DateTimeInterface
* instance.
*
* Please see the testing aids section (specifically static::setTestNow())
* for more on the possibility of this constructor returning a test instance.
*
* Date instances lack time components, however due to limitations in PHP's
* internal Datetime object the time will always be set to 00:00:00, and the
* timezone will always be the server local time. Normalizing the timezone allows for
* subtraction/addition to have deterministic results.
*
* @param \DateTimeInterface|string|int|null $time Fixed or relative time
* @param \DateTimeZone|string|null $tz The timezone in which the date is taken
*/
public function __construct($time = 'now', $tz = null)
{
if ($tz !== null) {
$tz = $tz instanceof DateTimeZone ? $tz : new DateTimeZone($tz);
}
$testNow = Chronos::getTestNow();
if ($testNow === null || !static::isRelativeOnly($time)) {
$time = $this->stripTime($time, $tz);
parent::__construct($time);
return;
}
$testNow = clone $testNow;
if ($tz !== $testNow->getTimezone()) {
$testNow = $testNow->setTimezone($tz ?? date_default_timezone_get());
}
if (!empty($time)) {
$testNow = $testNow->modify($time);
}
$time = $testNow->format('Y-m-d 00:00:00');
parent::__construct($time);
}
/**
* Create a new mutable instance from current immutable instance.
*
* @return \Cake\Chronos\MutableDate
*/
public function toMutable(): MutableDate
{
return MutableDate::instance($this);
}
/**
* Return properties for debugging.
*
* @return array
*/
public function __debugInfo(): array
{
$properties = [
'hasFixedNow' => static::hasTestNow(),
'date' => $this->format('Y-m-d'),
];
return $properties;
}
}

View File

@@ -1,107 +0,0 @@
<?php
declare(strict_types=1);
/**
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @copyright Copyright (c) Brian Nesbitt <brian@nesbot.com>
* @link http://cakephp.org CakePHP(tm) Project
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Cake\Chronos;
/**
* Handles formatting differences in text.
*
* Provides a swappable component for other libraries to leverage.
* when localizing or customizing the difference output.
*/
class DifferenceFormatter implements DifferenceFormatterInterface
{
/**
* The text translator object
*
* @var \Cake\Chronos\Translator
*/
protected $translate;
/**
* Constructor.
*
* @param \Cake\Chronos\Translator|null $translate The text translator object.
*/
public function __construct(?Translator $translate = null)
{
$this->translate = $translate ?: new Translator();
}
/**
* Get the difference in a human readable format.
*
* @param \Cake\Chronos\ChronosInterface $date The datetime to start with.
* @param \Cake\Chronos\ChronosInterface|null $other The datetime to compare against.
* @param bool $absolute removes time difference modifiers ago, after, etc
* @return string The difference between the two days in a human readable format
* @see \Cake\Chronos\ChronosInterface::diffForHumans
*/
public function diffForHumans(
ChronosInterface $date,
?ChronosInterface $other = null,
bool $absolute = false
): string {
$isNow = $other === null;
if ($isNow) {
$other = $date->now($date->tz);
}
$diffInterval = $date->diff($other);
switch (true) {
case $diffInterval->y > 0:
$unit = 'year';
$count = $diffInterval->y;
break;
case $diffInterval->m > 0:
$unit = 'month';
$count = $diffInterval->m;
break;
case $diffInterval->d > 0:
$unit = 'day';
$count = $diffInterval->d;
if ($count >= ChronosInterface::DAYS_PER_WEEK) {
$unit = 'week';
$count = (int)($count / ChronosInterface::DAYS_PER_WEEK);
}
break;
case $diffInterval->h > 0:
$unit = 'hour';
$count = $diffInterval->h;
break;
case $diffInterval->i > 0:
$unit = 'minute';
$count = $diffInterval->i;
break;
default:
$count = $diffInterval->s;
$unit = 'second';
break;
}
$time = $this->translate->plural($unit, $count, ['count' => $count]);
if ($absolute) {
return $time;
}
$isFuture = $diffInterval->invert === 1;
$transId = $isNow ? ($isFuture ? 'from_now' : 'ago') : ($isFuture ? 'after' : 'before');
// Some langs have special pluralization for past and future tense.
$tryKeyExists = $unit . '_' . $transId;
if ($this->translate->exists($tryKeyExists)) {
$time = $this->translate->plural($tryKeyExists, $count, ['count' => $count]);
}
return $this->translate->singular($transId, ['time' => $time]);
}
}

View File

@@ -1,35 +0,0 @@
<?php
declare(strict_types=1);
/**
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Cake\Chronos;
/**
* Interface for formatting differences in text.
*/
interface DifferenceFormatterInterface
{
/**
* Get the difference in a human readable format.
*
* @param \Cake\Chronos\ChronosInterface $date The datetime to start with.
* @param \Cake\Chronos\ChronosInterface|null $other The datetime to compare against.
* @param bool $absolute Removes time difference modifiers ago, after, etc.
* @return string The difference between the two days in a human readable format.
* @see \Cake\Chronos\ChronosInterface::diffForHumans
*/
public function diffForHumans(
ChronosInterface $date,
?ChronosInterface $other = null,
bool $absolute = false
): string;
}

View File

@@ -1,141 +0,0 @@
<?php
declare(strict_types=1);
/**
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Cake\Chronos;
use DateTime;
use DateTimeZone;
/**
* A mutable date object that converts all time components into 00:00:00.
*
* This class is useful when you want to represent a calendar date and ignore times.
* This means that timezone changes take no effect as a calendar date exists in all timezones
* in each respective date.
*
* @property-read int $year
* @property-read int $yearIso
* @property-read int $month
* @property-read int $day
* @property-read int $hour
* @property-read int $minute
* @property-read int $second
* @property-read int $micro
* @property-read int $microsecond
* @property-read int $timestamp seconds since the Unix Epoch
* @property-read \DateTimeZone $timezone the current timezone
* @property-read \DateTimeZone $tz alias of timezone
* @property-read int $dayOfWeek 1 (for Monday) through 7 (for Sunday)
* @property-read int $dayOfYear 0 through 365
* @property-read int $weekOfMonth 1 through 5
* @property-read int $weekOfYear ISO-8601 week number of year, weeks starting on Monday
* @property-read int $daysInMonth number of days in the given month
* @property-read int $age does a diffInYears() with default parameters
* @property-read int $quarter the quarter of this instance, 1 - 4
* @property-read int $offset the timezone offset in seconds from UTC
* @property-read int $offsetHours the timezone offset in hours from UTC
* @property-read bool $dst daylight savings time indicator, true if DST, false otherwise
* @property-read bool $local checks if the timezone is local, true if local, false otherwise
* @property-read bool $utc checks if the timezone is UTC, true if UTC, false otherwise
* @property-read string $timezoneName
* @property-read string $tzName
*/
class MutableDate extends DateTime implements ChronosInterface
{
use Traits\ComparisonTrait;
use Traits\DifferenceTrait;
use Traits\FactoryTrait;
use Traits\FormattingTrait;
use Traits\FrozenTimeTrait;
use Traits\MagicPropertyTrait;
use Traits\ModifierTrait;
use Traits\TestingAidTrait;
/**
* Format to use for __toString method when type juggling occurs.
*
* @var string
*/
protected static $toStringFormat = 'Y-m-d';
/**
* Create a new mutable Date instance.
*
* You can specify the timezone for the $time parameter. This timezone will
* not be used in any future modifications to the Date instance.
*
* The $timezone parameter is ignored if $time is a DateTimeInterface
* instance.
*
* Please see the testing aids section (specifically static::setTestNow())
* for more on the possibility of this constructor returning a test instance.
*
* Date instances lack time components, however due to limitations in PHP's
* internal Datetime object the time will always be set to 00:00:00, and the
* timezone will always be server local timezone. Normalizing the timezone allows for
* subtraction/addition to have deterministic results.
*
* @param \DateTimeInterface|string|int|null $time Fixed or relative time
* @param \DateTimeZone|string|null $tz The timezone in which the date is taken
*/
public function __construct($time = 'now', $tz = null)
{
if ($tz !== null) {
$tz = $tz instanceof DateTimeZone ? $tz : new DateTimeZone($tz);
}
$testNow = Chronos::getTestNow();
if ($testNow === null || !static::isRelativeOnly($time)) {
$time = $this->stripTime($time, $tz);
parent::__construct($time);
return;
}
$testNow = clone $testNow;
if ($tz !== $testNow->getTimezone()) {
$testNow = $testNow->setTimezone($tz ?? date_default_timezone_get());
}
if (!empty($time)) {
$testNow = $testNow->modify($time);
}
$time = $testNow->format('Y-m-d 00:00:00');
parent::__construct($time);
}
/**
* Create a new immutable instance from current mutable instance.
*
* @return \Cake\Chronos\Date
*/
public function toImmutable(): Date
{
return Date::instance($this);
}
/**
* Return properties for debugging.
*
* @return array
*/
public function __debugInfo(): array
{
$properties = [
'hasFixedNow' => static::hasTestNow(),
'date' => $this->format('Y-m-d'),
];
return $properties;
}
}

View File

@@ -1,200 +0,0 @@
<?php
declare(strict_types=1);
/**
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @copyright Copyright (c) Brian Nesbitt <brian@nesbot.com>
* @link http://cakephp.org CakePHP(tm) Project
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Cake\Chronos;
use DateTime;
use DateTimeZone;
use InvalidArgumentException;
/**
* A mutable datetime instance that implements the ChronosInterface.
*
* This object can be mutated in place using any setter method,
* or __set().
*
* @property-read int $year
* @property-read int $yearIso
* @property-read int $month
* @property-read int $day
* @property-read int $hour
* @property-read int $minute
* @property-read int $second
* @property-read int $micro
* @property-read int $microsecond
* @property-read int $timestamp seconds since the Unix Epoch
* @property-read \DateTimeZone|string $timezone the current timezone
* @property-read \DateTimeZone|string $tz alias of timezone
* @property-read int $dayOfWeek 1 (for Monday) through 7 (for Sunday)
* @property-read int $dayOfYear 0 through 365
* @property-read int $weekOfMonth 1 through 5
* @property-read int $weekOfYear ISO-8601 week number of year, weeks starting on Monday
* @property-read int $daysInMonth number of days in the given month
* @property-read int $age does a diffInYears() with default parameters
* @property-read int $quarter the quarter of this instance, 1 - 4
* @property-read int $offset the timezone offset in seconds from UTC
* @property-read int $offsetHours the timezone offset in hours from UTC
* @property-read bool $dst daylight savings time indicator, true if DST, false otherwise
* @property-read bool $local checks if the timezone is local, true if local, false otherwise
* @property-read bool $utc checks if the timezone is UTC, true if UTC, false otherwise
* @property-read string $timezoneName
* @property-read string $tzName
*/
class MutableDateTime extends DateTime implements ChronosInterface
{
use Traits\ComparisonTrait;
use Traits\DifferenceTrait;
use Traits\FactoryTrait;
use Traits\FormattingTrait;
use Traits\MagicPropertyTrait;
use Traits\ModifierTrait;
use Traits\RelativeKeywordTrait;
use Traits\TestingAidTrait;
use Traits\TimezoneTrait;
/**
* Format to use for __toString method when type juggling occurs.
*
* @var string
*/
protected static $toStringFormat = ChronosInterface::DEFAULT_TO_STRING_FORMAT;
/**
* Create a new MutableDateTime instance.
*
* Please see the testing aids section (specifically static::setTestNow())
* for more on the possibility of this constructor returning a test instance.
*
* @param \DateTimeInterface|string|int|null $time Fixed or relative time
* @param \DateTimeZone|string|null $tz The timezone for the instance
*/
public function __construct($time = 'now', $tz = null)
{
if (is_int($time)) {
parent::__construct('@' . $time);
return;
}
if ($tz !== null) {
$tz = $tz instanceof DateTimeZone ? $tz : new DateTimeZone($tz);
}
if ($time instanceof \DateTimeInterface) {
$time = $time->format('Y-m-d H:i:s.u');
}
$testNow = Chronos::getTestNow();
if ($testNow === null) {
parent::__construct($time ?? 'now', $tz);
return;
}
$relative = static::hasRelativeKeywords($time);
if (!empty($time) && $time !== 'now' && !$relative) {
parent::__construct($time, $tz);
return;
}
$testNow = clone $testNow;
$relativetime = static::isTimeExpression($time);
if (!$relativetime && $tz !== $testNow->getTimezone()) {
$testNow = $testNow->setTimezone($tz ?? date_default_timezone_get());
}
if ($relative) {
$testNow = $testNow->modify($time);
}
$time = $testNow->format('Y-m-d H:i:s.u');
parent::__construct($time, $tz);
}
/**
* Create a new immutable instance from current mutable instance.
*
* @return \Cake\Chronos\Chronos
*/
public function toImmutable(): Chronos
{
return Chronos::instance($this);
}
/**
* Set a part of the ChronosInterface object
*
* @param string $name The property to set.
* @param string|int|\DateTimeZone $value The value to set.
* @throws \InvalidArgumentException
* @return void
*/
public function __set(string $name, $value): void
{
switch ($name) {
case 'year':
$this->year($value);
break;
case 'month':
$this->month($value);
break;
case 'day':
$this->day($value);
break;
case 'hour':
$this->hour($value);
break;
case 'minute':
$this->minute($value);
break;
case 'second':
$this->second($value);
break;
case 'timestamp':
$this->timestamp($value);
break;
case 'timezone':
case 'tz':
$this->timezone($value);
break;
default:
throw new InvalidArgumentException(sprintf("Unknown setter '%s'", $name));
}
}
/**
* Return properties for debugging.
*
* @return array
*/
public function __debugInfo(): array
{
$properties = [
'hasFixedNow' => static::hasTestNow(),
'time' => $this->format('Y-m-d H:i:s.u'),
'timezone' => $this->getTimezone()->getName(),
];
return $properties;
}
}

View File

@@ -1,565 +0,0 @@
<?php
declare(strict_types=1);
/**
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @copyright Copyright (c) Brian Nesbitt <brian@nesbot.com>
* @link http://cakephp.org CakePHP(tm) Project
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Cake\Chronos\Traits;
use Cake\Chronos\ChronosInterface;
use DateTime;
/**
* Provides various comparison operator methods for datetime objects.
*/
trait ComparisonTrait
{
use CopyTrait;
/**
* Days of weekend
*
* @var array
*/
protected static $weekendDays = [ChronosInterface::SATURDAY, ChronosInterface::SUNDAY];
/**
* Get weekend days
*
* @return array
*/
public static function getWeekendDays(): array
{
return static::$weekendDays;
}
/**
* Set weekend days
*
* @param array $days Which days are 'weekends'.
* @return void
*/
public static function setWeekendDays(array $days): void
{
static::$weekendDays = $days;
}
/**
* Determines if the instance is equal to another
*
* @param \Cake\Chronos\ChronosInterface $dt The instance to compare with.
* @return bool
*/
public function eq(ChronosInterface $dt): bool
{
return $this == $dt;
}
/**
* Determines if the instance is equal to another
*
* @param \Cake\Chronos\ChronosInterface $dt The instance to compare with.
* @return bool
*/
public function equals(ChronosInterface $dt)
{
return $this->eq($dt);
}
/**
* Determines if the instance is not equal to another
*
* @param \Cake\Chronos\ChronosInterface $dt The instance to compare with.
* @return bool
*/
public function ne(ChronosInterface $dt): bool
{
return !$this->eq($dt);
}
/**
* Determines if the instance is not equal to another
*
* @param \Cake\Chronos\ChronosInterface $dt The instance to compare with.
* @return bool
*/
public function notEquals(ChronosInterface $dt)
{
return $this->ne($dt);
}
/**
* Determines if the instance is greater (after) than another
*
* @param \Cake\Chronos\ChronosInterface $dt The instance to compare with.
* @return bool
*/
public function gt(ChronosInterface $dt): bool
{
return $this > $dt;
}
/**
* Determines if the instance is greater (after) than another
*
* @param \Cake\Chronos\ChronosInterface $dt The instance to compare with.
* @return bool
*/
public function greaterThan(ChronosInterface $dt)
{
return $this->gt($dt);
}
/**
* Determines if the instance is greater (after) than or equal to another
*
* @param \Cake\Chronos\ChronosInterface $dt The instance to compare with.
* @return bool
*/
public function gte(ChronosInterface $dt): bool
{
return $this >= $dt;
}
/**
* Determines if the instance is greater (after) than or equal to another
*
* @param \Cake\Chronos\ChronosInterface $dt The instance to compare with.
* @return bool
*/
public function greaterThanOrEquals(ChronosInterface $dt)
{
return $this->gte($dt);
}
/**
* Determines if the instance is less (before) than another
*
* @param \Cake\Chronos\ChronosInterface $dt The instance to compare with.
* @return bool
*/
public function lt(ChronosInterface $dt): bool
{
return $this < $dt;
}
/**
* Determines if the instance is less (before) than another
*
* @param \Cake\Chronos\ChronosInterface $dt The instance to compare with.
* @return bool
*/
public function lessThan(ChronosInterface $dt)
{
return $this->lt($dt);
}
/**
* Determines if the instance is less (before) or equal to another
*
* @param \Cake\Chronos\ChronosInterface $dt The instance to compare with.
* @return bool
*/
public function lte(ChronosInterface $dt): bool
{
return $this <= $dt;
}
/**
* Determines if the instance is less (before) or equal to another
*
* @param \Cake\Chronos\ChronosInterface $dt The instance to compare with.
* @return bool
*/
public function lessThanOrEquals(ChronosInterface $dt)
{
return $this->lte($dt);
}
/**
* Determines if the instance is between two others
*
* @param \Cake\Chronos\ChronosInterface $dt1 The instance to compare with.
* @param \Cake\Chronos\ChronosInterface $dt2 The instance to compare with.
* @param bool $equal Indicates if a > and < comparison should be used or <= or >=
* @return bool
*/
public function between(ChronosInterface $dt1, ChronosInterface $dt2, bool $equal = true): bool
{
if ($dt1->gt($dt2)) {
$temp = $dt1;
$dt1 = $dt2;
$dt2 = $temp;
}
if ($equal) {
return $this->gte($dt1) && $this->lte($dt2);
}
return $this->gt($dt1) && $this->lt($dt2);
}
/**
* Get the closest date from the instance.
*
* @param \Cake\Chronos\ChronosInterface $dt1 The instance to compare with.
* @param \Cake\Chronos\ChronosInterface $dt2 The instance to compare with.
* @return \Cake\Chronos\ChronosInterface
*/
public function closest(ChronosInterface $dt1, ChronosInterface $dt2): ChronosInterface
{
return $this->diffInSeconds($dt1) < $this->diffInSeconds($dt2) ? $dt1 : $dt2;
}
/**
* Get the farthest date from the instance.
*
* @param \Cake\Chronos\ChronosInterface $dt1 The instance to compare with.
* @param \Cake\Chronos\ChronosInterface $dt2 The instance to compare with.
* @return \Cake\Chronos\ChronosInterface
*/
public function farthest(ChronosInterface $dt1, ChronosInterface $dt2): ChronosInterface
{
return $this->diffInSeconds($dt1) > $this->diffInSeconds($dt2) ? $dt1 : $dt2;
}
/**
* Get the minimum instance between a given instance (default now) and the current instance.
*
* @param \Cake\Chronos\ChronosInterface|null $dt The instance to compare with.
* @return \Cake\Chronos\ChronosInterface
*/
public function min(?ChronosInterface $dt = null): ChronosInterface
{
$dt = $dt ?? static::now($this->tz);
return $this->lt($dt) ? $this : $dt;
}
/**
* Get the maximum instance between a given instance (default now) and the current instance.
*
* @param \Cake\Chronos\ChronosInterface|null $dt The instance to compare with.
* @return \Cake\Chronos\ChronosInterface
*/
public function max(?ChronosInterface $dt = null): ChronosInterface
{
$dt = $dt ?? static::now($this->tz);
return $this->gt($dt) ? $this : $dt;
}
/**
* Determines if the instance is a weekday
*
* @return bool
*/
public function isWeekday(): bool
{
return !$this->isWeekend();
}
/**
* Determines if the instance is a weekend day
*
* @return bool
*/
public function isWeekend(): bool
{
return in_array($this->dayOfWeek, self::$weekendDays, true);
}
/**
* Determines if the instance is yesterday
*
* @return bool
*/
public function isYesterday(): bool
{
return $this->toDateString() === static::yesterday($this->tz)->toDateString();
}
/**
* Determines if the instance is today
*
* @return bool
*/
public function isToday(): bool
{
return $this->toDateString() === static::now($this->tz)->toDateString();
}
/**
* Determines if the instance is tomorrow
*
* @return bool
*/
public function isTomorrow(): bool
{
return $this->toDateString() === static::tomorrow($this->tz)->toDateString();
}
/**
* Determines if the instance is within the next week
*
* @return bool
*/
public function isNextWeek(): bool
{
return $this->format('W o') === static::now($this->tz)->addWeek()->format('W o');
}
/**
* Determines if the instance is within the last week
*
* @return bool
*/
public function isLastWeek(): bool
{
return $this->format('W o') === static::now($this->tz)->subWeek()->format('W o');
}
/**
* Determines if the instance is within the next month
*
* @return bool
*/
public function isNextMonth(): bool
{
return $this->format('m Y') === static::now($this->tz)->addMonth()->format('m Y');
}
/**
* Determines if the instance is within the last month
*
* @return bool
*/
public function isLastMonth(): bool
{
return $this->format('m Y') === static::now($this->tz)->subMonth()->format('m Y');
}
/**
* Determines if the instance is within the next year
*
* @return bool
*/
public function isNextYear(): bool
{
return $this->year === static::now($this->tz)->addYear()->year;
}
/**
* Determines if the instance is within the last year
*
* @return bool
*/
public function isLastYear(): bool
{
return $this->year === static::now($this->tz)->subYear()->year;
}
/**
* Determines if the instance is in the future, ie. greater (after) than now
*
* @return bool
*/
public function isFuture(): bool
{
return $this->gt(static::now($this->tz));
}
/**
* Determines if the instance is in the past, ie. less (before) than now
*
* @return bool
*/
public function isPast(): bool
{
return $this->lt(static::now($this->tz));
}
/**
* Determines if the instance is a leap year
*
* @return bool
*/
public function isLeapYear(): bool
{
return $this->format('L') === '1';
}
/**
* Checks if the passed in date is the same day as the instance current day.
*
* @param \Cake\Chronos\ChronosInterface $dt The instance to check against.
* @return bool
*/
public function isSameDay(ChronosInterface $dt): bool
{
return $this->toDateString() === $dt->toDateString();
}
/**
* Checks if this day is a Sunday.
*
* @return bool
*/
public function isSunday(): bool
{
return $this->dayOfWeek === ChronosInterface::SUNDAY;
}
/**
* Checks if this day is a Monday.
*
* @return bool
*/
public function isMonday(): bool
{
return $this->dayOfWeek === ChronosInterface::MONDAY;
}
/**
* Checks if this day is a Tuesday.
*
* @return bool
*/
public function isTuesday(): bool
{
return $this->dayOfWeek === ChronosInterface::TUESDAY;
}
/**
* Checks if this day is a Wednesday.
*
* @return bool
*/
public function isWednesday(): bool
{
return $this->dayOfWeek === ChronosInterface::WEDNESDAY;
}
/**
* Checks if this day is a Thursday.
*
* @return bool
*/
public function isThursday(): bool
{
return $this->dayOfWeek === ChronosInterface::THURSDAY;
}
/**
* Checks if this day is a Friday.
*
* @return bool
*/
public function isFriday(): bool
{
return $this->dayOfWeek === ChronosInterface::FRIDAY;
}
/**
* Checks if this day is a Saturday.
*
* @return bool
*/
public function isSaturday(): bool
{
return $this->dayOfWeek === ChronosInterface::SATURDAY;
}
/**
* Returns true if this object represents a date within the current week
*
* @return bool
*/
public function isThisWeek(): bool
{
return static::now($this->getTimezone())->format('W o') === $this->format('W o');
}
/**
* Returns true if this object represents a date within the current month
*
* @return bool
*/
public function isThisMonth(): bool
{
return static::now($this->getTimezone())->format('m Y') === $this->format('m Y');
}
/**
* Returns true if this object represents a date within the current year
*
* @return bool
*/
public function isThisYear(): bool
{
return static::now($this->getTimezone())->format('Y') === $this->format('Y');
}
/**
* Check if its the birthday. Compares the date/month values of the two dates.
*
* @param \Cake\Chronos\ChronosInterface|null $dt The instance to compare with or null to use current day.
* @return bool
*/
public function isBirthday(?ChronosInterface $dt = null): bool
{
$dt = $dt ?? static::now($this->tz);
return $this->format('md') === $dt->format('md');
}
/**
* Returns true this instance happened within the specified interval
*
* @param string|int $timeInterval the numeric value with space then time type.
* Example of valid types: 6 hours, 2 days, 1 minute.
* @return bool
*/
public function wasWithinLast($timeInterval): bool
{
$now = new static();
$interval = $now->copy()->modify('-' . $timeInterval);
$thisTime = $this->format('U');
return $thisTime >= $interval->format('U') && $thisTime <= $now->format('U');
}
/**
* Returns true this instance will happen within the specified interval
*
* @param string|int $timeInterval the numeric value with space then time type.
* Example of valid types: 6 hours, 2 days, 1 minute.
* @return bool
*/
public function isWithinNext($timeInterval): bool
{
$now = new static();
$interval = $now->copy()->modify('+' . $timeInterval);
$thisTime = $this->format('U');
return $thisTime <= $interval->format('U') && $thisTime >= $now->format('U');
}
/**
* Check if instance of ChronosInterface is mutable.
*
* @return bool
*/
public function isMutable(): bool
{
return $this instanceof DateTime;
}
}

View File

@@ -1,35 +0,0 @@
<?php
declare(strict_types=1);
/**
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @copyright Copyright (c) Brian Nesbitt <brian@nesbot.com>
* @link http://cakephp.org CakePHP(tm) Project
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Cake\Chronos\Traits;
use Cake\Chronos\ChronosInterface;
/**
* Provides methods for copying datetime objects.
*
* Expects that implementing classes provide a static `instance()` method.
*/
trait CopyTrait
{
/**
* Get a copy of the instance
*
* @return static
*/
public function copy(): ChronosInterface
{
return static::instance($this);
}
}

View File

@@ -1,332 +0,0 @@
<?php
declare(strict_types=1);
/**
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @copyright Copyright (c) Brian Nesbitt <brian@nesbot.com>
* @link http://cakephp.org CakePHP(tm) Project
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Cake\Chronos\Traits;
use Cake\Chronos\ChronosInterface;
use Cake\Chronos\ChronosInterval;
use Cake\Chronos\DifferenceFormatter;
use Cake\Chronos\DifferenceFormatterInterface;
use DatePeriod;
use DateTimeInterface;
use DateTimeZone;
/**
* Provides methods for getting differences between datetime objects.
*
* Expects that the implementing class implements:
*
* - static::now()
* - static::instance()
* - copy()
*/
trait DifferenceTrait
{
/**
* Instance of the diff formatting object.
*
* @var \Cake\Chronos\DifferenceFormatterInterface
*/
protected static $diffFormatter;
/**
* Get the difference in years
*
* @param \Cake\Chronos\ChronosInterface|null $dt The instance to difference from.
* @param bool $abs Get the absolute of the difference
* @return int
*/
public function diffInYears(?ChronosInterface $dt = null, bool $abs = true): int
{
$diff = $this->diff($dt ?? static::now($this->tz), $abs);
return $diff->invert ? -$diff->y : $diff->y;
}
/**
* Get the difference in months
*
* @param \Cake\Chronos\ChronosInterface|null $dt The instance to difference from.
* @param bool $abs Get the absolute of the difference
* @return int
*/
public function diffInMonths(?ChronosInterface $dt = null, bool $abs = true): int
{
$diff = $this->diff($dt ?? static::now($this->tz), $abs);
$months = $diff->y * ChronosInterface::MONTHS_PER_YEAR + $diff->m;
return $diff->invert ? -$months : $months;
}
/**
* Get the difference in months ignoring the timezone. This means the months are calculated
* in the specified timezone without converting to UTC first. This prevents the day from changing
* which can change the month.
*
* For example, if comparing `2019-06-01 Asia/Tokyo` and `2019-10-01 Asia/Tokyo`,
* the result would be 4 months instead of 3 when using normal `DateTime::diff()`.
*
* @param \Cake\Chronos\ChronosInterface|null $dt The instance to difference from.
* @param bool $abs Get the absolute of the difference
* @return int
*/
public function diffInMonthsIgnoreTimezone(?ChronosInterface $dt = null, bool $abs = true): int
{
$utcTz = new DateTimeZone('UTC');
$source = new static($this->format('Y-m-d H:i:s.u'), $utcTz);
$dt = $dt ?? static::now($this->tz);
$dt = new static($dt->format('Y-m-d H:i:s.u'), $utcTz);
return $source->diffInMonths($dt, $abs);
}
/**
* Get the difference in weeks
*
* @param \Cake\Chronos\ChronosInterface|null $dt The instance to difference from.
* @param bool $abs Get the absolute of the difference
* @return int
*/
public function diffInWeeks(?ChronosInterface $dt = null, bool $abs = true): int
{
return (int)($this->diffInDays($dt, $abs) / ChronosInterface::DAYS_PER_WEEK);
}
/**
* Get the difference in days
*
* @param \Cake\Chronos\ChronosInterface|null $dt The instance to difference from.
* @param bool $abs Get the absolute of the difference
* @return int
*/
public function diffInDays(?ChronosInterface $dt = null, bool $abs = true): int
{
$diff = $this->diff($dt ?? static::now($this->tz), $abs);
return $diff->invert ? -$diff->days : $diff->days;
}
/**
* Get the difference in days using a filter callable
*
* @param callable $callback The callback to use for filtering.
* @param \Cake\Chronos\ChronosInterface|null $dt The instance to difference from.
* @param bool $abs Get the absolute of the difference
* @return int
*/
public function diffInDaysFiltered(callable $callback, ?ChronosInterface $dt = null, bool $abs = true): int
{
return $this->diffFiltered(ChronosInterval::day(), $callback, $dt, $abs);
}
/**
* Get the difference in hours using a filter callable
*
* @param callable $callback The callback to use for filtering.
* @param \Cake\Chronos\ChronosInterface|null $dt The instance to difference from.
* @param bool $abs Get the absolute of the difference
* @return int
*/
public function diffInHoursFiltered(callable $callback, ?ChronosInterface $dt = null, bool $abs = true): int
{
return $this->diffFiltered(ChronosInterval::hour(), $callback, $dt, $abs);
}
/**
* Get the difference by the given interval using a filter callable
*
* @param \Cake\Chronos\ChronosInterval $ci An interval to traverse by
* @param callable $callback The callback to use for filtering.
* @param \Cake\Chronos\ChronosInterface|null $dt The instance to difference from.
* @param bool $abs Get the absolute of the difference
* @return int
*/
public function diffFiltered(
ChronosInterval $ci,
callable $callback,
?ChronosInterface $dt = null,
bool $abs = true
): int {
$start = $this;
$end = $dt ?? static::now($this->tz);
$inverse = false;
if ($end < $start) {
$start = $end;
$end = $this;
$inverse = true;
}
$period = new DatePeriod($start, $ci, $end);
$vals = array_filter(iterator_to_array($period), function (DateTimeInterface $date) use ($callback) {
return $callback(static::instance($date));
});
$diff = count($vals);
return $inverse && !$abs ? -$diff : $diff;
}
/**
* Get the difference in weekdays
*
* @param \Cake\Chronos\ChronosInterface|null $dt The instance to difference from.
* @param bool $abs Get the absolute of the difference
* @return int
*/
public function diffInWeekdays(?ChronosInterface $dt = null, bool $abs = true): int
{
return $this->diffInDaysFiltered(function (ChronosInterface $date) {
return $date->isWeekday();
}, $dt, $abs);
}
/**
* Get the difference in weekend days using a filter
*
* @param \Cake\Chronos\ChronosInterface|null $dt The instance to difference from.
* @param bool $abs Get the absolute of the difference
* @return int
*/
public function diffInWeekendDays(?ChronosInterface $dt = null, bool $abs = true): int
{
return $this->diffInDaysFiltered(function (ChronosInterface $date) {
return $date->isWeekend();
}, $dt, $abs);
}
/**
* Get the difference in hours
*
* @param \Cake\Chronos\ChronosInterface|null $dt The instance to difference from.
* @param bool $abs Get the absolute of the difference
* @return int
*/
public function diffInHours(?ChronosInterface $dt = null, bool $abs = true): int
{
return (int)(
$this->diffInSeconds($dt, $abs)
/ ChronosInterface::SECONDS_PER_MINUTE
/ ChronosInterface::MINUTES_PER_HOUR
);
}
/**
* Get the difference in minutes
*
* @param \Cake\Chronos\ChronosInterface|null $dt The instance to difference from.
* @param bool $abs Get the absolute of the difference
* @return int
*/
public function diffInMinutes(?ChronosInterface $dt = null, bool $abs = true): int
{
return (int)($this->diffInSeconds($dt, $abs) / ChronosInterface::SECONDS_PER_MINUTE);
}
/**
* Get the difference in seconds
*
* @param \Cake\Chronos\ChronosInterface|null $dt The instance to difference from.
* @param bool $abs Get the absolute of the difference
* @return int
*/
public function diffInSeconds(?ChronosInterface $dt = null, bool $abs = true): int
{
$dt = $dt ?? static::now($this->tz);
$value = $dt->getTimestamp() - $this->getTimestamp();
return $abs ? abs($value) : $value;
}
/**
* The number of seconds since midnight.
*
* @return int
*/
public function secondsSinceMidnight(): int
{
return $this->diffInSeconds($this->copy()->startOfDay());
}
/**
* The number of seconds until 23:59:59.
*
* @return int
*/
public function secondsUntilEndOfDay(): int
{
return $this->diffInSeconds($this->copy()->endOfDay());
}
/**
* Convenience method for getting the remaining time from a given time.
*
* @param \DateTime|\DateTimeImmutable $datetime The date to get the remaining time from.
* @return \DateInterval|bool The DateInterval object representing the difference between the two dates or FALSE on failure.
*/
public static function fromNow($datetime)
{
$timeNow = new static();
return $timeNow->diff($datetime);
}
/**
* Get the difference in a human readable format.
*
* When comparing a value in the past to default now:
* 1 hour ago
* 5 months ago
*
* When comparing a value in the future to default now:
* 1 hour from now
* 5 months from now
*
* When comparing a value in the past to another value:
* 1 hour before
* 5 months before
*
* When comparing a value in the future to another value:
* 1 hour after
* 5 months after
*
* @param \Cake\Chronos\ChronosInterface|null $other The datetime to compare with.
* @param bool $absolute removes time difference modifiers ago, after, etc
* @return string
*/
public function diffForHumans(?ChronosInterface $other = null, bool $absolute = false): string
{
return static::diffFormatter()->diffForHumans($this, $other, $absolute);
}
/**
* Get the difference formatter instance or overwrite the current one.
*
* @param \Cake\Chronos\DifferenceFormatterInterface|null $formatter The formatter instance when setting.
* @return \Cake\Chronos\DifferenceFormatterInterface The formatter instance.
*/
public static function diffFormatter(?DifferenceFormatterInterface $formatter = null): DifferenceFormatterInterface
{
if ($formatter === null) {
if (static::$diffFormatter === null) {
static::$diffFormatter = new DifferenceFormatter();
}
return static::$diffFormatter;
}
return static::$diffFormatter = $formatter;
}
}

View File

@@ -1,364 +0,0 @@
<?php
declare(strict_types=1);
/**
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @copyright Copyright (c) Brian Nesbitt <brian@nesbot.com>
* @link http://cakephp.org CakePHP(tm) Project
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Cake\Chronos\Traits;
use Cake\Chronos\ChronosInterface;
use DateTimeInterface;
use DateTimeZone;
use InvalidArgumentException;
/**
* Provides a number of datetime related factory methods.
*/
trait FactoryTrait
{
/**
* Holds the last error generated by createFromFormat
*
* @var array
*/
protected static $_lastErrors = [];
/**
* Create a ChronosInterface instance from a DateTimeInterface one
*
* @param \DateTimeInterface $dt The datetime instance to convert.
* @return static
*/
public static function instance(DateTimeInterface $dt): ChronosInterface
{
if ($dt instanceof static) {
return clone $dt;
}
return new static($dt->format('Y-m-d H:i:s.u'), $dt->getTimezone());
}
/**
* Create a ChronosInterface instance from a string. This is an alias for the
* constructor that allows better fluent syntax as it allows you to do
* ChronosInterface::parse('Monday next week')->fn() rather than
* (new Chronos('Monday next week'))->fn()
*
* @param \DateTimeInterface|string|int $time The strtotime compatible string to parse
* @param \DateTimeZone|string|null $tz The DateTimeZone object or timezone name.
* @return static
*/
public static function parse($time = 'now', $tz = null): ChronosInterface
{
return new static($time, $tz);
}
/**
* Get a ChronosInterface instance for the current date and time
*
* @param \DateTimeZone|string|null $tz The DateTimeZone object or timezone name.
* @return static
*/
public static function now($tz = null): ChronosInterface
{
return new static('now', $tz);
}
/**
* Create a ChronosInterface instance for today
*
* @param \DateTimeZone|string|null $tz The timezone to use.
* @return static
*/
public static function today($tz = null): ChronosInterface
{
return new static('midnight', $tz);
}
/**
* Create a ChronosInterface instance for tomorrow
*
* @param \DateTimeZone|string|null $tz The DateTimeZone object or timezone name the new instance should use.
* @return static
*/
public static function tomorrow($tz = null): ChronosInterface
{
return new static('tomorrow, midnight', $tz);
}
/**
* Create a ChronosInterface instance for yesterday
*
* @param \DateTimeZone|string|null $tz The DateTimeZone object or timezone name the new instance should use.
* @return static
*/
public static function yesterday($tz = null): ChronosInterface
{
return new static('yesterday, midnight', $tz);
}
/**
* Create a ChronosInterface instance for the greatest supported date.
*
* @return \Cake\Chronos\ChronosInterface
*/
public static function maxValue(): ChronosInterface
{
return static::createFromTimestampUTC(PHP_INT_MAX);
}
/**
* Create a ChronosInterface instance for the lowest supported date.
*
* @return \Cake\Chronos\ChronosInterface
*/
public static function minValue(): ChronosInterface
{
$max = PHP_INT_SIZE === 4 ? PHP_INT_MAX : PHP_INT_MAX / 10;
return static::createFromTimestampUTC(~$max);
}
/**
* Create a new ChronosInterface instance from a specific date and time.
*
* If any of $year, $month or $day are set to null their now() values
* will be used.
*
* If $hour is null it will be set to its now() value and the default values
* for $minute, $second and $microsecond will be their now() values.
* If $hour is not null then the default values for $minute, $second
* and $microsecond will be 0.
*
* @param int|null $year The year to create an instance with.
* @param int|null $month The month to create an instance with.
* @param int|null $day The day to create an instance with.
* @param int|null $hour The hour to create an instance with.
* @param int|null $minute The minute to create an instance with.
* @param int|null $second The second to create an instance with.
* @param int|null $microsecond The microsecond to create an instance with.
* @param \DateTimeZone|string|null $tz The DateTimeZone object or timezone name the new instance should use.
* @return static
*/
public static function create(
?int $year = null,
?int $month = null,
?int $day = null,
?int $hour = null,
?int $minute = null,
?int $second = null,
?int $microsecond = null,
$tz = null
): ChronosInterface {
$now = static::now();
$year = $year ?? (int)$now->format('Y');
$month = $month ?? $now->format('m');
$day = $day ?? $now->format('d');
if ($hour === null) {
$hour = $now->format('H');
$minute = $minute ?? $now->format('i');
$second = $second ?? $now->format('s');
$microsecond = $microsecond ?? $now->format('u');
} else {
$minute = $minute ?? 0;
$second = $second ?? 0;
$microsecond = $microsecond ?? 0;
}
$instance = static::createFromFormat(
'Y-m-d H:i:s.u',
sprintf('%s-%s-%s %s:%02s:%02s.%06s', 0, $month, $day, $hour, $minute, $second, $microsecond),
$tz
);
return $instance->addYears($year);
}
/**
* Create a ChronosInterface instance from just a date. The time portion is set to now.
*
* @param int|null $year The year to create an instance with.
* @param int|null $month The month to create an instance with.
* @param int|null $day The day to create an instance with.
* @param \DateTimeZone|string|null $tz The DateTimeZone object or timezone name the new instance should use.
* @return static
*/
public static function createFromDate(
?int $year = null,
?int $month = null,
?int $day = null,
$tz = null
): ChronosInterface {
return static::create($year, $month, $day, null, null, null, null, $tz);
}
/**
* Create a ChronosInterface instance from just a time. The date portion is set to today.
*
* @param int|null $hour The hour to create an instance with.
* @param int|null $minute The minute to create an instance with.
* @param int|null $second The second to create an instance with.
* @param int|null $microsecond The microsecond to create an instance with.
* @param \DateTimeZone|string|null $tz The DateTimeZone object or timezone name the new instance should use.
* @return static
*/
public static function createFromTime(
?int $hour = null,
?int $minute = null,
?int $second = null,
?int $microsecond = null,
$tz = null
): ChronosInterface {
return static::create(null, null, null, $hour, $minute, $second, $microsecond, $tz);
}
/**
* Create a ChronosInterface instance from a specific format
*
* @param string $format The date() compatible format string.
* @param string $time The formatted date string to interpret.
* @param \DateTimeZone|string|null $tz The DateTimeZone object or timezone name the new instance should use.
* @return static
* @throws \InvalidArgumentException
*/
public static function createFromFormat($format, $time, $tz = null): ChronosInterface
{
if ($tz !== null) {
$dt = parent::createFromFormat($format, $time, static::safeCreateDateTimeZone($tz));
} else {
$dt = parent::createFromFormat($format, $time);
}
$errors = parent::getLastErrors();
if (!$dt) {
throw new InvalidArgumentException(implode(PHP_EOL, $errors['errors']));
}
$dt = new static($dt->format('Y-m-d H:i:s.u'), $dt->getTimezone());
static::$_lastErrors = $errors;
return $dt;
}
/**
* Creates a ChronosInterface instance from an array of date and time values.
*
* The 'year', 'month' and 'day' values must all be set for a date. The time
* values all default to 0.
*
* The 'timezone' value can be any format supported by `\DateTimeZone`.
*
* Allowed values:
* - year
* - month
* - day
* - hour
* - minute
* - second
* - microsecond
* - meridian ('am' or 'pm')
* - timezone
*
* @param (int|string)[] $values Array of date and time values.
* @return static
*/
public static function createFromArray(array $values): ChronosInterface
{
$values += ['hour' => 0, 'minute' => 0, 'second' => 0, 'microsecond' => 0, 'timezone' => null];
$formatted = '';
if (
isset($values['year'], $values['month'], $values['day']) &&
(
is_numeric($values['year']) &&
is_numeric($values['month']) &&
is_numeric($values['day'])
)
) {
$formatted .= sprintf('%04d-%02d-%02d ', $values['year'], $values['month'], $values['day']);
}
if (isset($values['meridian']) && (int)$values['hour'] === 12) {
$values['hour'] = 0;
}
if (isset($values['meridian'])) {
$values['hour'] = strtolower($values['meridian']) === 'am' ? $values['hour'] : $values['hour'] + 12;
}
$formatted .= sprintf(
'%02d:%02d:%02d.%06d',
$values['hour'],
$values['minute'],
$values['second'],
$values['microsecond']
);
return static::parse($formatted, $values['timezone']);
}
/**
* Create a ChronosInterface instance from a timestamp
*
* @param int $timestamp The timestamp to create an instance from.
* @param \DateTimeZone|string|null $tz The DateTimeZone object or timezone name the new instance should use.
* @return static
*/
public static function createFromTimestamp(int $timestamp, $tz = null): ChronosInterface
{
return static::now($tz)->setTimestamp($timestamp);
}
/**
* Create a ChronosInterface instance from an UTC timestamp
*
* @param int $timestamp The UTC timestamp to create an instance from.
* @return static
*/
public static function createFromTimestampUTC(int $timestamp): ChronosInterface
{
return new static($timestamp);
}
/**
* Creates a DateTimeZone from a string or a DateTimeZone
*
* @param \DateTimeZone|string|null $object The value to convert.
* @return \DateTimeZone
* @throws \InvalidArgumentException
*/
protected static function safeCreateDateTimeZone($object): DateTimeZone
{
if ($object === null) {
return new DateTimeZone(date_default_timezone_get());
}
if ($object instanceof DateTimeZone) {
return $object;
}
return new DateTimeZone($object);
}
/**
* Returns any errors or warnings that were found during the parsing
* of the last object created by this class.
*
* @return array
*/
public static function getLastErrors(): array
{
if (empty(static::$_lastErrors)) {
return parent::getLastErrors();
}
return static::$_lastErrors;
}
}

View File

@@ -1,267 +0,0 @@
<?php
declare(strict_types=1);
/**
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @copyright Copyright (c) Brian Nesbitt <brian@nesbot.com>
* @link http://cakephp.org CakePHP(tm) Project
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Cake\Chronos\Traits;
use Cake\Chronos\ChronosInterface;
use DateTime;
/**
* Provides string formatting methods for datetime instances.
*
* Expects implementing classes to define static::$toStringFormat
*/
trait FormattingTrait
{
/**
* Reset the format used to the default when type juggling a ChronosInterface instance to a string
*
* @return void
*/
public static function resetToStringFormat(): void
{
static::setToStringFormat(ChronosInterface::DEFAULT_TO_STRING_FORMAT);
}
/**
* Set the default format used when type juggling a ChronosInterface instance to a string
*
* @param string $format The format to use in future __toString() calls.
* @return void
*/
public static function setToStringFormat($format): void
{
static::$toStringFormat = $format;
}
/**
* Format the instance as a string using the set format
*
* @return string
*/
public function __toString(): string
{
return $this->format(static::$toStringFormat);
}
/**
* Format the instance as date
*
* @return string
*/
public function toDateString(): string
{
return $this->format('Y-m-d');
}
/**
* Format the instance as a readable date
*
* @return string
*/
public function toFormattedDateString(): string
{
return $this->format('M j, Y');
}
/**
* Format the instance as time
*
* @return string
*/
public function toTimeString(): string
{
return $this->format('H:i:s');
}
/**
* Format the instance as date and time
*
* @return string
*/
public function toDateTimeString(): string
{
return $this->format('Y-m-d H:i:s');
}
/**
* Format the instance with day, date and time
*
* @return string
*/
public function toDayDateTimeString(): string
{
return $this->format('D, M j, Y g:i A');
}
/**
* Format the instance as ATOM
*
* @return string
*/
public function toAtomString(): string
{
return $this->format(DateTime::ATOM);
}
/**
* Format the instance as COOKIE
*
* @return string
*/
public function toCookieString(): string
{
return $this->format(DateTime::COOKIE);
}
/**
* Format the instance as ISO8601
*
* @return string
*/
public function toIso8601String(): string
{
return $this->format(DateTime::ATOM);
}
/**
* Format the instance as RFC822
*
* @return string
* @link https://tools.ietf.org/html/rfc822
*/
public function toRfc822String(): string
{
return $this->format(DateTime::RFC822);
}
/**
* Format the instance as RFC850
*
* @return string
* @link https://tools.ietf.org/html/rfc850
*/
public function toRfc850String(): string
{
return $this->format(DateTime::RFC850);
}
/**
* Format the instance as RFC1036
*
* @return string
* @link https://tools.ietf.org/html/rfc1036
*/
public function toRfc1036String(): string
{
return $this->format(DateTime::RFC1036);
}
/**
* Format the instance as RFC1123
*
* @return string
* @link https://tools.ietf.org/html/rfc1123
*/
public function toRfc1123String(): string
{
return $this->format(DateTime::RFC1123);
}
/**
* Format the instance as RFC2822
*
* @return string
* @link https://tools.ietf.org/html/rfc2822
*/
public function toRfc2822String(): string
{
return $this->format(DateTime::RFC2822);
}
/**
* Format the instance as RFC3339
*
* @return string
* @link https://tools.ietf.org/html/rfc3339
*/
public function toRfc3339String(): string
{
return $this->format(DateTime::RFC3339);
}
/**
* Format the instance as RSS
*
* @return string
*/
public function toRssString(): string
{
return $this->format(DateTime::RSS);
}
/**
* Format the instance as W3C
*
* @return string
*/
public function toW3cString(): string
{
return $this->format(DateTime::W3C);
}
/**
* Returns a UNIX timestamp.
*
* @return string UNIX timestamp
*/
public function toUnixString(): string
{
return $this->format('U');
}
/**
* Returns the quarter
*
* @param bool $range Range.
* @return int|array 1, 2, 3, or 4 quarter of year or array if $range true
*/
public function toQuarter(bool $range = false)
{
$quarter = (int)ceil($this->format('m') / 3);
if ($range === false) {
return $quarter;
}
$year = $this->format('Y');
switch ($quarter) {
case 1:
return [$year . '-01-01', $year . '-03-31'];
case 2:
return [$year . '-04-01', $year . '-06-30'];
case 3:
return [$year . '-07-01', $year . '-09-30'];
default:
return [$year . '-10-01', $year . '-12-31'];
}
}
/**
* @inheritDoc
*/
public function toWeek(): int
{
return (int)$this->format('W');
}
}

View File

@@ -1,183 +0,0 @@
<?php
declare(strict_types=1);
/**
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Cake\Chronos\Traits;
use Cake\Chronos\ChronosInterface;
use DateTimeImmutable;
use DateTimeInterface;
/**
* A trait for freezing the time aspect of a DateTime.
*
* Used in making calendar date objects, both mutable and immutable.
*/
trait FrozenTimeTrait
{
use RelativeKeywordTrait;
/**
* Removes the time components from an input string.
*
* Used to ensure constructed objects always lack time.
*
* @param \DateTime|\DateTimeImmutable|string|int|null $time The input time. Integer values will be assumed
* to be in UTC. The 'now' and '' values will use the current local time.
* @param \DateTimeZone|null $tz The timezone in which the date is taken
* @return string The date component of $time.
*/
protected function stripTime($time, $tz): string
{
if (is_int($time)) {
return gmdate('Y-m-d 00:00:00', $time);
}
if (is_string($time) && substr($time, 0, 1) === '@') {
return gmdate('Y-m-d 00:00:00', (int)substr($time, 1));
}
if (!($time instanceof DateTimeInterface)) {
$time = new DateTimeImmutable($time ?? 'now', $tz);
}
return $time->format('Y-m-d 00:00:00');
}
/**
* Remove time components from strtotime relative strings.
*
* @param string $time The input expression
* @return string The output expression with no time modifiers.
*/
protected function stripRelativeTime(string $time): string
{
return preg_replace('/([-+]\s*\d+\s(?:minutes|seconds|hours|microseconds))/', '', $time);
}
/**
* Modify the time on the Date.
*
* This method ignores all inputs and forces all inputs to 0.
*
* @param int $hours The hours to set (ignored)
* @param int $minutes The minutes to set (ignored)
* @param int $seconds The seconds to set (ignored)
* @param int $microseconds The microseconds to set (ignored)
* @return static A modified Date instance.
*/
public function setTime($hours, $minutes, $seconds = null, $microseconds = null): ChronosInterface
{
return parent::setTime(0, 0, 0, 0);
}
/**
* Add an Interval to a Date
*
* Any changes to the time will be ignored and reset to 00:00:00
*
* @param \DateInterval $interval The interval to modify this date by.
* @return static A modified Date instance
*/
public function add($interval): ChronosInterface
{
return parent::add($interval)->setTime(0, 0, 0);
}
/**
* Subtract an Interval from a Date.
*
* Any changes to the time will be ignored and reset to 00:00:00
*
* @param \DateInterval $interval The interval to modify this date by.
* @return static A modified Date instance
*/
public function sub($interval): ChronosInterface
{
return parent::sub($interval)->setTime(0, 0, 0);
}
/**
* No-op method.
*
* Timezones have no effect on calendar dates.
*
* @param \DateTimeZone|string $value The DateTimeZone object or timezone name to use.
* @return $this
*/
public function timezone($value)
{
return $this;
}
/**
* No-op method.
*
* Timezones have no effect on calendar dates.
*
* @param \DateTimeZone|string $value The DateTimeZone object or timezone name to use.
* @return $this
*/
public function tz($value)
{
return $this;
}
/**
* No-op method.
*
* Timezones have no effect on calendar dates.
*
* @param \DateTimeZone|string $value The DateTimeZone object or timezone name to use.
* @return $this
*/
public function setTimezone($value)
{
return $this;
}
/**
* Set the timestamp value and get a new object back.
*
* This method will discard the time aspects of the timestamp
* and only apply the date portions
*
* @param int $value The timestamp value to set.
* @return static
*/
public function setTimestamp($value): ChronosInterface
{
return parent::setTimestamp($value)->setTime(0, 0, 0);
}
/**
* Overloaded to ignore time changes.
*
* Changing any aspect of the time will be ignored, and the resulting object
* will have its time frozen to 00:00:00.
*
* @param string $relative The relative change to make.
* @return static A new date with the applied date changes.
*/
public function modify($relative): ChronosInterface
{
if (preg_match('/hour|minute|second/', $relative)) {
return $this;
}
$new = parent::modify($relative);
if ($new->format('H:i:s') !== '00:00:00') {
return $new->setTime(0, 0, 0);
}
return $new;
}
}

View File

@@ -1,138 +0,0 @@
<?php
declare(strict_types=1);
/**
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice. Provides various operator methods for datetime
* objects.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @copyright Copyright (c) Brian Nesbitt <brian@nesbot.com>
* @link http://cakephp.org CakePHP(tm) Project
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Cake\Chronos\Traits;
use Cake\Chronos\ChronosInterface;
use InvalidArgumentException;
/**
* Provides the magic methods that allow read access
* to magic properties.
*
* @property-read int $year
* @property-read int $yearIso
* @property-read int $month
* @property-read int $day
* @property-read int $hour
* @property-read int $minute
* @property-read int $second
* @property-read int $micro
* @property-read int $dayOfWeek
* @property-read int $dayOfYear
* @property-read int $weekOfYear
* @property-read int $daysInMonth
* @property-read int $timestamp
* @property-read int $weekOfMonth
* @property-read int $age
* @property-read int $quarter
* @property-read int $offset
* @property-read int $offsetHours
* @property-read bool $dst
* @property-read bool $local
* @property-read bool $utc
* @property-read \DateTimeZone $timezone
* @property-read \DateTimeZone $tz
* @property-read string $timezoneName
* @property-read string $tzName
* @property-read string $dayOfWeekName
*/
trait MagicPropertyTrait
{
/**
* Get a part of the ChronosInterface object
*
* @param string $name The property name to read.
* @return string|int|bool|\DateTimeZone The property value.
* @throws \InvalidArgumentException
*/
public function __get(string $name)
{
static $formats = [
'year' => 'Y',
'yearIso' => 'o',
'month' => 'n',
'day' => 'j',
'hour' => 'G',
'minute' => 'i',
'second' => 's',
'micro' => 'u',
'microsecond' => 'u',
'dayOfWeek' => 'N',
'dayOfYear' => 'z',
'weekOfYear' => 'W',
'daysInMonth' => 't',
'timestamp' => 'U',
];
switch (true) {
case isset($formats[$name]):
return (int)$this->format($formats[$name]);
case $name === 'dayOfWeekName':
return $this->format('l');
case $name === 'weekOfMonth':
return (int)ceil($this->day / ChronosInterface::DAYS_PER_WEEK);
case $name === 'age':
return $this->diffInYears();
case $name === 'quarter':
return (int)ceil($this->month / 3);
case $name === 'offset':
return $this->getOffset();
case $name === 'offsetHours':
return $this->getOffset() / ChronosInterface::SECONDS_PER_MINUTE / ChronosInterface::MINUTES_PER_HOUR;
case $name === 'dst':
return $this->format('I') === '1';
case $name === 'local':
return $this->offset === $this->copy()->setTimezone(date_default_timezone_get())->offset;
case $name === 'utc':
return $this->offset === 0;
case $name === 'timezone' || $name === 'tz':
return $this->getTimezone();
case $name === 'timezoneName' || $name === 'tzName':
return $this->getTimezone()->getName();
default:
throw new InvalidArgumentException(sprintf("Unknown getter '%s'", $name));
}
}
/**
* Check if an attribute exists on the object
*
* @param string $name The property name to check.
* @return bool Whether or not the property exists.
*/
public function __isset(string $name): bool
{
try {
$this->__get($name);
} catch (InvalidArgumentException $e) {
return false;
}
return true;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,85 +0,0 @@
<?php
declare(strict_types=1);
/**
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice. Provides various operator methods for datetime
* objects.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @copyright Copyright (c) Brian Nesbitt <brian@nesbot.com>
* @link http://cakephp.org CakePHP(tm) Project
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Cake\Chronos\Traits;
/**
* Provides methods for testing if strings contain relative keywords.
*/
trait RelativeKeywordTrait
{
/**
* Regex for relative period.
*
* @var string
*/
protected static $relativePattern = '/this|next|last|tomorrow|yesterday|midnight|today|[+-]|first|last|ago/i';
/**
* Determine if there is just a time in the time string
*
* @param string $time The time string to check.
* @return bool true if there is a keyword, otherwise false
*/
private static function isTimeExpression($time)
{
// Just a time
if (is_string($time) && preg_match('/^[0-2]?[0-9]:[0-5][0-9](?::[0-5][0-9](?:\.[0-9]{1,6})?)?$/', $time)) {
return true;
}
return false;
}
/**
* Determine if there is a relative keyword in the time string, this is to
* create dates relative to now for test instances. e.g.: next tuesday
*
* @param string|null $time The time string to check.
* @return bool true if there is a keyword, otherwise false
*/
public static function hasRelativeKeywords(?string $time): bool
{
if (self::isTimeExpression($time)) {
return true;
}
// skip common format with a '-' in it
if ($time && preg_match('/[0-9]{4}-[0-9]{1,2}-[0-9]{1,2}/', $time) !== 1) {
return preg_match(static::$relativePattern, $time) > 0;
}
return false;
}
/**
* Determines if there is no fixed date in the time string.
*
* @param \DateTimeInterface|string|null $time The time string to check
* @return bool true if doesn't contain a fixed date
*/
private static function isRelativeOnly($time): bool
{
if ($time === null) {
return true;
}
if (!is_string($time)) {
return false;
}
// must not contain fixed date before relative keywords or time expression
return preg_match('/[0-9]{4}-[0-9]{1,2}-[0-9]{1,2}/', $time) !== 1;
}
}

View File

@@ -1,60 +0,0 @@
<?php
declare(strict_types=1);
/**
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice. Provides various operator methods for datetime
* objects.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @copyright Copyright (c) Brian Nesbitt <brian@nesbot.com>
* @link http://cakephp.org CakePHP(tm) Project
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Cake\Chronos\Traits;
use Cake\Chronos\Chronos;
use Cake\Chronos\ChronosInterface;
/**
* Provides methods for setting a 'test' now. This lets you
* retrieve pre-determined times with now().
*/
trait TestingAidTrait
{
/**
* Set the test now used by Date and Time classes provided by Chronos
*
* @see \Cake\Chronos\Chronos::setTestNow()
* @param \Cake\Chronos\ChronosInterface|string|null $testNow The instance to use for all future instances.
* @return void
*/
public static function setTestNow($testNow = null): void
{
Chronos::setTestNow($testNow);
}
/**
* Get the test instance stored in Chronos
*
* @see \Cake\Chronos\Chronos::getTestNow()
* @return \Cake\Chronos\ChronosInterface|null the current instance used for testing or null.
*/
public static function getTestNow(): ?ChronosInterface
{
return Chronos::getTestNow();
}
/**
* Get whether or not Chronos has a test instance set.
*
* @see \Cake\Chronos\Chronos::hasTestNow()
* @return bool True if there is a test instance, otherwise false
*/
public static function hasTestNow(): bool
{
return Chronos::hasTestNow();
}
}

View File

@@ -1,57 +0,0 @@
<?php
declare(strict_types=1);
/**
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice. Provides various operator methods for datetime
* objects.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @copyright Copyright (c) Brian Nesbitt <brian@nesbot.com>
* @link http://cakephp.org CakePHP(tm) Project
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Cake\Chronos\Traits;
use Cake\Chronos\ChronosInterface;
/**
* Methods for modifying/reading timezone data.
*/
trait TimezoneTrait
{
/**
* Alias for setTimezone()
*
* @param \DateTimeZone|string $value The DateTimeZone object or timezone name to use.
* @return static
*/
public function timezone($value): ChronosInterface
{
return $this->setTimezone($value);
}
/**
* Alias for setTimezone()
*
* @param \DateTimeZone|string $value The DateTimeZone object or timezone name to use.
* @return static
*/
public function tz($value): ChronosInterface
{
return $this->setTimezone($value);
}
/**
* Set the instance's timezone from a string or object
*
* @param \DateTimeZone|string $value The DateTimeZone object or timezone name to use.
* @return static
*/
public function setTimezone($value): ChronosInterface
{
return parent::setTimezone(static::safeCreateDateTimeZone($value));
}
}

View File

@@ -1,95 +0,0 @@
<?php
declare(strict_types=1);
/**
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Cake\Chronos;
/**
* Basic english only 'translator' for diffForHumans()
*/
class Translator
{
/**
* Translation strings.
*
* @var array
*/
public static $strings = [
'year' => '1 year',
'year_plural' => '{count} years',
'month' => '1 month',
'month_plural' => '{count} months',
'week' => '1 week',
'week_plural' => '{count} weeks',
'day' => '1 day',
'day_plural' => '{count} days',
'hour' => '1 hour',
'hour_plural' => '{count} hours',
'minute' => '1 minute',
'minute_plural' => '{count} minutes',
'second' => '1 second',
'second_plural' => '{count} seconds',
'ago' => '{time} ago',
'from_now' => '{time} from now',
'after' => '{time} after',
'before' => '{time} before',
];
/**
* Check if a translation key exists.
*
* @param string $key The key to check.
* @return bool Whether or not the key exists.
*/
public function exists(string $key): bool
{
return isset(static::$strings[$key]);
}
/**
* Get a plural message.
*
* @param string $key The key to use.
* @param int $count The number of items in the translation.
* @param array $vars Additional context variables.
* @return string The translated message or ''.
*/
public function plural(string $key, int $count, array $vars = []): string
{
if ($count === 1) {
return $this->singular($key, $vars);
}
return $this->singular($key . '_plural', ['count' => $count] + $vars);
}
/**
* Get a singular message.
*
* @param string $key The key to use.
* @param array $vars Additional context variables.
* @return string The translated message or ''.
*/
public function singular(string $key, array $vars = []): string
{
if (isset(static::$strings[$key])) {
$varKeys = array_keys($vars);
foreach ($varKeys as $i => $k) {
$varKeys[$i] = '{' . $k . '}';
}
return str_replace($varKeys, $vars, static::$strings[$key]);
}
return '';
}
}

View File

@@ -1,23 +0,0 @@
<?php
declare(strict_types=1);
/**
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @copyright Copyright (c) Brian Nesbitt <brian@nesbot.com>
* @link http://cakephp.org CakePHP(tm) Project
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
// Check if the interface alias exists and don't redeclare it in case we are in
// a preloaded context.
if (!\class_exists('Carbon\Carbon') && !\interface_exists('Carbon\CarbonInterface', false)) {
// Create class aliases for Carbon so applications
// can upgrade more easily.
class_alias('Cake\Chronos\Chronos', 'Carbon\MutableDateTime');
class_alias('Cake\Chronos\ChronosInterface', 'Carbon\CarbonInterface');
}

View File

@@ -42,6 +42,8 @@ namespace Composer\Autoload;
*/ */
class ClassLoader class ClassLoader
{ {
private $vendorDir;
// PSR-4 // PSR-4
private $prefixLengthsPsr4 = array(); private $prefixLengthsPsr4 = array();
private $prefixDirsPsr4 = array(); private $prefixDirsPsr4 = array();
@@ -57,6 +59,13 @@ class ClassLoader
private $missingClasses = array(); private $missingClasses = array();
private $apcuPrefix; private $apcuPrefix;
private static $registeredLoaders = array();
public function __construct($vendorDir = null)
{
$this->vendorDir = $vendorDir;
}
public function getPrefixes() public function getPrefixes()
{ {
if (!empty($this->prefixesPsr0)) { if (!empty($this->prefixesPsr0)) {
@@ -300,6 +309,17 @@ class ClassLoader
public function register($prepend = false) public function register($prepend = false)
{ {
spl_autoload_register(array($this, 'loadClass'), true, $prepend); spl_autoload_register(array($this, 'loadClass'), true, $prepend);
if (null === $this->vendorDir) {
return;
}
if ($prepend) {
self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
} else {
unset(self::$registeredLoaders[$this->vendorDir]);
self::$registeredLoaders[$this->vendorDir] = $this;
}
} }
/** /**
@@ -308,6 +328,10 @@ class ClassLoader
public function unregister() public function unregister()
{ {
spl_autoload_unregister(array($this, 'loadClass')); spl_autoload_unregister(array($this, 'loadClass'));
if (null !== $this->vendorDir) {
unset(self::$registeredLoaders[$this->vendorDir]);
}
} }
/** /**
@@ -367,6 +391,16 @@ class ClassLoader
return $file; return $file;
} }
/**
* Returns the currently registered loaders indexed by their corresponding vendor directories.
*
* @return self[]
*/
public static function getRegisteredLoaders()
{
return self::$registeredLoaders;
}
private function findFileWithExtension($class, $ext) private function findFileWithExtension($class, $ext)
{ {
// PSR-4 lookup // PSR-4 lookup

View File

@@ -30,7 +30,7 @@ private static $installed = array (
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => 'e248cd036c7757b009d90b73fcd77176cbb45e76', 'reference' => '41b78a0599d303bea0254a30f8ebc3c778e3e34e',
'name' => 'laravel/laravel', 'name' => 'laravel/laravel',
), ),
'versions' => 'versions' =>
@@ -53,15 +53,6 @@ private static $installed = array (
), ),
'reference' => 'dff976c2f3487d42c1db75a3b180e2b9f0e72ce0', 'reference' => 'dff976c2f3487d42c1db75a3b180e2b9f0e72ce0',
), ),
'cakephp/chronos' =>
array (
'pretty_version' => '2.1.2',
'version' => '2.1.2.0',
'aliases' =>
array (
),
'reference' => '1d187c71587c97520c00491f626e0f255144953e',
),
'cordoval/hamcrest-php' => 'cordoval/hamcrest-php' =>
array ( array (
'replaced' => 'replaced' =>
@@ -105,12 +96,12 @@ private static $installed = array (
), ),
'dragonmantank/cron-expression' => 'dragonmantank/cron-expression' =>
array ( array (
'pretty_version' => 'v2.3.1', 'pretty_version' => 'v3.1.0',
'version' => '2.3.1.0', 'version' => '3.1.0.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => '65b2d8ee1f10915efb3b55597da3404f096acba2', 'reference' => '7a8c6e56ab3ffcc538d05e8155bb42269abf1a0c',
), ),
'egulias/email-validator' => 'egulias/email-validator' =>
array ( array (
@@ -123,12 +114,12 @@ private static $installed = array (
), ),
'eveseat/eseye' => 'eveseat/eseye' =>
array ( array (
'pretty_version' => '2.3.2', 'pretty_version' => '2.4.0',
'version' => '2.3.2.0', 'version' => '2.4.0.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => '69a0180f1727369614971fe377a1a8b2301c505d', 'reference' => 'b9d6753ccad9edce2bed6c91142f62eaebe24a8c',
), ),
'facade/ignition-contracts' => 'facade/ignition-contracts' =>
array ( array (
@@ -175,14 +166,23 @@ private static $installed = array (
), ),
'reference' => '848d8125239d7dbf8ab25cb7f054f1a630e68c2e', 'reference' => '848d8125239d7dbf8ab25cb7f054f1a630e68c2e',
), ),
'guzzlehttp/guzzle' => 'graham-campbell/result-type' =>
array ( array (
'pretty_version' => '6.5.5', 'pretty_version' => 'v1.0.1',
'version' => '6.5.5.0', 'version' => '1.0.1.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => '9d4290de1cfd701f38099ef7e183b64b4b7b0c5e', 'reference' => '7e279d2cd5d7fbb156ce46daada972355cea27bb',
),
'guzzlehttp/guzzle' =>
array (
'pretty_version' => '7.3.0',
'version' => '7.3.0.0',
'aliases' =>
array (
),
'reference' => '7008573787b430c1c1f650e3722d9bba59967628',
), ),
'guzzlehttp/promises' => 'guzzlehttp/promises' =>
array ( array (
@@ -215,203 +215,217 @@ private static $installed = array (
array ( array (
'replaced' => 'replaced' =>
array ( array (
0 => 'v7.30.4', 0 => 'v8.44.0',
), ),
), ),
'illuminate/broadcasting' => 'illuminate/broadcasting' =>
array ( array (
'replaced' => 'replaced' =>
array ( array (
0 => 'v7.30.4', 0 => 'v8.44.0',
), ),
), ),
'illuminate/bus' => 'illuminate/bus' =>
array ( array (
'replaced' => 'replaced' =>
array ( array (
0 => 'v7.30.4', 0 => 'v8.44.0',
), ),
), ),
'illuminate/cache' => 'illuminate/cache' =>
array ( array (
'replaced' => 'replaced' =>
array ( array (
0 => 'v7.30.4', 0 => 'v8.44.0',
),
),
'illuminate/collections' =>
array (
'replaced' =>
array (
0 => 'v8.44.0',
), ),
), ),
'illuminate/config' => 'illuminate/config' =>
array ( array (
'replaced' => 'replaced' =>
array ( array (
0 => 'v7.30.4', 0 => 'v8.44.0',
), ),
), ),
'illuminate/console' => 'illuminate/console' =>
array ( array (
'replaced' => 'replaced' =>
array ( array (
0 => 'v7.30.4', 0 => 'v8.44.0',
), ),
), ),
'illuminate/container' => 'illuminate/container' =>
array ( array (
'replaced' => 'replaced' =>
array ( array (
0 => 'v7.30.4', 0 => 'v8.44.0',
), ),
), ),
'illuminate/contracts' => 'illuminate/contracts' =>
array ( array (
'replaced' => 'replaced' =>
array ( array (
0 => 'v7.30.4', 0 => 'v8.44.0',
), ),
), ),
'illuminate/cookie' => 'illuminate/cookie' =>
array ( array (
'replaced' => 'replaced' =>
array ( array (
0 => 'v7.30.4', 0 => 'v8.44.0',
), ),
), ),
'illuminate/database' => 'illuminate/database' =>
array ( array (
'replaced' => 'replaced' =>
array ( array (
0 => 'v7.30.4', 0 => 'v8.44.0',
), ),
), ),
'illuminate/encryption' => 'illuminate/encryption' =>
array ( array (
'replaced' => 'replaced' =>
array ( array (
0 => 'v7.30.4', 0 => 'v8.44.0',
), ),
), ),
'illuminate/events' => 'illuminate/events' =>
array ( array (
'replaced' => 'replaced' =>
array ( array (
0 => 'v7.30.4', 0 => 'v8.44.0',
), ),
), ),
'illuminate/filesystem' => 'illuminate/filesystem' =>
array ( array (
'replaced' => 'replaced' =>
array ( array (
0 => 'v7.30.4', 0 => 'v8.44.0',
), ),
), ),
'illuminate/hashing' => 'illuminate/hashing' =>
array ( array (
'replaced' => 'replaced' =>
array ( array (
0 => 'v7.30.4', 0 => 'v8.44.0',
), ),
), ),
'illuminate/http' => 'illuminate/http' =>
array ( array (
'replaced' => 'replaced' =>
array ( array (
0 => 'v7.30.4', 0 => 'v8.44.0',
), ),
), ),
'illuminate/log' => 'illuminate/log' =>
array ( array (
'replaced' => 'replaced' =>
array ( array (
0 => 'v7.30.4', 0 => 'v8.44.0',
),
),
'illuminate/macroable' =>
array (
'replaced' =>
array (
0 => 'v8.44.0',
), ),
), ),
'illuminate/mail' => 'illuminate/mail' =>
array ( array (
'replaced' => 'replaced' =>
array ( array (
0 => 'v7.30.4', 0 => 'v8.44.0',
), ),
), ),
'illuminate/notifications' => 'illuminate/notifications' =>
array ( array (
'replaced' => 'replaced' =>
array ( array (
0 => 'v7.30.4', 0 => 'v8.44.0',
), ),
), ),
'illuminate/pagination' => 'illuminate/pagination' =>
array ( array (
'replaced' => 'replaced' =>
array ( array (
0 => 'v7.30.4', 0 => 'v8.44.0',
), ),
), ),
'illuminate/pipeline' => 'illuminate/pipeline' =>
array ( array (
'replaced' => 'replaced' =>
array ( array (
0 => 'v7.30.4', 0 => 'v8.44.0',
), ),
), ),
'illuminate/queue' => 'illuminate/queue' =>
array ( array (
'replaced' => 'replaced' =>
array ( array (
0 => 'v7.30.4', 0 => 'v8.44.0',
), ),
), ),
'illuminate/redis' => 'illuminate/redis' =>
array ( array (
'replaced' => 'replaced' =>
array ( array (
0 => 'v7.30.4', 0 => 'v8.44.0',
), ),
), ),
'illuminate/routing' => 'illuminate/routing' =>
array ( array (
'replaced' => 'replaced' =>
array ( array (
0 => 'v7.30.4', 0 => 'v8.44.0',
), ),
), ),
'illuminate/session' => 'illuminate/session' =>
array ( array (
'replaced' => 'replaced' =>
array ( array (
0 => 'v7.30.4', 0 => 'v8.44.0',
), ),
), ),
'illuminate/support' => 'illuminate/support' =>
array ( array (
'replaced' => 'replaced' =>
array ( array (
0 => 'v7.30.4', 0 => 'v8.44.0',
), ),
), ),
'illuminate/testing' => 'illuminate/testing' =>
array ( array (
'replaced' => 'replaced' =>
array ( array (
0 => 'v7.30.4', 0 => 'v8.44.0',
), ),
), ),
'illuminate/translation' => 'illuminate/translation' =>
array ( array (
'replaced' => 'replaced' =>
array ( array (
0 => 'v7.30.4', 0 => 'v8.44.0',
), ),
), ),
'illuminate/validation' => 'illuminate/validation' =>
array ( array (
'replaced' => 'replaced' =>
array ( array (
0 => 'v7.30.4', 0 => 'v8.44.0',
), ),
), ),
'illuminate/view' => 'illuminate/view' =>
array ( array (
'replaced' => 'replaced' =>
array ( array (
0 => 'v7.30.4', 0 => 'v8.44.0',
), ),
), ),
'khill/lavacharts' => 'khill/lavacharts' =>
@@ -432,12 +446,12 @@ private static $installed = array (
), ),
'laravel/framework' => 'laravel/framework' =>
array ( array (
'pretty_version' => 'v7.30.4', 'pretty_version' => 'v8.44.0',
'version' => '7.30.4.0', 'version' => '8.44.0.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => '9dd38140dc2924daa1a020a3d7a45f9ceff03df3', 'reference' => '7b3b27dc8911ab02a69731af2ba97b5130b2ddb8',
), ),
'laravel/helpers' => 'laravel/helpers' =>
array ( array (
@@ -450,12 +464,12 @@ private static $installed = array (
), ),
'laravel/horizon' => 'laravel/horizon' =>
array ( array (
'pretty_version' => 'v4.3.5', 'pretty_version' => 'v5.7.8',
'version' => '4.3.5.0', 'version' => '5.7.8.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => 'b3fba0daaaaf5e84197b06dd25f3b27bb7301171', 'reference' => '2b5628b598c813650458dc7e4afacb500d72ff9a',
), ),
'laravel/laravel' => 'laravel/laravel' =>
array ( array (
@@ -464,7 +478,7 @@ private static $installed = array (
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => 'e248cd036c7757b009d90b73fcd77176cbb45e76', 'reference' => '41b78a0599d303bea0254a30f8ebc3c778e3e34e',
), ),
'laravel/socialite' => 'laravel/socialite' =>
array ( array (
@@ -477,12 +491,12 @@ private static $installed = array (
), ),
'laravel/ui' => 'laravel/ui' =>
array ( array (
'pretty_version' => 'v2.5.0', 'pretty_version' => 'v3.3.0',
'version' => '2.5.0.0', 'version' => '3.3.0.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => 'd01a705763c243b07be795e9d1bb47f89260f73d', 'reference' => '07d725813350c695c779382cbd6dac0ab8665537',
), ),
'laravelcollective/html' => 'laravelcollective/html' =>
array ( array (
@@ -531,12 +545,12 @@ private static $installed = array (
), ),
'lorisleiva/cron-translator' => 'lorisleiva/cron-translator' =>
array ( array (
'pretty_version' => 'v0.1.1', 'pretty_version' => 'v0.2.0',
'version' => '0.1.1.0', 'version' => '0.2.0.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => '784a6f6255a4b5f45da5d89dc6ec631a14d7b011', 'reference' => '764996770558dddc7def8619095391a4ec8048f2',
), ),
'mockery/mockery' => 'mockery/mockery' =>
array ( array (
@@ -556,6 +570,13 @@ private static $installed = array (
), ),
'reference' => '1cb1cde8e8dd0f70cc0fe51354a59acad9302084', 'reference' => '1cb1cde8e8dd0f70cc0fe51354a59acad9302084',
), ),
'mtdowling/cron-expression' =>
array (
'replaced' =>
array (
0 => '^1.0',
),
),
'myclabs/deep-copy' => 'myclabs/deep-copy' =>
array ( array (
'pretty_version' => '1.10.2', 'pretty_version' => '1.10.2',
@@ -571,21 +592,30 @@ private static $installed = array (
), ),
'nesbot/carbon' => 'nesbot/carbon' =>
array ( array (
'pretty_version' => '2.48.0', 'pretty_version' => '2.48.1',
'version' => '2.48.0.0', 'version' => '2.48.1.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => 'd3c447f21072766cddec3522f9468a5849a76147', 'reference' => '8d1f50f1436fb4b05e7127360483dd9c6e73da16',
),
'nikic/php-parser' =>
array (
'pretty_version' => 'v4.10.5',
'version' => '4.10.5.0',
'aliases' =>
array (
),
'reference' => '4432ba399e47c66624bc73c8c0f811e5c109576f',
), ),
'nunomaduro/collision' => 'nunomaduro/collision' =>
array ( array (
'pretty_version' => 'v4.3.0', 'pretty_version' => 'v5.4.0',
'version' => '4.3.0.0', 'version' => '5.4.0.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => '7c125dc2463f3e144ddc7e05e63077109508c94e', 'reference' => '41b7e9999133d5082700d31a1d0977161df8322a',
), ),
'opis/closure' => 'opis/closure' =>
array ( array (
@@ -661,57 +691,57 @@ private static $installed = array (
), ),
'phpunit/php-code-coverage' => 'phpunit/php-code-coverage' =>
array ( array (
'pretty_version' => '7.0.14', 'pretty_version' => '9.2.6',
'version' => '7.0.14.0', 'version' => '9.2.6.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => 'bb7c9a210c72e4709cdde67f8b7362f672f2225c', 'reference' => 'f6293e1b30a2354e8428e004689671b83871edde',
), ),
'phpunit/php-file-iterator' => 'phpunit/php-file-iterator' =>
array ( array (
'pretty_version' => '2.0.3', 'pretty_version' => '3.0.5',
'version' => '2.0.3.0', 'version' => '3.0.5.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => '4b49fb70f067272b659ef0174ff9ca40fdaa6357', 'reference' => 'aa4be8575f26070b100fccb67faabb28f21f66f8',
),
'phpunit/php-invoker' =>
array (
'pretty_version' => '3.1.1',
'version' => '3.1.1.0',
'aliases' =>
array (
),
'reference' => '5a10147d0aaf65b58940a0b72f71c9ac0423cc67',
), ),
'phpunit/php-text-template' => 'phpunit/php-text-template' =>
array ( array (
'pretty_version' => '1.2.1', 'pretty_version' => '2.0.4',
'version' => '1.2.1.0', 'version' => '2.0.4.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => '31f8b717e51d9a2afca6c9f046f5d69fc27c8686', 'reference' => '5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28',
), ),
'phpunit/php-timer' => 'phpunit/php-timer' =>
array ( array (
'pretty_version' => '2.1.3', 'pretty_version' => '5.0.3',
'version' => '2.1.3.0', 'version' => '5.0.3.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => '2454ae1765516d20c4ffe103d85a58a9a3bd5662', 'reference' => '5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2',
),
'phpunit/php-token-stream' =>
array (
'pretty_version' => '4.0.4',
'version' => '4.0.4.0',
'aliases' =>
array (
),
'reference' => 'a853a0e183b9db7eed023d7933a858fa1c8d25a3',
), ),
'phpunit/phpunit' => 'phpunit/phpunit' =>
array ( array (
'pretty_version' => '8.5.15', 'pretty_version' => '9.5.4',
'version' => '8.5.15.0', 'version' => '9.5.4.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => '038d4196d8e8cb405cd5e82cedfe413ad6eef9ef', 'reference' => 'c73c6737305e779771147af66c96ca6a7ed8a741',
), ),
'predis/predis' => 'predis/predis' =>
array ( array (
@@ -754,6 +784,22 @@ private static $installed = array (
0 => '1.0', 0 => '1.0',
), ),
), ),
'psr/http-client' =>
array (
'pretty_version' => '1.0.1',
'version' => '1.0.1.0',
'aliases' =>
array (
),
'reference' => '2dfb5f6c5eff0e91e20e913f8c5452ed95b86621',
),
'psr/http-client-implementation' =>
array (
'provided' =>
array (
0 => '1.0',
),
),
'psr/http-message' => 'psr/http-message' =>
array ( array (
'pretty_version' => '1.0.1', 'pretty_version' => '1.0.1',
@@ -830,113 +876,149 @@ private static $installed = array (
0 => '4.1.1', 0 => '4.1.1',
), ),
), ),
'sebastian/code-unit-reverse-lookup' => 'sebastian/cli-parser' =>
array ( array (
'pretty_version' => '1.0.2', 'pretty_version' => '1.0.1',
'version' => '1.0.2.0', 'version' => '1.0.1.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => '1de8cd5c010cb153fcd68b8d0f64606f523f7619', 'reference' => '442e7c7e687e42adc03470c7b668bc4b2402c0b2',
),
'sebastian/code-unit' =>
array (
'pretty_version' => '1.0.8',
'version' => '1.0.8.0',
'aliases' =>
array (
),
'reference' => '1fc9f64c0927627ef78ba436c9b17d967e68e120',
),
'sebastian/code-unit-reverse-lookup' =>
array (
'pretty_version' => '2.0.3',
'version' => '2.0.3.0',
'aliases' =>
array (
),
'reference' => 'ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5',
), ),
'sebastian/comparator' => 'sebastian/comparator' =>
array ( array (
'pretty_version' => '3.0.3', 'pretty_version' => '4.0.6',
'version' => '3.0.3.0', 'version' => '4.0.6.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => '1071dfcef776a57013124ff35e1fc41ccd294758', 'reference' => '55f4261989e546dc112258c7a75935a81a7ce382',
), ),
'sebastian/diff' => 'sebastian/complexity' =>
array (
'pretty_version' => '3.0.3',
'version' => '3.0.3.0',
'aliases' =>
array (
),
'reference' => '14f72dd46eaf2f2293cbe79c93cc0bc43161a211',
),
'sebastian/environment' =>
array (
'pretty_version' => '4.2.4',
'version' => '4.2.4.0',
'aliases' =>
array (
),
'reference' => 'd47bbbad83711771f167c72d4e3f25f7fcc1f8b0',
),
'sebastian/exporter' =>
array (
'pretty_version' => '3.1.3',
'version' => '3.1.3.0',
'aliases' =>
array (
),
'reference' => '6b853149eab67d4da22291d36f5b0631c0fd856e',
),
'sebastian/global-state' =>
array (
'pretty_version' => '3.0.1',
'version' => '3.0.1.0',
'aliases' =>
array (
),
'reference' => '474fb9edb7ab891665d3bfc6317f42a0a150454b',
),
'sebastian/object-enumerator' =>
array (
'pretty_version' => '3.0.4',
'version' => '3.0.4.0',
'aliases' =>
array (
),
'reference' => 'e67f6d32ebd0c749cf9d1dbd9f226c727043cdf2',
),
'sebastian/object-reflector' =>
array (
'pretty_version' => '1.1.2',
'version' => '1.1.2.0',
'aliases' =>
array (
),
'reference' => '9b8772b9cbd456ab45d4a598d2dd1a1bced6363d',
),
'sebastian/recursion-context' =>
array (
'pretty_version' => '3.0.1',
'version' => '3.0.1.0',
'aliases' =>
array (
),
'reference' => '367dcba38d6e1977be014dc4b22f47a484dac7fb',
),
'sebastian/resource-operations' =>
array ( array (
'pretty_version' => '2.0.2', 'pretty_version' => '2.0.2',
'version' => '2.0.2.0', 'version' => '2.0.2.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => '31d35ca87926450c44eae7e2611d45a7a65ea8b3', 'reference' => '739b35e53379900cc9ac327b2147867b8b6efd88',
),
'sebastian/diff' =>
array (
'pretty_version' => '4.0.4',
'version' => '4.0.4.0',
'aliases' =>
array (
),
'reference' => '3461e3fccc7cfdfc2720be910d3bd73c69be590d',
),
'sebastian/environment' =>
array (
'pretty_version' => '5.1.3',
'version' => '5.1.3.0',
'aliases' =>
array (
),
'reference' => '388b6ced16caa751030f6a69e588299fa09200ac',
),
'sebastian/exporter' =>
array (
'pretty_version' => '4.0.3',
'version' => '4.0.3.0',
'aliases' =>
array (
),
'reference' => 'd89cc98761b8cb5a1a235a6b703ae50d34080e65',
),
'sebastian/global-state' =>
array (
'pretty_version' => '5.0.2',
'version' => '5.0.2.0',
'aliases' =>
array (
),
'reference' => 'a90ccbddffa067b51f574dea6eb25d5680839455',
),
'sebastian/lines-of-code' =>
array (
'pretty_version' => '1.0.3',
'version' => '1.0.3.0',
'aliases' =>
array (
),
'reference' => 'c1c2e997aa3146983ed888ad08b15470a2e22ecc',
),
'sebastian/object-enumerator' =>
array (
'pretty_version' => '4.0.4',
'version' => '4.0.4.0',
'aliases' =>
array (
),
'reference' => '5c9eeac41b290a3712d88851518825ad78f45c71',
),
'sebastian/object-reflector' =>
array (
'pretty_version' => '2.0.4',
'version' => '2.0.4.0',
'aliases' =>
array (
),
'reference' => 'b4f479ebdbf63ac605d183ece17d8d7fe49c15c7',
),
'sebastian/recursion-context' =>
array (
'pretty_version' => '4.0.4',
'version' => '4.0.4.0',
'aliases' =>
array (
),
'reference' => 'cd9d8cf3c5804de4341c283ed787f099f5506172',
),
'sebastian/resource-operations' =>
array (
'pretty_version' => '3.0.3',
'version' => '3.0.3.0',
'aliases' =>
array (
),
'reference' => '0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8',
), ),
'sebastian/type' => 'sebastian/type' =>
array ( array (
'pretty_version' => '1.1.4', 'pretty_version' => '2.3.1',
'version' => '1.1.4.0', 'version' => '2.3.1.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => '0150cfbc4495ed2df3872fb31b26781e4e077eb4', 'reference' => '81cd61ab7bbf2de744aba0ea61fae32f721df3d2',
), ),
'sebastian/version' => 'sebastian/version' =>
array ( array (
'pretty_version' => '2.0.1', 'pretty_version' => '3.0.2',
'version' => '2.0.1.0', 'version' => '3.0.2.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => '99732be0ddb3361e16ad77b68ba41efc8e979019', 'reference' => 'c6c1022351a901512170118436c764e473f6de8c',
), ),
'socialiteproviders/manager' => 'socialiteproviders/manager' =>
array ( array (
@@ -958,12 +1040,12 @@ private static $installed = array (
), ),
'spatie/laravel-schedule-monitor' => 'spatie/laravel-schedule-monitor' =>
array ( array (
'pretty_version' => '2.0.1', 'pretty_version' => '2.3.0',
'version' => '2.0.1.0', 'version' => '2.3.0.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => '4ffdaea81b5c27a119b6cbac8f4894657b8fd6d9', 'reference' => 'cc65f9822d0e0b69043372d6c7d3e8dbd072f85d',
), ),
'spomky-labs/base64url' => 'spomky-labs/base64url' =>
array ( array (
@@ -994,12 +1076,12 @@ private static $installed = array (
), ),
'symfony/css-selector' => 'symfony/css-selector' =>
array ( array (
'pretty_version' => 'v5.2.7', 'pretty_version' => 'v5.2.9',
'version' => '5.2.7.0', 'version' => '5.2.9.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => '59a684f5ac454f066ecbe6daecce6719aed283fb', 'reference' => '5d5f97809015102116208b976eb2edb44b689560',
), ),
'symfony/deprecation-contracts' => 'symfony/deprecation-contracts' =>
array ( array (
@@ -1046,12 +1128,12 @@ private static $installed = array (
), ),
'symfony/finder' => 'symfony/finder' =>
array ( array (
'pretty_version' => 'v5.2.8', 'pretty_version' => 'v5.2.9',
'version' => '5.2.8.0', 'version' => '5.2.9.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => 'eccb8be70d7a6a2230d05f6ecede40f3fdd9e252', 'reference' => 'ccccb9d48ca42757dd12f2ca4bf857a4e217d90d',
), ),
'symfony/http-client-contracts' => 'symfony/http-client-contracts' =>
array ( array (
@@ -1073,102 +1155,102 @@ private static $installed = array (
), ),
'symfony/http-kernel' => 'symfony/http-kernel' =>
array ( array (
'pretty_version' => 'v5.2.8', 'pretty_version' => 'v5.2.9',
'version' => '5.2.8.0', 'version' => '5.2.9.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => 'c3cb71ee7e2d3eae5fe1001f81780d6a49b37937', 'reference' => 'eb540ef6870dbf33c92e372cfb869ebf9649e6cb',
), ),
'symfony/mime' => 'symfony/mime' =>
array ( array (
'pretty_version' => 'v5.2.7', 'pretty_version' => 'v5.2.9',
'version' => '5.2.7.0', 'version' => '5.2.9.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => '7af452bf51c46f18da00feb32e1ad36db9426515', 'reference' => '64258e870f8cc75c3dae986201ea2df58c210b52',
), ),
'symfony/polyfill-ctype' => 'symfony/polyfill-ctype' =>
array ( array (
'pretty_version' => 'v1.22.1', 'pretty_version' => 'v1.23.0',
'version' => '1.22.1.0', 'version' => '1.23.0.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => 'c6c942b1ac76c82448322025e084cadc56048b4e', 'reference' => '46cd95797e9df938fdd2b03693b5fca5e64b01ce',
), ),
'symfony/polyfill-iconv' => 'symfony/polyfill-iconv' =>
array ( array (
'pretty_version' => 'v1.22.1', 'pretty_version' => 'v1.23.0',
'version' => '1.22.1.0', 'version' => '1.23.0.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => '06fb361659649bcfd6a208a0f1fcaf4e827ad342', 'reference' => '63b5bb7db83e5673936d6e3b8b3e022ff6474933',
), ),
'symfony/polyfill-intl-grapheme' => 'symfony/polyfill-intl-grapheme' =>
array ( array (
'pretty_version' => 'v1.22.1', 'pretty_version' => 'v1.23.0',
'version' => '1.22.1.0', 'version' => '1.23.0.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => '5601e09b69f26c1828b13b6bb87cb07cddba3170', 'reference' => '24b72c6baa32c746a4d0840147c9715e42bb68ab',
), ),
'symfony/polyfill-intl-idn' => 'symfony/polyfill-intl-idn' =>
array ( array (
'pretty_version' => 'v1.22.1', 'pretty_version' => 'v1.23.0',
'version' => '1.22.1.0', 'version' => '1.23.0.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => '2d63434d922daf7da8dd863e7907e67ee3031483', 'reference' => '65bd267525e82759e7d8c4e8ceea44f398838e65',
), ),
'symfony/polyfill-intl-normalizer' => 'symfony/polyfill-intl-normalizer' =>
array ( array (
'pretty_version' => 'v1.22.1', 'pretty_version' => 'v1.23.0',
'version' => '1.22.1.0', 'version' => '1.23.0.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => '43a0283138253ed1d48d352ab6d0bdb3f809f248', 'reference' => '8590a5f561694770bdcd3f9b5c69dde6945028e8',
), ),
'symfony/polyfill-mbstring' => 'symfony/polyfill-mbstring' =>
array ( array (
'pretty_version' => 'v1.22.1', 'pretty_version' => 'v1.23.0',
'version' => '1.22.1.0', 'version' => '1.23.0.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => '5232de97ee3b75b0360528dae24e73db49566ab1', 'reference' => '2df51500adbaebdc4c38dea4c89a2e131c45c8a1',
), ),
'symfony/polyfill-php72' => 'symfony/polyfill-php72' =>
array ( array (
'pretty_version' => 'v1.22.1', 'pretty_version' => 'v1.23.0',
'version' => '1.22.1.0', 'version' => '1.23.0.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => 'cc6e6f9b39fe8075b3dabfbaf5b5f645ae1340c9', 'reference' => '9a142215a36a3888e30d0a9eeea9766764e96976',
), ),
'symfony/polyfill-php73' => 'symfony/polyfill-php73' =>
array ( array (
'pretty_version' => 'v1.22.1', 'pretty_version' => 'v1.23.0',
'version' => '1.22.1.0', 'version' => '1.23.0.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => 'a678b42e92f86eca04b7fa4c0f6f19d097fb69e2', 'reference' => 'fba8933c384d6476ab14fb7b8526e5287ca7e010',
), ),
'symfony/polyfill-php80' => 'symfony/polyfill-php80' =>
array ( array (
'pretty_version' => 'v1.22.1', 'pretty_version' => 'v1.23.0',
'version' => '1.22.1.0', 'version' => '1.23.0.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => 'dc3063ba22c2a1fd2f45ed856374d79114998f91', 'reference' => 'eca0bf41ed421bed1b57c4958bab16aa86b757d0',
), ),
'symfony/process' => 'symfony/process' =>
array ( array (
@@ -1181,12 +1263,12 @@ private static $installed = array (
), ),
'symfony/routing' => 'symfony/routing' =>
array ( array (
'pretty_version' => 'v5.2.7', 'pretty_version' => 'v5.2.9',
'version' => '5.2.7.0', 'version' => '5.2.9.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => '3f0cab2e95b5e92226f34c2c1aa969d3fc41f48c', 'reference' => '4a7b2bf5e1221be1902b6853743a9bb317f6925e',
), ),
'symfony/service-contracts' => 'symfony/service-contracts' =>
array ( array (
@@ -1208,12 +1290,12 @@ private static $installed = array (
), ),
'symfony/translation' => 'symfony/translation' =>
array ( array (
'pretty_version' => 'v5.2.8', 'pretty_version' => 'v5.2.9',
'version' => '5.2.8.0', 'version' => '5.2.9.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => '445caa74a5986f1cc9dd91a2975ef68fa7cb2068', 'reference' => '61af68dba333e2d376a325a29c2a3f2a605b4876',
), ),
'symfony/translation-contracts' => 'symfony/translation-contracts' =>
array ( array (
@@ -1276,12 +1358,12 @@ private static $installed = array (
), ),
'vlucas/phpdotenv' => 'vlucas/phpdotenv' =>
array ( array (
'pretty_version' => 'v4.2.0', 'pretty_version' => 'v5.3.0',
'version' => '4.2.0.0', 'version' => '5.3.0.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => 'da64796370fc4eb03cc277088f6fede9fde88482', 'reference' => 'b3eac5c7ac896e52deab4a99068e3f4ab12d9e56',
), ),
'voku/portable-ascii' => 'voku/portable-ascii' =>
array ( array (

File diff suppressed because it is too large Load Diff

View File

@@ -6,6 +6,7 @@ $vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir); $baseDir = dirname($vendorDir);
return array( return array(
'ec07570ca5a812141189b1fa81503674' => $vendorDir . '/phpunit/phpunit/src/Framework/Assert/Functions.php',
'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php', 'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php',
'6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php', '6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php',
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php', '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
@@ -18,18 +19,19 @@ return array(
'7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php', '7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php',
'c964ee0ededf28c96ebd9db5099ef910' => $vendorDir . '/guzzlehttp/promises/src/functions_include.php', 'c964ee0ededf28c96ebd9db5099ef910' => $vendorDir . '/guzzlehttp/promises/src/functions_include.php',
'a0edc8309cc5e1d60e3047b5df6b7052' => $vendorDir . '/guzzlehttp/psr7/src/functions_include.php', 'a0edc8309cc5e1d60e3047b5df6b7052' => $vendorDir . '/guzzlehttp/psr7/src/functions_include.php',
'a1105708a18b76903365ca1c4aa61b02' => $vendorDir . '/symfony/translation/Resources/functions.php',
'37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php', '37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php',
'def43f6c87e4f8dfd0c9e1b1bab14fe8' => $vendorDir . '/symfony/polyfill-iconv/bootstrap.php', 'def43f6c87e4f8dfd0c9e1b1bab14fe8' => $vendorDir . '/symfony/polyfill-iconv/bootstrap.php',
'2c102faa651ef8ea5874edb585946bce' => $vendorDir . '/swiftmailer/swiftmailer/lib/swift_required.php', '2c102faa651ef8ea5874edb585946bce' => $vendorDir . '/swiftmailer/swiftmailer/lib/swift_required.php',
'a1105708a18b76903365ca1c4aa61b02' => $vendorDir . '/symfony/translation/Resources/functions.php',
'e39a8b23c42d4e1452234d762b03835a' => $vendorDir . '/ramsey/uuid/src/functions.php', 'e39a8b23c42d4e1452234d762b03835a' => $vendorDir . '/ramsey/uuid/src/functions.php',
'538ca81a9a966a6716601ecf48f4eaef' => $vendorDir . '/opis/closure/functions.php', '538ca81a9a966a6716601ecf48f4eaef' => $vendorDir . '/opis/closure/functions.php',
'8825ede83f2f289127722d4e842cf7e8' => $vendorDir . '/symfony/polyfill-intl-grapheme/bootstrap.php', '8825ede83f2f289127722d4e842cf7e8' => $vendorDir . '/symfony/polyfill-intl-grapheme/bootstrap.php',
'34122c0574b76bf21c9a8db62b5b9cf3' => $vendorDir . '/cakephp/chronos/src/carbon_compat.php',
'f0906e6318348a765ffb6eb24e0d0938' => $vendorDir . '/laravel/framework/src/Illuminate/Foundation/helpers.php',
'58571171fd5812e6e447dce228f52f4d' => $vendorDir . '/laravel/framework/src/Illuminate/Support/helpers.php',
'6124b4c8570aa390c21fafd04a26c69f' => $vendorDir . '/myclabs/deep-copy/src/DeepCopy/deep_copy.php', '6124b4c8570aa390c21fafd04a26c69f' => $vendorDir . '/myclabs/deep-copy/src/DeepCopy/deep_copy.php',
'b6b991a57620e2fb6b2f66f03fe9ddc2' => $vendorDir . '/symfony/string/Resources/functions.php', 'b6b991a57620e2fb6b2f66f03fe9ddc2' => $vendorDir . '/symfony/string/Resources/functions.php',
'265b4faa2b3a9766332744949e83bf97' => $vendorDir . '/laravel/framework/src/Illuminate/Collections/helpers.php',
'c7a3c339e7e14b60e06a2d7fcce9476b' => $vendorDir . '/laravel/framework/src/Illuminate/Events/functions.php',
'f0906e6318348a765ffb6eb24e0d0938' => $vendorDir . '/laravel/framework/src/Illuminate/Foundation/helpers.php',
'58571171fd5812e6e447dce228f52f4d' => $vendorDir . '/laravel/framework/src/Illuminate/Support/helpers.php',
'0d8253363903f0ac7b0978dcde4e28a0' => $vendorDir . '/beyondcode/laravel-dump-server/helpers.php', '0d8253363903f0ac7b0978dcde4e28a0' => $vendorDir . '/beyondcode/laravel-dump-server/helpers.php',
'664e151c91315b3715336cbec9a6600a' => $vendorDir . '/eveseat/eseye/src/Helpers/helpers.php', '664e151c91315b3715336cbec9a6600a' => $vendorDir . '/eveseat/eseye/src/Helpers/helpers.php',
'17d016dc52a631c1e74d2eb8fdd57342' => $vendorDir . '/laravel/helpers/src/helpers.php', '17d016dc52a631c1e74d2eb8fdd57342' => $vendorDir . '/laravel/helpers/src/helpers.php',

View File

@@ -47,10 +47,12 @@ return array(
'Psr\\SimpleCache\\' => array($vendorDir . '/psr/simple-cache/src'), 'Psr\\SimpleCache\\' => array($vendorDir . '/psr/simple-cache/src'),
'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'), 'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-message/src'), 'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-message/src'),
'Psr\\Http\\Client\\' => array($vendorDir . '/psr/http-client/src'),
'Psr\\EventDispatcher\\' => array($vendorDir . '/psr/event-dispatcher/src'), 'Psr\\EventDispatcher\\' => array($vendorDir . '/psr/event-dispatcher/src'),
'Psr\\Container\\' => array($vendorDir . '/psr/container/src'), 'Psr\\Container\\' => array($vendorDir . '/psr/container/src'),
'Prophecy\\' => array($vendorDir . '/phpspec/prophecy/src/Prophecy'), 'Prophecy\\' => array($vendorDir . '/phpspec/prophecy/src/Prophecy'),
'Predis\\' => array($vendorDir . '/predis/predis/src'), 'Predis\\' => array($vendorDir . '/predis/predis/src'),
'PhpParser\\' => array($vendorDir . '/nikic/php-parser/lib/PhpParser'),
'PhpOption\\' => array($vendorDir . '/phpoption/phpoption/src/PhpOption'), 'PhpOption\\' => array($vendorDir . '/phpoption/phpoption/src/PhpOption'),
'Opis\\Closure\\' => array($vendorDir . '/opis/closure/src'), 'Opis\\Closure\\' => array($vendorDir . '/opis/closure/src'),
'NunoMaduro\\Collision\\' => array($vendorDir . '/nunomaduro/collision/src'), 'NunoMaduro\\Collision\\' => array($vendorDir . '/nunomaduro/collision/src'),
@@ -70,11 +72,13 @@ return array(
'Jose\\Component\\Encryption\\' => array($vendorDir . '/web-token/jwt-encryption'), 'Jose\\Component\\Encryption\\' => array($vendorDir . '/web-token/jwt-encryption'),
'Jose\\Component\\Core\\' => array($vendorDir . '/web-token/jwt-core'), 'Jose\\Component\\Core\\' => array($vendorDir . '/web-token/jwt-core'),
'Jose\\Component\\Checker\\' => array($vendorDir . '/web-token/jwt-checker'), 'Jose\\Component\\Checker\\' => array($vendorDir . '/web-token/jwt-checker'),
'Illuminate\\Support\\' => array($vendorDir . '/laravel/framework/src/Illuminate/Macroable', $vendorDir . '/laravel/framework/src/Illuminate/Collections'),
'Illuminate\\Foundation\\Auth\\' => array($vendorDir . '/laravel/ui/auth-backend'), 'Illuminate\\Foundation\\Auth\\' => array($vendorDir . '/laravel/ui/auth-backend'),
'Illuminate\\' => array($vendorDir . '/laravel/framework/src/Illuminate'), 'Illuminate\\' => array($vendorDir . '/laravel/framework/src/Illuminate'),
'GuzzleHttp\\Psr7\\' => array($vendorDir . '/guzzlehttp/psr7/src'), 'GuzzleHttp\\Psr7\\' => array($vendorDir . '/guzzlehttp/psr7/src'),
'GuzzleHttp\\Promise\\' => array($vendorDir . '/guzzlehttp/promises/src'), 'GuzzleHttp\\Promise\\' => array($vendorDir . '/guzzlehttp/promises/src'),
'GuzzleHttp\\' => array($vendorDir . '/guzzlehttp/guzzle/src'), 'GuzzleHttp\\' => array($vendorDir . '/guzzlehttp/guzzle/src'),
'GrahamCampbell\\ResultType\\' => array($vendorDir . '/graham-campbell/result-type/src'),
'Fideloper\\Proxy\\' => array($vendorDir . '/fideloper/proxy/src'), 'Fideloper\\Proxy\\' => array($vendorDir . '/fideloper/proxy/src'),
'Faker\\' => array($vendorDir . '/fzaninotto/faker/src/Faker'), 'Faker\\' => array($vendorDir . '/fzaninotto/faker/src/Faker'),
'Facade\\IgnitionContracts\\' => array($vendorDir . '/facade/ignition-contracts/src'), 'Facade\\IgnitionContracts\\' => array($vendorDir . '/facade/ignition-contracts/src'),
@@ -88,7 +92,6 @@ return array(
'Cron\\' => array($vendorDir . '/dragonmantank/cron-expression/src/Cron'), 'Cron\\' => array($vendorDir . '/dragonmantank/cron-expression/src/Cron'),
'Collective\\Html\\' => array($vendorDir . '/laravelcollective/html/src'), 'Collective\\Html\\' => array($vendorDir . '/laravelcollective/html/src'),
'Carbon\\' => array($vendorDir . '/nesbot/carbon/src/Carbon'), 'Carbon\\' => array($vendorDir . '/nesbot/carbon/src/Carbon'),
'Cake\\Chronos\\' => array($vendorDir . '/cakephp/chronos/src'),
'Brick\\Math\\' => array($vendorDir . '/brick/math/src'), 'Brick\\Math\\' => array($vendorDir . '/brick/math/src'),
'BeyondCode\\DumpServer\\' => array($vendorDir . '/beyondcode/laravel-dump-server/src'), 'BeyondCode\\DumpServer\\' => array($vendorDir . '/beyondcode/laravel-dump-server/src'),
'Base64Url\\' => array($vendorDir . '/spomky-labs/base64url/src'), 'Base64Url\\' => array($vendorDir . '/spomky-labs/base64url/src'),

View File

@@ -25,7 +25,7 @@ class ComposerAutoloaderInitc3f953f8a7291d41a76e1664339777c9
require __DIR__ . '/platform_check.php'; require __DIR__ . '/platform_check.php';
spl_autoload_register(array('ComposerAutoloaderInitc3f953f8a7291d41a76e1664339777c9', 'loadClassLoader'), true, true); spl_autoload_register(array('ComposerAutoloaderInitc3f953f8a7291d41a76e1664339777c9', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader(); self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__)));
spl_autoload_unregister(array('ComposerAutoloaderInitc3f953f8a7291d41a76e1664339777c9', 'loadClassLoader')); spl_autoload_unregister(array('ComposerAutoloaderInitc3f953f8a7291d41a76e1664339777c9', 'loadClassLoader'));
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded()); $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -6,7 +6,7 @@
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => 'e248cd036c7757b009d90b73fcd77176cbb45e76', 'reference' => '41b78a0599d303bea0254a30f8ebc3c778e3e34e',
'name' => 'laravel/laravel', 'name' => 'laravel/laravel',
), ),
'versions' => 'versions' =>
@@ -29,15 +29,6 @@
), ),
'reference' => 'dff976c2f3487d42c1db75a3b180e2b9f0e72ce0', 'reference' => 'dff976c2f3487d42c1db75a3b180e2b9f0e72ce0',
), ),
'cakephp/chronos' =>
array (
'pretty_version' => '2.1.2',
'version' => '2.1.2.0',
'aliases' =>
array (
),
'reference' => '1d187c71587c97520c00491f626e0f255144953e',
),
'cordoval/hamcrest-php' => 'cordoval/hamcrest-php' =>
array ( array (
'replaced' => 'replaced' =>
@@ -81,12 +72,12 @@
), ),
'dragonmantank/cron-expression' => 'dragonmantank/cron-expression' =>
array ( array (
'pretty_version' => 'v2.3.1', 'pretty_version' => 'v3.1.0',
'version' => '2.3.1.0', 'version' => '3.1.0.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => '65b2d8ee1f10915efb3b55597da3404f096acba2', 'reference' => '7a8c6e56ab3ffcc538d05e8155bb42269abf1a0c',
), ),
'egulias/email-validator' => 'egulias/email-validator' =>
array ( array (
@@ -99,12 +90,12 @@
), ),
'eveseat/eseye' => 'eveseat/eseye' =>
array ( array (
'pretty_version' => '2.3.2', 'pretty_version' => '2.4.0',
'version' => '2.3.2.0', 'version' => '2.4.0.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => '69a0180f1727369614971fe377a1a8b2301c505d', 'reference' => 'b9d6753ccad9edce2bed6c91142f62eaebe24a8c',
), ),
'facade/ignition-contracts' => 'facade/ignition-contracts' =>
array ( array (
@@ -151,14 +142,23 @@
), ),
'reference' => '848d8125239d7dbf8ab25cb7f054f1a630e68c2e', 'reference' => '848d8125239d7dbf8ab25cb7f054f1a630e68c2e',
), ),
'guzzlehttp/guzzle' => 'graham-campbell/result-type' =>
array ( array (
'pretty_version' => '6.5.5', 'pretty_version' => 'v1.0.1',
'version' => '6.5.5.0', 'version' => '1.0.1.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => '9d4290de1cfd701f38099ef7e183b64b4b7b0c5e', 'reference' => '7e279d2cd5d7fbb156ce46daada972355cea27bb',
),
'guzzlehttp/guzzle' =>
array (
'pretty_version' => '7.3.0',
'version' => '7.3.0.0',
'aliases' =>
array (
),
'reference' => '7008573787b430c1c1f650e3722d9bba59967628',
), ),
'guzzlehttp/promises' => 'guzzlehttp/promises' =>
array ( array (
@@ -191,203 +191,217 @@
array ( array (
'replaced' => 'replaced' =>
array ( array (
0 => 'v7.30.4', 0 => 'v8.44.0',
), ),
), ),
'illuminate/broadcasting' => 'illuminate/broadcasting' =>
array ( array (
'replaced' => 'replaced' =>
array ( array (
0 => 'v7.30.4', 0 => 'v8.44.0',
), ),
), ),
'illuminate/bus' => 'illuminate/bus' =>
array ( array (
'replaced' => 'replaced' =>
array ( array (
0 => 'v7.30.4', 0 => 'v8.44.0',
), ),
), ),
'illuminate/cache' => 'illuminate/cache' =>
array ( array (
'replaced' => 'replaced' =>
array ( array (
0 => 'v7.30.4', 0 => 'v8.44.0',
),
),
'illuminate/collections' =>
array (
'replaced' =>
array (
0 => 'v8.44.0',
), ),
), ),
'illuminate/config' => 'illuminate/config' =>
array ( array (
'replaced' => 'replaced' =>
array ( array (
0 => 'v7.30.4', 0 => 'v8.44.0',
), ),
), ),
'illuminate/console' => 'illuminate/console' =>
array ( array (
'replaced' => 'replaced' =>
array ( array (
0 => 'v7.30.4', 0 => 'v8.44.0',
), ),
), ),
'illuminate/container' => 'illuminate/container' =>
array ( array (
'replaced' => 'replaced' =>
array ( array (
0 => 'v7.30.4', 0 => 'v8.44.0',
), ),
), ),
'illuminate/contracts' => 'illuminate/contracts' =>
array ( array (
'replaced' => 'replaced' =>
array ( array (
0 => 'v7.30.4', 0 => 'v8.44.0',
), ),
), ),
'illuminate/cookie' => 'illuminate/cookie' =>
array ( array (
'replaced' => 'replaced' =>
array ( array (
0 => 'v7.30.4', 0 => 'v8.44.0',
), ),
), ),
'illuminate/database' => 'illuminate/database' =>
array ( array (
'replaced' => 'replaced' =>
array ( array (
0 => 'v7.30.4', 0 => 'v8.44.0',
), ),
), ),
'illuminate/encryption' => 'illuminate/encryption' =>
array ( array (
'replaced' => 'replaced' =>
array ( array (
0 => 'v7.30.4', 0 => 'v8.44.0',
), ),
), ),
'illuminate/events' => 'illuminate/events' =>
array ( array (
'replaced' => 'replaced' =>
array ( array (
0 => 'v7.30.4', 0 => 'v8.44.0',
), ),
), ),
'illuminate/filesystem' => 'illuminate/filesystem' =>
array ( array (
'replaced' => 'replaced' =>
array ( array (
0 => 'v7.30.4', 0 => 'v8.44.0',
), ),
), ),
'illuminate/hashing' => 'illuminate/hashing' =>
array ( array (
'replaced' => 'replaced' =>
array ( array (
0 => 'v7.30.4', 0 => 'v8.44.0',
), ),
), ),
'illuminate/http' => 'illuminate/http' =>
array ( array (
'replaced' => 'replaced' =>
array ( array (
0 => 'v7.30.4', 0 => 'v8.44.0',
), ),
), ),
'illuminate/log' => 'illuminate/log' =>
array ( array (
'replaced' => 'replaced' =>
array ( array (
0 => 'v7.30.4', 0 => 'v8.44.0',
),
),
'illuminate/macroable' =>
array (
'replaced' =>
array (
0 => 'v8.44.0',
), ),
), ),
'illuminate/mail' => 'illuminate/mail' =>
array ( array (
'replaced' => 'replaced' =>
array ( array (
0 => 'v7.30.4', 0 => 'v8.44.0',
), ),
), ),
'illuminate/notifications' => 'illuminate/notifications' =>
array ( array (
'replaced' => 'replaced' =>
array ( array (
0 => 'v7.30.4', 0 => 'v8.44.0',
), ),
), ),
'illuminate/pagination' => 'illuminate/pagination' =>
array ( array (
'replaced' => 'replaced' =>
array ( array (
0 => 'v7.30.4', 0 => 'v8.44.0',
), ),
), ),
'illuminate/pipeline' => 'illuminate/pipeline' =>
array ( array (
'replaced' => 'replaced' =>
array ( array (
0 => 'v7.30.4', 0 => 'v8.44.0',
), ),
), ),
'illuminate/queue' => 'illuminate/queue' =>
array ( array (
'replaced' => 'replaced' =>
array ( array (
0 => 'v7.30.4', 0 => 'v8.44.0',
), ),
), ),
'illuminate/redis' => 'illuminate/redis' =>
array ( array (
'replaced' => 'replaced' =>
array ( array (
0 => 'v7.30.4', 0 => 'v8.44.0',
), ),
), ),
'illuminate/routing' => 'illuminate/routing' =>
array ( array (
'replaced' => 'replaced' =>
array ( array (
0 => 'v7.30.4', 0 => 'v8.44.0',
), ),
), ),
'illuminate/session' => 'illuminate/session' =>
array ( array (
'replaced' => 'replaced' =>
array ( array (
0 => 'v7.30.4', 0 => 'v8.44.0',
), ),
), ),
'illuminate/support' => 'illuminate/support' =>
array ( array (
'replaced' => 'replaced' =>
array ( array (
0 => 'v7.30.4', 0 => 'v8.44.0',
), ),
), ),
'illuminate/testing' => 'illuminate/testing' =>
array ( array (
'replaced' => 'replaced' =>
array ( array (
0 => 'v7.30.4', 0 => 'v8.44.0',
), ),
), ),
'illuminate/translation' => 'illuminate/translation' =>
array ( array (
'replaced' => 'replaced' =>
array ( array (
0 => 'v7.30.4', 0 => 'v8.44.0',
), ),
), ),
'illuminate/validation' => 'illuminate/validation' =>
array ( array (
'replaced' => 'replaced' =>
array ( array (
0 => 'v7.30.4', 0 => 'v8.44.0',
), ),
), ),
'illuminate/view' => 'illuminate/view' =>
array ( array (
'replaced' => 'replaced' =>
array ( array (
0 => 'v7.30.4', 0 => 'v8.44.0',
), ),
), ),
'khill/lavacharts' => 'khill/lavacharts' =>
@@ -408,12 +422,12 @@
), ),
'laravel/framework' => 'laravel/framework' =>
array ( array (
'pretty_version' => 'v7.30.4', 'pretty_version' => 'v8.44.0',
'version' => '7.30.4.0', 'version' => '8.44.0.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => '9dd38140dc2924daa1a020a3d7a45f9ceff03df3', 'reference' => '7b3b27dc8911ab02a69731af2ba97b5130b2ddb8',
), ),
'laravel/helpers' => 'laravel/helpers' =>
array ( array (
@@ -426,12 +440,12 @@
), ),
'laravel/horizon' => 'laravel/horizon' =>
array ( array (
'pretty_version' => 'v4.3.5', 'pretty_version' => 'v5.7.8',
'version' => '4.3.5.0', 'version' => '5.7.8.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => 'b3fba0daaaaf5e84197b06dd25f3b27bb7301171', 'reference' => '2b5628b598c813650458dc7e4afacb500d72ff9a',
), ),
'laravel/laravel' => 'laravel/laravel' =>
array ( array (
@@ -440,7 +454,7 @@
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => 'e248cd036c7757b009d90b73fcd77176cbb45e76', 'reference' => '41b78a0599d303bea0254a30f8ebc3c778e3e34e',
), ),
'laravel/socialite' => 'laravel/socialite' =>
array ( array (
@@ -453,12 +467,12 @@
), ),
'laravel/ui' => 'laravel/ui' =>
array ( array (
'pretty_version' => 'v2.5.0', 'pretty_version' => 'v3.3.0',
'version' => '2.5.0.0', 'version' => '3.3.0.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => 'd01a705763c243b07be795e9d1bb47f89260f73d', 'reference' => '07d725813350c695c779382cbd6dac0ab8665537',
), ),
'laravelcollective/html' => 'laravelcollective/html' =>
array ( array (
@@ -507,12 +521,12 @@
), ),
'lorisleiva/cron-translator' => 'lorisleiva/cron-translator' =>
array ( array (
'pretty_version' => 'v0.1.1', 'pretty_version' => 'v0.2.0',
'version' => '0.1.1.0', 'version' => '0.2.0.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => '784a6f6255a4b5f45da5d89dc6ec631a14d7b011', 'reference' => '764996770558dddc7def8619095391a4ec8048f2',
), ),
'mockery/mockery' => 'mockery/mockery' =>
array ( array (
@@ -532,6 +546,13 @@
), ),
'reference' => '1cb1cde8e8dd0f70cc0fe51354a59acad9302084', 'reference' => '1cb1cde8e8dd0f70cc0fe51354a59acad9302084',
), ),
'mtdowling/cron-expression' =>
array (
'replaced' =>
array (
0 => '^1.0',
),
),
'myclabs/deep-copy' => 'myclabs/deep-copy' =>
array ( array (
'pretty_version' => '1.10.2', 'pretty_version' => '1.10.2',
@@ -547,21 +568,30 @@
), ),
'nesbot/carbon' => 'nesbot/carbon' =>
array ( array (
'pretty_version' => '2.48.0', 'pretty_version' => '2.48.1',
'version' => '2.48.0.0', 'version' => '2.48.1.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => 'd3c447f21072766cddec3522f9468a5849a76147', 'reference' => '8d1f50f1436fb4b05e7127360483dd9c6e73da16',
),
'nikic/php-parser' =>
array (
'pretty_version' => 'v4.10.5',
'version' => '4.10.5.0',
'aliases' =>
array (
),
'reference' => '4432ba399e47c66624bc73c8c0f811e5c109576f',
), ),
'nunomaduro/collision' => 'nunomaduro/collision' =>
array ( array (
'pretty_version' => 'v4.3.0', 'pretty_version' => 'v5.4.0',
'version' => '4.3.0.0', 'version' => '5.4.0.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => '7c125dc2463f3e144ddc7e05e63077109508c94e', 'reference' => '41b7e9999133d5082700d31a1d0977161df8322a',
), ),
'opis/closure' => 'opis/closure' =>
array ( array (
@@ -637,57 +667,57 @@
), ),
'phpunit/php-code-coverage' => 'phpunit/php-code-coverage' =>
array ( array (
'pretty_version' => '7.0.14', 'pretty_version' => '9.2.6',
'version' => '7.0.14.0', 'version' => '9.2.6.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => 'bb7c9a210c72e4709cdde67f8b7362f672f2225c', 'reference' => 'f6293e1b30a2354e8428e004689671b83871edde',
), ),
'phpunit/php-file-iterator' => 'phpunit/php-file-iterator' =>
array ( array (
'pretty_version' => '2.0.3', 'pretty_version' => '3.0.5',
'version' => '2.0.3.0', 'version' => '3.0.5.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => '4b49fb70f067272b659ef0174ff9ca40fdaa6357', 'reference' => 'aa4be8575f26070b100fccb67faabb28f21f66f8',
),
'phpunit/php-invoker' =>
array (
'pretty_version' => '3.1.1',
'version' => '3.1.1.0',
'aliases' =>
array (
),
'reference' => '5a10147d0aaf65b58940a0b72f71c9ac0423cc67',
), ),
'phpunit/php-text-template' => 'phpunit/php-text-template' =>
array ( array (
'pretty_version' => '1.2.1', 'pretty_version' => '2.0.4',
'version' => '1.2.1.0', 'version' => '2.0.4.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => '31f8b717e51d9a2afca6c9f046f5d69fc27c8686', 'reference' => '5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28',
), ),
'phpunit/php-timer' => 'phpunit/php-timer' =>
array ( array (
'pretty_version' => '2.1.3', 'pretty_version' => '5.0.3',
'version' => '2.1.3.0', 'version' => '5.0.3.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => '2454ae1765516d20c4ffe103d85a58a9a3bd5662', 'reference' => '5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2',
),
'phpunit/php-token-stream' =>
array (
'pretty_version' => '4.0.4',
'version' => '4.0.4.0',
'aliases' =>
array (
),
'reference' => 'a853a0e183b9db7eed023d7933a858fa1c8d25a3',
), ),
'phpunit/phpunit' => 'phpunit/phpunit' =>
array ( array (
'pretty_version' => '8.5.15', 'pretty_version' => '9.5.4',
'version' => '8.5.15.0', 'version' => '9.5.4.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => '038d4196d8e8cb405cd5e82cedfe413ad6eef9ef', 'reference' => 'c73c6737305e779771147af66c96ca6a7ed8a741',
), ),
'predis/predis' => 'predis/predis' =>
array ( array (
@@ -730,6 +760,22 @@
0 => '1.0', 0 => '1.0',
), ),
), ),
'psr/http-client' =>
array (
'pretty_version' => '1.0.1',
'version' => '1.0.1.0',
'aliases' =>
array (
),
'reference' => '2dfb5f6c5eff0e91e20e913f8c5452ed95b86621',
),
'psr/http-client-implementation' =>
array (
'provided' =>
array (
0 => '1.0',
),
),
'psr/http-message' => 'psr/http-message' =>
array ( array (
'pretty_version' => '1.0.1', 'pretty_version' => '1.0.1',
@@ -806,113 +852,149 @@
0 => '4.1.1', 0 => '4.1.1',
), ),
), ),
'sebastian/code-unit-reverse-lookup' => 'sebastian/cli-parser' =>
array ( array (
'pretty_version' => '1.0.2', 'pretty_version' => '1.0.1',
'version' => '1.0.2.0', 'version' => '1.0.1.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => '1de8cd5c010cb153fcd68b8d0f64606f523f7619', 'reference' => '442e7c7e687e42adc03470c7b668bc4b2402c0b2',
),
'sebastian/code-unit' =>
array (
'pretty_version' => '1.0.8',
'version' => '1.0.8.0',
'aliases' =>
array (
),
'reference' => '1fc9f64c0927627ef78ba436c9b17d967e68e120',
),
'sebastian/code-unit-reverse-lookup' =>
array (
'pretty_version' => '2.0.3',
'version' => '2.0.3.0',
'aliases' =>
array (
),
'reference' => 'ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5',
), ),
'sebastian/comparator' => 'sebastian/comparator' =>
array ( array (
'pretty_version' => '3.0.3', 'pretty_version' => '4.0.6',
'version' => '3.0.3.0', 'version' => '4.0.6.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => '1071dfcef776a57013124ff35e1fc41ccd294758', 'reference' => '55f4261989e546dc112258c7a75935a81a7ce382',
), ),
'sebastian/diff' => 'sebastian/complexity' =>
array (
'pretty_version' => '3.0.3',
'version' => '3.0.3.0',
'aliases' =>
array (
),
'reference' => '14f72dd46eaf2f2293cbe79c93cc0bc43161a211',
),
'sebastian/environment' =>
array (
'pretty_version' => '4.2.4',
'version' => '4.2.4.0',
'aliases' =>
array (
),
'reference' => 'd47bbbad83711771f167c72d4e3f25f7fcc1f8b0',
),
'sebastian/exporter' =>
array (
'pretty_version' => '3.1.3',
'version' => '3.1.3.0',
'aliases' =>
array (
),
'reference' => '6b853149eab67d4da22291d36f5b0631c0fd856e',
),
'sebastian/global-state' =>
array (
'pretty_version' => '3.0.1',
'version' => '3.0.1.0',
'aliases' =>
array (
),
'reference' => '474fb9edb7ab891665d3bfc6317f42a0a150454b',
),
'sebastian/object-enumerator' =>
array (
'pretty_version' => '3.0.4',
'version' => '3.0.4.0',
'aliases' =>
array (
),
'reference' => 'e67f6d32ebd0c749cf9d1dbd9f226c727043cdf2',
),
'sebastian/object-reflector' =>
array (
'pretty_version' => '1.1.2',
'version' => '1.1.2.0',
'aliases' =>
array (
),
'reference' => '9b8772b9cbd456ab45d4a598d2dd1a1bced6363d',
),
'sebastian/recursion-context' =>
array (
'pretty_version' => '3.0.1',
'version' => '3.0.1.0',
'aliases' =>
array (
),
'reference' => '367dcba38d6e1977be014dc4b22f47a484dac7fb',
),
'sebastian/resource-operations' =>
array ( array (
'pretty_version' => '2.0.2', 'pretty_version' => '2.0.2',
'version' => '2.0.2.0', 'version' => '2.0.2.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => '31d35ca87926450c44eae7e2611d45a7a65ea8b3', 'reference' => '739b35e53379900cc9ac327b2147867b8b6efd88',
),
'sebastian/diff' =>
array (
'pretty_version' => '4.0.4',
'version' => '4.0.4.0',
'aliases' =>
array (
),
'reference' => '3461e3fccc7cfdfc2720be910d3bd73c69be590d',
),
'sebastian/environment' =>
array (
'pretty_version' => '5.1.3',
'version' => '5.1.3.0',
'aliases' =>
array (
),
'reference' => '388b6ced16caa751030f6a69e588299fa09200ac',
),
'sebastian/exporter' =>
array (
'pretty_version' => '4.0.3',
'version' => '4.0.3.0',
'aliases' =>
array (
),
'reference' => 'd89cc98761b8cb5a1a235a6b703ae50d34080e65',
),
'sebastian/global-state' =>
array (
'pretty_version' => '5.0.2',
'version' => '5.0.2.0',
'aliases' =>
array (
),
'reference' => 'a90ccbddffa067b51f574dea6eb25d5680839455',
),
'sebastian/lines-of-code' =>
array (
'pretty_version' => '1.0.3',
'version' => '1.0.3.0',
'aliases' =>
array (
),
'reference' => 'c1c2e997aa3146983ed888ad08b15470a2e22ecc',
),
'sebastian/object-enumerator' =>
array (
'pretty_version' => '4.0.4',
'version' => '4.0.4.0',
'aliases' =>
array (
),
'reference' => '5c9eeac41b290a3712d88851518825ad78f45c71',
),
'sebastian/object-reflector' =>
array (
'pretty_version' => '2.0.4',
'version' => '2.0.4.0',
'aliases' =>
array (
),
'reference' => 'b4f479ebdbf63ac605d183ece17d8d7fe49c15c7',
),
'sebastian/recursion-context' =>
array (
'pretty_version' => '4.0.4',
'version' => '4.0.4.0',
'aliases' =>
array (
),
'reference' => 'cd9d8cf3c5804de4341c283ed787f099f5506172',
),
'sebastian/resource-operations' =>
array (
'pretty_version' => '3.0.3',
'version' => '3.0.3.0',
'aliases' =>
array (
),
'reference' => '0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8',
), ),
'sebastian/type' => 'sebastian/type' =>
array ( array (
'pretty_version' => '1.1.4', 'pretty_version' => '2.3.1',
'version' => '1.1.4.0', 'version' => '2.3.1.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => '0150cfbc4495ed2df3872fb31b26781e4e077eb4', 'reference' => '81cd61ab7bbf2de744aba0ea61fae32f721df3d2',
), ),
'sebastian/version' => 'sebastian/version' =>
array ( array (
'pretty_version' => '2.0.1', 'pretty_version' => '3.0.2',
'version' => '2.0.1.0', 'version' => '3.0.2.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => '99732be0ddb3361e16ad77b68ba41efc8e979019', 'reference' => 'c6c1022351a901512170118436c764e473f6de8c',
), ),
'socialiteproviders/manager' => 'socialiteproviders/manager' =>
array ( array (
@@ -934,12 +1016,12 @@
), ),
'spatie/laravel-schedule-monitor' => 'spatie/laravel-schedule-monitor' =>
array ( array (
'pretty_version' => '2.0.1', 'pretty_version' => '2.3.0',
'version' => '2.0.1.0', 'version' => '2.3.0.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => '4ffdaea81b5c27a119b6cbac8f4894657b8fd6d9', 'reference' => 'cc65f9822d0e0b69043372d6c7d3e8dbd072f85d',
), ),
'spomky-labs/base64url' => 'spomky-labs/base64url' =>
array ( array (
@@ -970,12 +1052,12 @@
), ),
'symfony/css-selector' => 'symfony/css-selector' =>
array ( array (
'pretty_version' => 'v5.2.7', 'pretty_version' => 'v5.2.9',
'version' => '5.2.7.0', 'version' => '5.2.9.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => '59a684f5ac454f066ecbe6daecce6719aed283fb', 'reference' => '5d5f97809015102116208b976eb2edb44b689560',
), ),
'symfony/deprecation-contracts' => 'symfony/deprecation-contracts' =>
array ( array (
@@ -1022,12 +1104,12 @@
), ),
'symfony/finder' => 'symfony/finder' =>
array ( array (
'pretty_version' => 'v5.2.8', 'pretty_version' => 'v5.2.9',
'version' => '5.2.8.0', 'version' => '5.2.9.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => 'eccb8be70d7a6a2230d05f6ecede40f3fdd9e252', 'reference' => 'ccccb9d48ca42757dd12f2ca4bf857a4e217d90d',
), ),
'symfony/http-client-contracts' => 'symfony/http-client-contracts' =>
array ( array (
@@ -1049,102 +1131,102 @@
), ),
'symfony/http-kernel' => 'symfony/http-kernel' =>
array ( array (
'pretty_version' => 'v5.2.8', 'pretty_version' => 'v5.2.9',
'version' => '5.2.8.0', 'version' => '5.2.9.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => 'c3cb71ee7e2d3eae5fe1001f81780d6a49b37937', 'reference' => 'eb540ef6870dbf33c92e372cfb869ebf9649e6cb',
), ),
'symfony/mime' => 'symfony/mime' =>
array ( array (
'pretty_version' => 'v5.2.7', 'pretty_version' => 'v5.2.9',
'version' => '5.2.7.0', 'version' => '5.2.9.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => '7af452bf51c46f18da00feb32e1ad36db9426515', 'reference' => '64258e870f8cc75c3dae986201ea2df58c210b52',
), ),
'symfony/polyfill-ctype' => 'symfony/polyfill-ctype' =>
array ( array (
'pretty_version' => 'v1.22.1', 'pretty_version' => 'v1.23.0',
'version' => '1.22.1.0', 'version' => '1.23.0.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => 'c6c942b1ac76c82448322025e084cadc56048b4e', 'reference' => '46cd95797e9df938fdd2b03693b5fca5e64b01ce',
), ),
'symfony/polyfill-iconv' => 'symfony/polyfill-iconv' =>
array ( array (
'pretty_version' => 'v1.22.1', 'pretty_version' => 'v1.23.0',
'version' => '1.22.1.0', 'version' => '1.23.0.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => '06fb361659649bcfd6a208a0f1fcaf4e827ad342', 'reference' => '63b5bb7db83e5673936d6e3b8b3e022ff6474933',
), ),
'symfony/polyfill-intl-grapheme' => 'symfony/polyfill-intl-grapheme' =>
array ( array (
'pretty_version' => 'v1.22.1', 'pretty_version' => 'v1.23.0',
'version' => '1.22.1.0', 'version' => '1.23.0.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => '5601e09b69f26c1828b13b6bb87cb07cddba3170', 'reference' => '24b72c6baa32c746a4d0840147c9715e42bb68ab',
), ),
'symfony/polyfill-intl-idn' => 'symfony/polyfill-intl-idn' =>
array ( array (
'pretty_version' => 'v1.22.1', 'pretty_version' => 'v1.23.0',
'version' => '1.22.1.0', 'version' => '1.23.0.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => '2d63434d922daf7da8dd863e7907e67ee3031483', 'reference' => '65bd267525e82759e7d8c4e8ceea44f398838e65',
), ),
'symfony/polyfill-intl-normalizer' => 'symfony/polyfill-intl-normalizer' =>
array ( array (
'pretty_version' => 'v1.22.1', 'pretty_version' => 'v1.23.0',
'version' => '1.22.1.0', 'version' => '1.23.0.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => '43a0283138253ed1d48d352ab6d0bdb3f809f248', 'reference' => '8590a5f561694770bdcd3f9b5c69dde6945028e8',
), ),
'symfony/polyfill-mbstring' => 'symfony/polyfill-mbstring' =>
array ( array (
'pretty_version' => 'v1.22.1', 'pretty_version' => 'v1.23.0',
'version' => '1.22.1.0', 'version' => '1.23.0.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => '5232de97ee3b75b0360528dae24e73db49566ab1', 'reference' => '2df51500adbaebdc4c38dea4c89a2e131c45c8a1',
), ),
'symfony/polyfill-php72' => 'symfony/polyfill-php72' =>
array ( array (
'pretty_version' => 'v1.22.1', 'pretty_version' => 'v1.23.0',
'version' => '1.22.1.0', 'version' => '1.23.0.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => 'cc6e6f9b39fe8075b3dabfbaf5b5f645ae1340c9', 'reference' => '9a142215a36a3888e30d0a9eeea9766764e96976',
), ),
'symfony/polyfill-php73' => 'symfony/polyfill-php73' =>
array ( array (
'pretty_version' => 'v1.22.1', 'pretty_version' => 'v1.23.0',
'version' => '1.22.1.0', 'version' => '1.23.0.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => 'a678b42e92f86eca04b7fa4c0f6f19d097fb69e2', 'reference' => 'fba8933c384d6476ab14fb7b8526e5287ca7e010',
), ),
'symfony/polyfill-php80' => 'symfony/polyfill-php80' =>
array ( array (
'pretty_version' => 'v1.22.1', 'pretty_version' => 'v1.23.0',
'version' => '1.22.1.0', 'version' => '1.23.0.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => 'dc3063ba22c2a1fd2f45ed856374d79114998f91', 'reference' => 'eca0bf41ed421bed1b57c4958bab16aa86b757d0',
), ),
'symfony/process' => 'symfony/process' =>
array ( array (
@@ -1157,12 +1239,12 @@
), ),
'symfony/routing' => 'symfony/routing' =>
array ( array (
'pretty_version' => 'v5.2.7', 'pretty_version' => 'v5.2.9',
'version' => '5.2.7.0', 'version' => '5.2.9.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => '3f0cab2e95b5e92226f34c2c1aa969d3fc41f48c', 'reference' => '4a7b2bf5e1221be1902b6853743a9bb317f6925e',
), ),
'symfony/service-contracts' => 'symfony/service-contracts' =>
array ( array (
@@ -1184,12 +1266,12 @@
), ),
'symfony/translation' => 'symfony/translation' =>
array ( array (
'pretty_version' => 'v5.2.8', 'pretty_version' => 'v5.2.9',
'version' => '5.2.8.0', 'version' => '5.2.9.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => '445caa74a5986f1cc9dd91a2975ef68fa7cb2068', 'reference' => '61af68dba333e2d376a325a29c2a3f2a605b4876',
), ),
'symfony/translation-contracts' => 'symfony/translation-contracts' =>
array ( array (
@@ -1252,12 +1334,12 @@
), ),
'vlucas/phpdotenv' => 'vlucas/phpdotenv' =>
array ( array (
'pretty_version' => 'v4.2.0', 'pretty_version' => 'v5.3.0',
'version' => '4.2.0.0', 'version' => '5.3.0.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => 'da64796370fc4eb03cc277088f6fede9fde88482', 'reference' => 'b3eac5c7ac896e52deab4a99068e3f4ab12d9e56',
), ),
'voku/portable-ascii' => 'voku/portable-ascii' =>
array ( array (

View File

@@ -1,5 +1,55 @@
# Change Log # Change Log
## [3.1.0] - 2020-11-24
### Added
- Added `CronExpression::getParts()` method to get parts of the expression as an array (#83)
### Changed
- Changed to Interfaces for some type hints (#97, #86)
- Dropped minimum PHP version to 7.2
- Few syntax changes for phpstan compatibility (#93)
### Fixed
- N/A
### Deprecated
- Deprecated `CronExpression::factory` in favor of the constructor (#56)
- Deprecated `CronExpression::YEAR` as a formality, the functionality is already removed (#87)
## [3.0.1] - 2020-10-12
### Added
- Added support for PHP 8 (#92)
### Changed
- N/A
### Fixed
- N/A
## [3.0.0] - 2020-03-25
**MAJOR CHANGE** - In previous versions of this library, setting both a "Day of Month" and a "Day of Week" would be interpreted as an `AND` statement, not an `OR` statement. For example:
`30 0 1 * 1`
would evaluate to "Run 30 minutes after the 0 hour when the Day Of Month is 1 AND a Monday" instead of "Run 30 minutes after the 0 hour on Day Of Month 1 OR a Monday", where the latter is more inline with most cron systems. This means that if your cron expression has both of these fields set, you may see your expression fire more often starting with v3.0.0.
### Added
- Additional docblocks for IDE and documentation
- Added phpstan as a development dependency
- Added a `Cron\FieldFactoryInterface` to make migrations easier (#38)
### Changed
- Changed some DI testing during TravisCI runs
- `\Cron\CronExpression::determineTimezone()` now checks for `\DateTimeInterface` instead of just `\DateTime`
- Errors with fields now report a more human-understandable error and are 1-based instead of 0-based
- Better support for `\DateTimeImmutable` across the library by typehinting for `\DateTimeInterface` now
- Literals should now be less case-sensative across the board
- Changed logic for when both a Day of Week and a Day of Month are supplied to now be an OR statement, not an AND
### Fixed
- Fixed infinite loop when determining last day of week from literals
- Fixed bug where single number ranges were allowed (ex: `1/10`)
- Fixed nullable FieldFactory in CronExpression where no factory could be supplied
- Fixed issue where logic for dropping seconds to 0 could lead to a timezone change
## [2.3.1] - 2020-10-12 ## [2.3.1] - 2020-10-12
### Added ### Added
- Added support for PHP 8 (#92) - Added support for PHP 8 (#92)

View File

@@ -1,7 +1,7 @@
PHP Cron Expression Parser PHP Cron Expression Parser
========================== ==========================
[![Latest Stable Version](https://poser.pugx.org/dragonmantank/cron-expression/v/stable.png)](https://packagist.org/packages/dragonmantank/cron-expression) [![Total Downloads](https://poser.pugx.org/dragonmantank/cron-expression/downloads.png)](https://packagist.org/packages/dragonmantank/cron-expression) [![Build Status](https://secure.travis-ci.org/dragonmantank/cron-expression.png)](http://travis-ci.org/dragonmantank/cron-expression) [![Latest Stable Version](https://poser.pugx.org/dragonmantank/cron-expression/v/stable.png)](https://packagist.org/packages/dragonmantank/cron-expression) [![Total Downloads](https://poser.pugx.org/dragonmantank/cron-expression/downloads.png)](https://packagist.org/packages/dragonmantank/cron-expression) [![Build Status](https://secure.travis-ci.org/dragonmantank/cron-expression.png)](http://travis-ci.org/dragonmantank/cron-expression) [![StyleCI](https://github.styleci.io/repos/103715337/shield?branch=master)](https://github.styleci.io/repos/103715337)
The PHP cron expression parser can parse a CRON expression, determine if it is 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 due to run, calculate the next run date of the expression, and calculate the previous
@@ -32,21 +32,21 @@ Usage
require_once '/vendor/autoload.php'; require_once '/vendor/autoload.php';
// Works with predefined scheduling definitions // Works with predefined scheduling definitions
$cron = Cron\CronExpression::factory('@daily'); $cron = new Cron\CronExpression('@daily');
$cron->isDue(); $cron->isDue();
echo $cron->getNextRunDate()->format('Y-m-d H:i:s'); echo $cron->getNextRunDate()->format('Y-m-d H:i:s');
echo $cron->getPreviousRunDate()->format('Y-m-d H:i:s'); echo $cron->getPreviousRunDate()->format('Y-m-d H:i:s');
// Works with complex expressions // Works with complex expressions
$cron = Cron\CronExpression::factory('3-59/15 6-12 */15 1 2-5'); $cron = new Cron\CronExpression('3-59/15 6-12 */15 1 2-5');
echo $cron->getNextRunDate()->format('Y-m-d H:i:s'); echo $cron->getNextRunDate()->format('Y-m-d H:i:s');
// Calculate a run date two iterations into the future // Calculate a run date two iterations into the future
$cron = Cron\CronExpression::factory('@daily'); $cron = new Cron\CronExpression('@daily');
echo $cron->getNextRunDate(null, 2)->format('Y-m-d H:i:s'); echo $cron->getNextRunDate(null, 2)->format('Y-m-d H:i:s');
// Calculate a run date relative to a specific time // Calculate a run date relative to a specific time
$cron = Cron\CronExpression::factory('@monthly'); $cron = new Cron\CronExpression('@monthly');
echo $cron->getNextRunDate('2010-01-12 00:00:00')->format('Y-m-d H:i:s'); echo $cron->getNextRunDate('2010-01-12 00:00:00')->format('Y-m-d H:i:s');
``` ```
@@ -65,10 +65,18 @@ A CRON expression is a string representing the schedule for a particular command
| +-------------------- hour (0 - 23) | +-------------------- hour (0 - 23)
+------------------------- min (0 - 59) +------------------------- min (0 - 59)
This library also supports a few macros:
* `@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 * * * *`
Requirements Requirements
============ ============
- PHP 7.0+ - PHP 7.1+
- PHPUnit is required to run the unit tests - PHPUnit is required to run the unit tests
- Composer is required to run the unit tests - Composer is required to run the unit tests
@@ -76,3 +84,4 @@ Projects that Use cron-expression
================================= =================================
* Part of the [Laravel Framework](https://github.com/laravel/framework/) * Part of the [Laravel Framework](https://github.com/laravel/framework/)
* Available as a [Symfony Bundle - setono/cron-expression-bundle](https://github.com/Setono/CronExpressionBundle) * Available as a [Symfony Bundle - setono/cron-expression-bundle](https://github.com/Setono/CronExpressionBundle)
* Framework agnostic, PHP-based job scheduler - [Crunz](https://github.com/lavary/crunz)

View File

@@ -5,11 +5,6 @@
"keywords": ["cron", "schedule"], "keywords": ["cron", "schedule"],
"license": "MIT", "license": "MIT",
"authors": [ "authors": [
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
},
{ {
"name": "Chris Tankersley", "name": "Chris Tankersley",
"email": "chris@ctankersley.com", "email": "chris@ctankersley.com",
@@ -17,10 +12,14 @@
} }
], ],
"require": { "require": {
"php": "^7.0|^8.0" "php": "^7.2|^8.0",
"webmozart/assert": "^1.7.0"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "^6.4|^7.0|^8.0|^9.0" "phpstan/phpstan": "^0.12",
"phpunit/phpunit": "^7.0|^8.0|^9.0",
"phpstan/phpstan-webmozart-assert": "^0.12.7",
"phpstan/extension-installer": "^1.0"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {
@@ -29,12 +28,14 @@
}, },
"autoload-dev": { "autoload-dev": {
"psr-4": { "psr-4": {
"Tests\\": "tests/Cron/" "Cron\\Tests\\": "tests/Cron/"
} }
}, },
"extra": { "replace": {
"branch-alias": { "mtdowling/cron-expression": "^1.0"
"dev-master": "2.3-dev" },
} "scripts": {
"phpstan": "./vendor/bin/phpstan analyse -l max src",
"test": "phpunit"
} }
} }

View File

@@ -0,0 +1,2 @@
parameters:
checkMissingIterableValueType: false

View File

@@ -1,33 +1,39 @@
<?php <?php
declare(strict_types=1);
namespace Cron; namespace Cron;
/** /**
* Abstract CRON expression field * Abstract CRON expression field.
*/ */
abstract class AbstractField implements FieldInterface abstract class AbstractField implements FieldInterface
{ {
/** /**
* Full range of values that are allowed for this field type * Full range of values that are allowed for this field type.
*
* @var array * @var array
*/ */
protected $fullRange = []; protected $fullRange = [];
/** /**
* Literal values we need to convert to integers * Literal values we need to convert to integers.
*
* @var array * @var array
*/ */
protected $literals = []; protected $literals = [];
/** /**
* Start value of the full range * Start value of the full range.
* @var integer *
* @var int
*/ */
protected $rangeStart; protected $rangeStart;
/** /**
* End value of the full range * End value of the full range.
* @var integer *
* @var int
*/ */
protected $rangeEnd; protected $rangeEnd;
@@ -40,98 +46,101 @@ abstract class AbstractField implements FieldInterface
} }
/** /**
* Check to see if a field is satisfied by a value * Check to see if a field is satisfied by a value.
* *
* @param string $dateValue Date value to check * @param int $dateValue Date value to check
* @param string $value Value to test * @param string $value Value to test
* *
* @return bool * @return bool
*/ */
public function isSatisfied($dateValue, $value) public function isSatisfied(int $dateValue, string $value): bool
{ {
if ($this->isIncrementsOfRanges($value)) { if ($this->isIncrementsOfRanges($value)) {
return $this->isInIncrementsOfRanges($dateValue, $value); return $this->isInIncrementsOfRanges($dateValue, $value);
} elseif ($this->isRange($value)) { }
if ($this->isRange($value)) {
return $this->isInRange($dateValue, $value); return $this->isInRange($dateValue, $value);
} }
return $value == '*' || $dateValue == $value; return '*' === $value || $dateValue === (int) $value;
} }
/** /**
* Check if a value is a range * Check if a value is a range.
* *
* @param string $value Value to test * @param string $value Value to test
* *
* @return bool * @return bool
*/ */
public function isRange($value) public function isRange(string $value): bool
{ {
return strpos($value, '-') !== false; return false !== strpos($value, '-');
} }
/** /**
* Check if a value is an increments of ranges * Check if a value is an increments of ranges.
* *
* @param string $value Value to test * @param string $value Value to test
* *
* @return bool * @return bool
*/ */
public function isIncrementsOfRanges($value) public function isIncrementsOfRanges(string $value): bool
{ {
return strpos($value, '/') !== false; return false !== strpos($value, '/');
} }
/** /**
* Test if a value is within a range * Test if a value is within a range.
* *
* @param string $dateValue Set date value * @param int $dateValue Set date value
* @param string $value Value to test * @param string $value Value to test
* *
* @return bool * @return bool
*/ */
public function isInRange($dateValue, $value) public function isInRange(int $dateValue, $value): bool
{ {
$parts = array_map(function($value) { $parts = array_map(
function ($value) {
$value = trim($value); $value = trim($value);
$value = $this->convertLiterals($value);
return $value; return $this->convertLiterals($value);
}, },
explode('-', $value, 2) explode('-', $value, 2)
); );
return $dateValue >= $parts[0] && $dateValue <= $parts[1]; return $dateValue >= $parts[0] && $dateValue <= $parts[1];
} }
/** /**
* Test if a value is within an increments of ranges (offset[-to]/step size) * Test if a value is within an increments of ranges (offset[-to]/step size).
* *
* @param string $dateValue Set date value * @param int $dateValue Set date value
* @param string $value Value to test * @param string $value Value to test
* *
* @return bool * @return bool
*/ */
public function isInIncrementsOfRanges($dateValue, $value) public function isInIncrementsOfRanges(int $dateValue, string $value): bool
{ {
$chunks = array_map('trim', explode('/', $value, 2)); $chunks = array_map('trim', explode('/', $value, 2));
$range = $chunks[0]; $range = $chunks[0];
$step = isset($chunks[1]) ? $chunks[1] : 0; $step = $chunks[1] ?? 0;
// No step or 0 steps aren't cool // No step or 0 steps aren't cool
if (is_null($step) || '0' === $step || 0 === $step) { /** @phpstan-ignore-next-line */
if (null === $step || '0' === $step || 0 === $step) {
return false; return false;
} }
// Expand the * to a full range // Expand the * to a full range
if ('*' == $range) { if ('*' === $range) {
$range = $this->rangeStart . '-' . $this->rangeEnd; $range = $this->rangeStart . '-' . $this->rangeEnd;
} }
// Generate the requested small range // Generate the requested small range
$rangeChunks = explode('-', $range, 2); $rangeChunks = explode('-', $range, 2);
$rangeStart = $rangeChunks[0]; $rangeStart = $rangeChunks[0];
$rangeEnd = isset($rangeChunks[1]) ? $rangeChunks[1] : $rangeStart; $rangeEnd = $rangeChunks[1] ?? $rangeStart;
if ($rangeStart < $this->rangeStart || $rangeStart > $this->rangeEnd || $rangeStart > $rangeEnd) { if ($rangeStart < $this->rangeStart || $rangeStart > $this->rangeEnd || $rangeStart > $rangeEnd) {
throw new \OutOfRangeException('Invalid range start requested'); throw new \OutOfRangeException('Invalid range start requested');
@@ -143,80 +152,80 @@ abstract class AbstractField implements FieldInterface
// Steps larger than the range need to wrap around and be handled slightly differently than smaller steps // Steps larger than the range need to wrap around and be handled slightly differently than smaller steps
if ($step >= $this->rangeEnd) { if ($step >= $this->rangeEnd) {
$thisRange = [$this->fullRange[$step % count($this->fullRange)]]; $thisRange = [$this->fullRange[$step % \count($this->fullRange)]];
} else { } else {
$thisRange = range($rangeStart, $rangeEnd, $step); $thisRange = range($rangeStart, $rangeEnd, (int) $step);
} }
return in_array($dateValue, $thisRange); return \in_array($dateValue, $thisRange, true);
} }
/** /**
* Returns a range of values for the given cron expression * Returns a range of values for the given cron expression.
* *
* @param string $expression The expression to evaluate * @param string $expression The expression to evaluate
* @param int $max Maximum offset for range * @param int $max Maximum offset for range
* *
* @return array * @return array
*/ */
public function getRangeForExpression($expression, $max) public function getRangeForExpression(string $expression, int $max): array
{ {
$values = array(); $values = [];
$expression = $this->convertLiterals($expression); $expression = $this->convertLiterals($expression);
if (strpos($expression, ',') !== false) { if (false !== strpos($expression, ',')) {
$ranges = explode(',', $expression); $ranges = explode(',', $expression);
$values = []; $values = [];
foreach ($ranges as $range) { foreach ($ranges as $range) {
$expanded = $this->getRangeForExpression($range, $this->rangeEnd); $expanded = $this->getRangeForExpression($range, $this->rangeEnd);
$values = array_merge($values, $expanded); $values = array_merge($values, $expanded);
} }
return $values; return $values;
} }
if ($this->isRange($expression) || $this->isIncrementsOfRanges($expression)) { if ($this->isRange($expression) || $this->isIncrementsOfRanges($expression)) {
if (!$this->isIncrementsOfRanges($expression)) { if (!$this->isIncrementsOfRanges($expression)) {
list ($offset, $to) = explode('-', $expression); [$offset, $to] = explode('-', $expression);
$offset = $this->convertLiterals($offset); $offset = $this->convertLiterals($offset);
$to = $this->convertLiterals($to); $to = $this->convertLiterals($to);
$stepSize = 1; $stepSize = 1;
} } else {
else {
$range = array_map('trim', explode('/', $expression, 2)); $range = array_map('trim', explode('/', $expression, 2));
$stepSize = isset($range[1]) ? $range[1] : 0; $stepSize = $range[1] ?? 0;
$range = $range[0]; $range = $range[0];
$range = explode('-', $range, 2); $range = explode('-', $range, 2);
$offset = $range[0]; $offset = $range[0];
$to = isset($range[1]) ? $range[1] : $max; $to = $range[1] ?? $max;
} }
$offset = $offset == '*' ? $this->rangeStart : $offset; $offset = '*' === $offset ? $this->rangeStart : $offset;
if ($stepSize >= $this->rangeEnd) { if ($stepSize >= $this->rangeEnd) {
$values = [$this->fullRange[$stepSize % count($this->fullRange)]]; $values = [$this->fullRange[$stepSize % \count($this->fullRange)]];
} else { } else {
for ($i = $offset; $i <= $to; $i += $stepSize) { for ($i = $offset; $i <= $to; $i += $stepSize) {
$values[] = (int)$i; $values[] = (int) $i;
} }
} }
sort($values); sort($values);
} } else {
else { $values = [$expression];
$values = array($expression);
} }
return $values; return $values;
} }
/** /**
* Convert literal * Convert literal.
* *
* @param string $value * @param string $value
*
* @return string * @return string
*/ */
protected function convertLiterals($value) protected function convertLiterals(string $value): string
{ {
if (count($this->literals)) { if (\count($this->literals)) {
$key = array_search($value, $this->literals); $key = array_search(strtoupper($value), $this->literals, true);
if ($key !== false) { if (false !== $key) {
return (string) $key; return (string) $key;
} }
} }
@@ -225,12 +234,13 @@ abstract class AbstractField implements FieldInterface
} }
/** /**
* Checks to see if a value is valid for the field * Checks to see if a value is valid for the field.
* *
* @param string $value * @param string $value
*
* @return bool * @return bool
*/ */
public function validate($value) public function validate(string $value): bool
{ {
$value = $this->convertLiterals($value); $value = $this->convertLiterals($value);
@@ -239,22 +249,29 @@ abstract class AbstractField implements FieldInterface
return true; return true;
} }
if (strpos($value, '/') !== false) { if (false !== strpos($value, '/')) {
list($range, $step) = explode('/', $value); [$range, $step] = explode('/', $value);
// Don't allow numeric ranges
if (is_numeric($range)) {
return false;
}
return $this->validate($range) && filter_var($step, FILTER_VALIDATE_INT); return $this->validate($range) && filter_var($step, FILTER_VALIDATE_INT);
} }
// Validate each chunk of a list individually // Validate each chunk of a list individually
if (strpos($value, ',') !== false) { if (false !== strpos($value, ',')) {
foreach (explode(',', $value) as $listItem) { foreach (explode(',', $value) as $listItem) {
if (!$this->validate($listItem)) { if (!$this->validate($listItem)) {
return false; return false;
} }
} }
return true; return true;
} }
if (strpos($value, '-') !== false) { if (false !== strpos($value, '-')) {
if (substr_count($value, '-') > 1) { if (substr_count($value, '-') > 1) {
return false; return false;
} }
@@ -263,7 +280,7 @@ abstract class AbstractField implements FieldInterface
$chunks[0] = $this->convertLiterals($chunks[0]); $chunks[0] = $this->convertLiterals($chunks[0]);
$chunks[1] = $this->convertLiterals($chunks[1]); $chunks[1] = $this->convertLiterals($chunks[1]);
if ('*' == $chunks[0] || '*' == $chunks[1]) { if ('*' === $chunks[0] || '*' === $chunks[1]) {
return false; return false;
} }
@@ -274,13 +291,13 @@ abstract class AbstractField implements FieldInterface
return false; return false;
} }
if (is_float($value) || strpos($value, '.') !== false) { if (false !== strpos($value, '.')) {
return false; return false;
} }
// We should have a numeric by now, so coerce this into an integer // We should have a numeric by now, so coerce this into an integer
$value = (int) $value; $value = (int) $value;
return in_array($value, $this->fullRange, true); return \in_array($value, $this->fullRange, true);
} }
} }

View File

@@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace Cron; namespace Cron;
use DateTime; use DateTime;
@@ -9,6 +11,7 @@ use DateTimeZone;
use Exception; use Exception;
use InvalidArgumentException; use InvalidArgumentException;
use RuntimeException; use RuntimeException;
use Webmozart\Assert\Assert;
/** /**
* CRON expression parser that can determine whether or not a CRON expression is * CRON expression parser that can determine whether or not a CRON expression is
@@ -20,16 +23,27 @@ use RuntimeException;
* minute [0-59], hour [0-23], day of month, month [1-12|JAN-DEC], day of week * 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. * [1-7|MON-SUN], and an optional year.
* *
* @link http://en.wikipedia.org/wiki/Cron * @see http://en.wikipedia.org/wiki/Cron
*/ */
class CronExpression class CronExpression
{ {
const MINUTE = 0; public const MINUTE = 0;
const HOUR = 1; public const HOUR = 1;
const DAY = 2; public const DAY = 2;
const MONTH = 3; public const MONTH = 3;
const WEEKDAY = 4; public const WEEKDAY = 4;
const YEAR = 5;
/** @deprecated */
public const YEAR = 5;
public const MAPPINGS = [
'@yearly' => '0 0 1 1 *',
'@annually' => '0 0 1 1 *',
'@monthly' => '0 0 1 * *',
'@weekly' => '0 0 * * 0',
'@daily' => '0 0 * * *',
'@hourly' => '0 * * * *',
];
/** /**
* @var array CRON expression parts * @var array CRON expression parts
@@ -37,7 +51,7 @@ class CronExpression
private $cronParts; private $cronParts;
/** /**
* @var FieldFactory CRON field factory * @var FieldFactoryInterface CRON field factory
*/ */
private $fieldFactory; private $fieldFactory;
@@ -49,54 +63,35 @@ class CronExpression
/** /**
* @var array Order in which to test of cron parts * @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); private static $order = [
self::YEAR,
self::MONTH,
self::DAY,
self::WEEKDAY,
self::HOUR,
self::MINUTE,
];
/** /**
* Factory method to create a new CronExpression. * @deprecated since version 3.0.2, use __construct instead.
*
* @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|null $fieldFactory Field factory to use
*
* @return CronExpression
*/ */
public static function factory($expression, FieldFactory $fieldFactory = null) public static function factory(string $expression, FieldFactoryInterface $fieldFactory = null): CronExpression
{ {
$mappings = array( /** @phpstan-ignore-next-line */
'@yearly' => '0 0 1 1 *', return new static($expression, $fieldFactory);
'@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. * Validate a CronExpression.
* *
* @param string $expression The CRON expression to validate. * @param string $expression the CRON expression to validate
* *
* @return bool True if a valid CRON expression was passed. False if not. * @return bool True if a valid CRON expression was passed. False if not.
* @see \Cron\CronExpression::factory
*/ */
public static function isValidExpression($expression) public static function isValidExpression(string $expression): bool
{ {
try { try {
self::factory($expression); new CronExpression($expression);
} catch (InvalidArgumentException $e) { } catch (InvalidArgumentException $e) {
return false; return false;
} }
@@ -105,29 +100,36 @@ class CronExpression
} }
/** /**
* Parse a CRON expression * Parse a CRON expression.
* *
* @param string $expression CRON expression (e.g. '8 * * * *') * @param string $expression CRON expression (e.g. '8 * * * *')
* @param FieldFactory|null $fieldFactory Factory to create cron fields * @param null|FieldFactoryInterface $fieldFactory Factory to create cron fields
*/ */
public function __construct($expression, FieldFactory $fieldFactory = null) public function __construct(string $expression, FieldFactoryInterface $fieldFactory = null)
{ {
$this->fieldFactory = $fieldFactory; $shortcut = strtolower($expression);
$expression = self::MAPPINGS[$shortcut] ?? $expression;
$this->fieldFactory = $fieldFactory ?: new FieldFactory();
$this->setExpression($expression); $this->setExpression($expression);
} }
/** /**
* Set or change the CRON expression * Set or change the CRON expression.
* *
* @param string $value CRON expression (e.g. 8 * * * *) * @param string $value CRON expression (e.g. 8 * * * *)
* *
* @return CronExpression
* @throws \InvalidArgumentException if not a valid CRON expression * @throws \InvalidArgumentException if not a valid CRON expression
*
* @return CronExpression
*/ */
public function setExpression($value) public function setExpression(string $value): CronExpression
{ {
$this->cronParts = preg_split('/\s/', $value, -1, PREG_SPLIT_NO_EMPTY); $split = preg_split('/\s/', $value, -1, PREG_SPLIT_NO_EMPTY);
if (count($this->cronParts) < 5) { Assert::isArray($split);
$this->cronParts = $split;
if (\count($this->cronParts) < 5) {
throw new InvalidArgumentException( throw new InvalidArgumentException(
$value . ' is not a valid CRON expression' $value . ' is not a valid CRON expression'
); );
@@ -141,15 +143,16 @@ class CronExpression
} }
/** /**
* Set part of the CRON expression * Set part of the CRON expression.
* *
* @param int $position The position of the CRON expression to set * @param int $position The position of the CRON expression to set
* @param string $value The value to set * @param string $value The value to set
* *
* @return CronExpression
* @throws \InvalidArgumentException if the value is not valid for the part * @throws \InvalidArgumentException if the value is not valid for the part
*
* @return CronExpression
*/ */
public function setPart($position, $value) public function setPart(int $position, string $value): CronExpression
{ {
if (!$this->fieldFactory->getField($position)->validate($value)) { if (!$this->fieldFactory->getField($position)->validate($value)) {
throw new InvalidArgumentException( throw new InvalidArgumentException(
@@ -163,13 +166,13 @@ class CronExpression
} }
/** /**
* Set max iteration count for searching next run dates * Set max iteration count for searching next run dates.
* *
* @param int $maxIterationCount Max iteration count when searching for next run date * @param int $maxIterationCount Max iteration count when searching for next run date
* *
* @return CronExpression * @return CronExpression
*/ */
public function setMaxIterationCount($maxIterationCount) public function setMaxIterationCount(int $maxIterationCount): CronExpression
{ {
$this->maxIterationCount = $maxIterationCount; $this->maxIterationCount = $maxIterationCount;
@@ -191,16 +194,18 @@ class CronExpression
* it matches the cron expression. * it matches the cron expression.
* @param null|string $timeZone TimeZone to use instead of the system default * @param null|string $timeZone TimeZone to use instead of the system default
* *
* @return \DateTime
* @throws \RuntimeException on too many iterations * @throws \RuntimeException on too many iterations
* @throws \Exception
*
* @return \DateTime
*/ */
public function getNextRunDate($currentTime = 'now', $nth = 0, $allowCurrentDate = false, $timeZone = null) public function getNextRunDate($currentTime = 'now', int $nth = 0, bool $allowCurrentDate = false, $timeZone = null): DateTime
{ {
return $this->getRunDate($currentTime, $nth, false, $allowCurrentDate, $timeZone); return $this->getRunDate($currentTime, $nth, false, $allowCurrentDate, $timeZone);
} }
/** /**
* Get a previous run date relative to the current date or a specific date * Get a previous run date relative to the current date or a specific date.
* *
* @param string|\DateTimeInterface $currentTime Relative calculation date * @param string|\DateTimeInterface $currentTime Relative calculation date
* @param int $nth Number of matches to skip before returning * @param int $nth Number of matches to skip before returning
@@ -208,20 +213,23 @@ class CronExpression
* current date if it matches the cron expression * current date if it matches the cron expression
* @param null|string $timeZone TimeZone to use instead of the system default * @param null|string $timeZone TimeZone to use instead of the system default
* *
* @return \DateTime
* @throws \RuntimeException on too many iterations * @throws \RuntimeException on too many iterations
* @throws \Exception
*
* @return \DateTime
*
* @see \Cron\CronExpression::getNextRunDate * @see \Cron\CronExpression::getNextRunDate
*/ */
public function getPreviousRunDate($currentTime = 'now', $nth = 0, $allowCurrentDate = false, $timeZone = null) public function getPreviousRunDate($currentTime = 'now', int $nth = 0, bool $allowCurrentDate = false, $timeZone = null): DateTime
{ {
return $this->getRunDate($currentTime, $nth, true, $allowCurrentDate, $timeZone); return $this->getRunDate($currentTime, $nth, true, $allowCurrentDate, $timeZone);
} }
/** /**
* Get multiple run dates starting at the current date or a specific date * 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 int $total Set the total number of dates to calculate
* @param string|\DateTimeInterface $currentTime Relative calculation date * @param string|\DateTimeInterface|null $currentTime Relative calculation date
* @param bool $invert Set to TRUE to retrieve previous dates * @param bool $invert Set to TRUE to retrieve previous dates
* @param bool $allowCurrentDate Set to TRUE to return the * @param bool $allowCurrentDate Set to TRUE to return the
* current date if it matches the cron expression * current date if it matches the cron expression
@@ -229,10 +237,11 @@ class CronExpression
* *
* @return \DateTime[] Returns an array of run dates * @return \DateTime[] Returns an array of run dates
*/ */
public function getMultipleRunDates($total, $currentTime = 'now', $invert = false, $allowCurrentDate = false, $timeZone = null) public function getMultipleRunDates(int $total, $currentTime = 'now', bool $invert = false, bool $allowCurrentDate = false, $timeZone = null): array
{ {
$matches = array(); $matches = [];
for ($i = 0; $i < max(0, $total); $i++) { $max = max(0, $total);
for ($i = 0; $i < $max; ++$i) {
try { try {
$matches[] = $this->getRunDate($currentTime, $i, $invert, $allowCurrentDate, $timeZone); $matches[] = $this->getRunDate($currentTime, $i, $invert, $allowCurrentDate, $timeZone);
} catch (RuntimeException $e) { } catch (RuntimeException $e) {
@@ -244,33 +253,46 @@ class CronExpression
} }
/** /**
* Get all or part of the CRON expression * Get all or part of the CRON expression.
* *
* @param string $part Specify the part to retrieve or NULL to get the full * @param int|string|null $part specify the part to retrieve or NULL to get the full
* cron schedule string. * cron schedule string
* *
* @return string|null Returns the CRON expression, a part of the * @return null|string Returns the CRON expression, a part of the
* CRON expression, or NULL if the part was specified but not found * CRON expression, or NULL if the part was specified but not found
*/ */
public function getExpression($part = null) public function getExpression($part = null): ?string
{ {
if (null === $part) { if (null === $part) {
return implode(' ', $this->cronParts); return implode(' ', $this->cronParts);
} elseif (array_key_exists($part, $this->cronParts)) { }
if (array_key_exists($part, $this->cronParts)) {
return $this->cronParts[$part]; return $this->cronParts[$part];
} }
return null; return null;
} }
/**
* Gets the parts of the cron expression as an array.
*
* @return string[]
* The array of parts that make up this expression.
*/
public function getParts()
{
return $this->cronParts;
}
/** /**
* Helper method to output the full expression. * Helper method to output the full expression.
* *
* @return string Full CRON expression * @return string Full CRON expression
*/ */
public function __toString() public function __toString(): string
{ {
return $this->getExpression(); return (string) $this->getExpression();
} }
/** /**
@@ -283,23 +305,25 @@ class CronExpression
* *
* @return bool Returns TRUE if the cron is due to run or FALSE if not * @return bool Returns TRUE if the cron is due to run or FALSE if not
*/ */
public function isDue($currentTime = 'now', $timeZone = null) public function isDue($currentTime = 'now', $timeZone = null): bool
{ {
$timeZone = $this->determineTimeZone($currentTime, $timeZone); $timeZone = $this->determineTimeZone($currentTime, $timeZone);
if ('now' === $currentTime) { if ('now' === $currentTime) {
$currentTime = new DateTime(); $currentTime = new DateTime();
} elseif ($currentTime instanceof DateTime) { } elseif ($currentTime instanceof DateTime) {
// $currentTime = clone $currentTime;
} elseif ($currentTime instanceof DateTimeImmutable) { } elseif ($currentTime instanceof DateTimeImmutable) {
$currentTime = DateTime::createFromFormat('U', $currentTime->format('U')); $currentTime = DateTime::createFromFormat('U', $currentTime->format('U'));
} else { } elseif (\is_string($currentTime)) {
$currentTime = new DateTime($currentTime); $currentTime = new DateTime($currentTime);
} }
$currentTime->setTimeZone(new DateTimeZone($timeZone));
Assert::isInstanceOf($currentTime, DateTime::class);
$currentTime->setTimezone(new DateTimeZone($timeZone));
// drop the seconds to 0 // drop the seconds to 0
$currentTime = DateTime::createFromFormat('Y-m-d H:i', $currentTime->format('Y-m-d H:i')); $currentTime->setTime((int) $currentTime->format('H'), (int) $currentTime->format('i'), 0);
try { try {
return $this->getNextRunDate($currentTime, 0, true)->getTimestamp() === $currentTime->getTimestamp(); return $this->getNextRunDate($currentTime, 0, true)->getTimestamp() === $currentTime->getTimestamp();
@@ -309,19 +333,21 @@ class CronExpression
} }
/** /**
* Get the next or previous run date of the expression relative to a date * Get the next or previous run date of the expression relative to a date.
* *
* @param string|\DateTimeInterface $currentTime Relative calculation date * @param string|\DateTimeInterface|null $currentTime Relative calculation date
* @param int $nth Number of matches to skip before returning * @param int $nth Number of matches to skip before returning
* @param bool $invert Set to TRUE to go backwards in time * @param bool $invert Set to TRUE to go backwards in time
* @param bool $allowCurrentDate Set to TRUE to return the * @param bool $allowCurrentDate Set to TRUE to return the
* current date if it matches the cron expression * current date if it matches the cron expression
* @param string|null $timeZone TimeZone to use instead of the system default * @param string|null $timeZone TimeZone to use instead of the system default
* *
* @return \DateTime
* @throws \RuntimeException on too many iterations * @throws \RuntimeException on too many iterations
* @throws Exception
*
* @return \DateTime
*/ */
protected function getRunDate($currentTime = null, $nth = 0, $invert = false, $allowCurrentDate = false, $timeZone = null) protected function getRunDate($currentTime = null, int $nth = 0, bool $invert = false, bool $allowCurrentDate = false, $timeZone = null): DateTime
{ {
$timeZone = $this->determineTimeZone($currentTime, $timeZone); $timeZone = $this->determineTimeZone($currentTime, $timeZone);
@@ -329,18 +355,21 @@ class CronExpression
$currentDate = clone $currentTime; $currentDate = clone $currentTime;
} elseif ($currentTime instanceof DateTimeImmutable) { } elseif ($currentTime instanceof DateTimeImmutable) {
$currentDate = DateTime::createFromFormat('U', $currentTime->format('U')); $currentDate = DateTime::createFromFormat('U', $currentTime->format('U'));
} elseif (\is_string($currentTime)) {
$currentDate = new DateTime($currentTime);
} else { } else {
$currentDate = new DateTime($currentTime ?: 'now'); $currentDate = new DateTime('now');
} }
$currentDate->setTimeZone(new DateTimeZone($timeZone)); Assert::isInstanceOf($currentDate, DateTime::class);
$currentDate->setTime($currentDate->format('H'), $currentDate->format('i'), 0); $currentDate->setTimezone(new DateTimeZone($timeZone));
$currentDate->setTime((int) $currentDate->format('H'), (int) $currentDate->format('i'), 0);
$nextRun = clone $currentDate; $nextRun = clone $currentDate;
$nth = (int) $nth;
// We don't have to satisfy * or null fields // We don't have to satisfy * or null fields
$parts = array(); $parts = [];
$fields = array(); $fields = [];
foreach (self::$order as $position) { foreach (self::$order as $position) {
$part = $this->getExpression($position); $part = $this->getExpression($position);
if (null === $part || '*' === $part) { if (null === $part || '*' === $part) {
@@ -350,20 +379,38 @@ class CronExpression
$fields[$position] = $this->fieldFactory->getField($position); $fields[$position] = $this->fieldFactory->getField($position);
} }
// Set a hard limit to bail on an impossible date if (isset($parts[2]) && isset($parts[4])) {
for ($i = 0; $i < $this->maxIterationCount; $i++) { $domExpression = sprintf('%s %s %s %s *', $this->getExpression(0), $this->getExpression(1), $this->getExpression(2), $this->getExpression(3));
$dowExpression = sprintf('%s %s * %s %s', $this->getExpression(0), $this->getExpression(1), $this->getExpression(3), $this->getExpression(4));
$domExpression = new self($domExpression);
$dowExpression = new self($dowExpression);
$domRunDates = $domExpression->getMultipleRunDates($nth + 1, $currentTime, $invert, $allowCurrentDate, $timeZone);
$dowRunDates = $dowExpression->getMultipleRunDates($nth + 1, $currentTime, $invert, $allowCurrentDate, $timeZone);
$combined = array_merge($domRunDates, $dowRunDates);
usort($combined, function ($a, $b) {
return $a->format('Y-m-d H:i:s') <=> $b->format('Y-m-d H:i:s');
});
return $combined[$nth];
}
// Set a hard limit to bail on an impossible date
for ($i = 0; $i < $this->maxIterationCount; ++$i) {
foreach ($parts as $position => $part) { foreach ($parts as $position => $part) {
$satisfied = false; $satisfied = false;
// Get the field object used to validate this part // Get the field object used to validate this part
$field = $fields[$position]; $field = $fields[$position];
// Check if this is singular or a list // Check if this is singular or a list
if (strpos($part, ',') === false) { if (false === strpos($part, ',')) {
$satisfied = $field->isSatisfiedBy($nextRun, $part); $satisfied = $field->isSatisfiedBy($nextRun, $part);
} else { } else {
foreach (array_map('trim', explode(',', $part)) as $listPart) { foreach (array_map('trim', explode(',', $part)) as $listPart) {
if ($field->isSatisfiedBy($nextRun, $listPart)) { if ($field->isSatisfiedBy($nextRun, $listPart)) {
$satisfied = true; $satisfied = true;
break; break;
} }
} }
@@ -372,13 +419,15 @@ class CronExpression
// If the field is not satisfied, then start over // If the field is not satisfied, then start over
if (!$satisfied) { if (!$satisfied) {
$field->increment($nextRun, $invert, $part); $field->increment($nextRun, $invert, $part);
continue 2; continue 2;
} }
} }
// Skip this match if needed // Skip this match if needed
if ((!$allowCurrentDate && $nextRun == $currentDate) || --$nth > -1) { if ((!$allowCurrentDate && $nextRun == $currentDate) || --$nth > -1) {
$this->fieldFactory->getField(0)->increment($nextRun, $invert, isset($parts[0]) ? $parts[0] : null); $this->fieldFactory->getField(0)->increment($nextRun, $invert, $parts[0] ?? null);
continue; continue;
} }
@@ -393,18 +442,18 @@ class CronExpression
/** /**
* Workout what timeZone should be used. * Workout what timeZone should be used.
* *
* @param string|\DateTimeInterface $currentTime Relative calculation date * @param string|\DateTimeInterface|null $currentTime Relative calculation date
* @param string|null $timeZone TimeZone to use instead of the system default * @param string|null $timeZone TimeZone to use instead of the system default
* *
* @return string * @return string
*/ */
protected function determineTimeZone($currentTime, $timeZone) protected function determineTimeZone($currentTime, ?string $timeZone): string
{ {
if (! is_null($timeZone)) { if (null !== $timeZone) {
return $timeZone; return $timeZone;
} }
if ($currentTime instanceOf DateTimeInterface) { if ($currentTime instanceof DateTimeInterface) {
return $currentTime->getTimeZone()->getName(); return $currentTime->getTimeZone()->getName();
} }

View File

@@ -1,12 +1,14 @@
<?php <?php
declare(strict_types=1);
namespace Cron; namespace Cron;
use DateTime; use DateTime;
use DateTimeInterface; use DateTimeInterface;
/** /**
* Day of month field. Allows: * , / - ? L W * Day of month field. Allows: * , / - ? L W.
* *
* 'L' stands for "last" and specifies the last day of the month. * 'L' stands for "last" and specifies the last day of the month.
* *
@@ -26,28 +28,33 @@ use DateTimeInterface;
class DayOfMonthField extends AbstractField class DayOfMonthField extends AbstractField
{ {
/** /**
* @inheritDoc * {@inheritdoc}
*/ */
protected $rangeStart = 1; protected $rangeStart = 1;
/** /**
* @inheritDoc * {@inheritdoc}
*/ */
protected $rangeEnd = 31; protected $rangeEnd = 31;
/** /**
* Get the nearest day of the week for a given day in a month * Get the nearest day of the week for a given day in a month.
* *
* @param int $currentYear Current year * @param int $currentYear Current year
* @param int $currentMonth Current month * @param int $currentMonth Current month
* @param int $targetDay Target day of the month * @param int $targetDay Target day of the month
* *
* @return \DateTime Returns the nearest date * @return \DateTime|null Returns the nearest date
*/ */
private static function getNearestWeekday($currentYear, $currentMonth, $targetDay) private static function getNearestWeekday(int $currentYear, int $currentMonth, int $targetDay): ?DateTime
{ {
$tday = str_pad($targetDay, 2, '0', STR_PAD_LEFT); $tday = str_pad((string) $targetDay, 2, '0', STR_PAD_LEFT);
$target = DateTime::createFromFormat('Y-m-d', "$currentYear-$currentMonth-$tday"); $target = DateTime::createFromFormat('Y-m-d', "${currentYear}-${currentMonth}-${tday}");
if ($target === false) {
return null;
}
$currentWeekday = (int) $target->format('N'); $currentWeekday = (int) $target->format('N');
if ($currentWeekday < 6) { if ($currentWeekday < 6) {
@@ -55,56 +62,60 @@ class DayOfMonthField extends AbstractField
} }
$lastDayOfMonth = $target->format('t'); $lastDayOfMonth = $target->format('t');
foreach ([-1, 1, -2, 2] as $i) {
foreach (array(-1, 1, -2, 2) as $i) {
$adjusted = $targetDay + $i; $adjusted = $targetDay + $i;
if ($adjusted > 0 && $adjusted <= $lastDayOfMonth) { if ($adjusted > 0 && $adjusted <= $lastDayOfMonth) {
$target->setDate($currentYear, $currentMonth, $adjusted); $target->setDate($currentYear, $currentMonth, $adjusted);
if ($target->format('N') < 6 && $target->format('m') == $currentMonth) {
if ((int) $target->format('N') < 6 && (int) $target->format('m') === $currentMonth) {
return $target; return $target;
} }
} }
} }
return null;
} }
/** /**
* @inheritDoc * {@inheritdoc}
*/ */
public function isSatisfiedBy(DateTimeInterface $date, $value) public function isSatisfiedBy(DateTimeInterface $date, $value): bool
{ {
// ? states that the field value is to be skipped // ? states that the field value is to be skipped
if ($value == '?') { if ('?' === $value) {
return true; return true;
} }
$fieldValue = $date->format('d'); $fieldValue = $date->format('d');
// Check to see if this is the last day of the month // Check to see if this is the last day of the month
if ($value == 'L') { if ('L' === $value) {
return $fieldValue == $date->format('t'); return $fieldValue === $date->format('t');
} }
// Check to see if this is the nearest weekday to a particular value // Check to see if this is the nearest weekday to a particular value
if (strpos($value, 'W')) { if (strpos($value, 'W')) {
// Parse the target day // Parse the target day
$targetDay = substr($value, 0, strpos($value, 'W')); /** @phpstan-ignore-next-line */
$targetDay = (int) substr($value, 0, strpos($value, 'W'));
// Find out if the current day is the nearest day of the week // Find out if the current day is the nearest day of the week
return $date->format('j') == self::getNearestWeekday( /** @phpstan-ignore-next-line */
$date->format('Y'), return $date->format('j') === self::getNearestWeekday(
$date->format('m'), (int) $date->format('Y'),
(int) $date->format('m'),
$targetDay $targetDay
)->format('j'); )->format('j');
} }
return $this->isSatisfied($date->format('d'), $value); return $this->isSatisfied((int) $date->format('d'), $value);
} }
/** /**
* @inheritDoc * @inheritDoc
* *
* @param \DateTime|\DateTimeImmutable &$date * @param \DateTime|\DateTimeImmutable $date
*/ */
public function increment(DateTimeInterface &$date, $invert = false) public function increment(DateTimeInterface &$date, $invert = false, $parts = null): FieldInterface
{ {
if ($invert) { if ($invert) {
$date = $date->modify('previous day')->setTime(23, 59); $date = $date->modify('previous day')->setTime(23, 59);
@@ -116,20 +127,23 @@ class DayOfMonthField extends AbstractField
} }
/** /**
* @inheritDoc * {@inheritdoc}
*/ */
public function validate($value) public function validate(string $value): bool
{ {
$basicChecks = parent::validate($value); $basicChecks = parent::validate($value);
// Validate that a list don't have W or L // Validate that a list don't have W or L
if (strpos($value, ',') !== false && (strpos($value, 'W') !== false || strpos($value, 'L') !== false)) { if (false !== strpos($value, ',') && (false !== strpos($value, 'W') || false !== strpos($value, 'L'))) {
return false; return false;
} }
if (!$basicChecks) { if (!$basicChecks) {
if ('?' === $value) {
return true;
}
if ($value === 'L') { if ('L' === $value) {
return true; return true;
} }

View File

@@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace Cron; namespace Cron;
use DateTime; use DateTime;
@@ -7,7 +9,7 @@ use DateTimeInterface;
use InvalidArgumentException; use InvalidArgumentException;
/** /**
* Day of week field. Allows: * / , - ? L # * Day of week field. Allows: * / , - ? L #.
* *
* Days of the week can be represented as a number 0-7 (0|7 = Sunday) * 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. * or as a three letter string: SUN, MON, TUE, WED, THU, FRI, SAT.
@@ -22,12 +24,12 @@ use InvalidArgumentException;
class DayOfWeekField extends AbstractField class DayOfWeekField extends AbstractField
{ {
/** /**
* @inheritDoc * {@inheritdoc}
*/ */
protected $rangeStart = 0; protected $rangeStart = 0;
/** /**
* @inheritDoc * {@inheritdoc}
*/ */
protected $rangeEnd = 7; protected $rangeEnd = 7;
@@ -37,7 +39,7 @@ class DayOfWeekField extends AbstractField
protected $nthRange; protected $nthRange;
/** /**
* @inheritDoc * {@inheritdoc}
*/ */
protected $literals = [1 => 'MON', 2 => 'TUE', 3 => 'WED', 4 => 'THU', 5 => 'FRI', 6 => 'SAT', 7 => 'SUN']; protected $literals = [1 => 'MON', 2 => 'TUE', 3 => 'WED', 4 => 'THU', 5 => 'FRI', 6 => 'SAT', 7 => 'SUN'];
@@ -55,39 +57,39 @@ class DayOfWeekField extends AbstractField
* *
* @param \DateTime|\DateTimeImmutable $date * @param \DateTime|\DateTimeImmutable $date
*/ */
public function isSatisfiedBy(DateTimeInterface $date, $value) public function isSatisfiedBy(DateTimeInterface $date, $value): bool
{ {
if ($value == '?') { if ('?' === $value) {
return true; return true;
} }
// Convert text day of the week values to integers // Convert text day of the week values to integers
$value = $this->convertLiterals($value); $value = $this->convertLiterals($value);
$currentYear = $date->format('Y'); $currentYear = (int) $date->format('Y');
$currentMonth = $date->format('m'); $currentMonth = (int) $date->format('m');
$lastDayOfMonth = $date->format('t'); $lastDayOfMonth = (int) $date->format('t');
// Find out if this is the last specific weekday of the month // Find out if this is the last specific weekday of the month
if (strpos($value, 'L')) { if (strpos($value, 'L')) {
$weekday = (int) $this->convertLiterals(substr($value, 0, strpos($value, 'L'))); /** @phpstan-ignore-next-line */
$weekday = $this->convertLiterals(substr($value, 0, strpos($value, 'L')));
$weekday %= 7; $weekday %= 7;
$tdate = clone $date; $tdate = clone $date;
$tdate = $tdate->setDate($currentYear, $currentMonth, $lastDayOfMonth); $tdate = $tdate->setDate($currentYear, $currentMonth, $lastDayOfMonth);
while ($tdate->format('w') != $weekday) { while ($tdate->format('w') != $weekday) {
$tdateClone = new DateTime(); $tdateClone = new DateTime();
$tdate = $tdateClone $tdate = $tdateClone->setTimezone($tdate->getTimezone())
->setTimezone($tdate->getTimezone())
->setDate($currentYear, $currentMonth, --$lastDayOfMonth); ->setDate($currentYear, $currentMonth, --$lastDayOfMonth);
} }
return $date->format('j') == $lastDayOfMonth; return (int) $date->format('j') === $lastDayOfMonth;
} }
// Handle # hash tokens // Handle # hash tokens
if (strpos($value, '#')) { if (strpos($value, '#')) {
list($weekday, $nth) = explode('#', $value); [$weekday, $nth] = explode('#', $value);
if (!is_numeric($nth)) { if (!is_numeric($nth)) {
throw new InvalidArgumentException("Hashed weekdays must be numeric, {$nth} given"); throw new InvalidArgumentException("Hashed weekdays must be numeric, {$nth} given");
@@ -96,23 +98,23 @@ class DayOfWeekField extends AbstractField
} }
// 0 and 7 are both Sunday, however 7 matches date('N') format ISO-8601 // 0 and 7 are both Sunday, however 7 matches date('N') format ISO-8601
if ($weekday === '0') { if ('0' === $weekday) {
$weekday = 7; $weekday = 7;
} }
$weekday = $this->convertLiterals($weekday); $weekday = (int) $this->convertLiterals((string) $weekday);
// Validate the hash fields // Validate the hash fields
if ($weekday < 0 || $weekday > 7) { if ($weekday < 0 || $weekday > 7) {
throw new InvalidArgumentException("Weekday must be a value between 0 and 7. {$weekday} given"); throw new InvalidArgumentException("Weekday must be a value between 0 and 7. {$weekday} given");
} }
if (!in_array($nth, $this->nthRange)) { if (!\in_array($nth, $this->nthRange, true)) {
throw new InvalidArgumentException("There are never more than 5 or less than 1 of a given weekday in a month, {$nth} given"); 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 // The current weekday must match the targeted weekday to proceed
if ($date->format('N') != $weekday) { if ((int) $date->format('N') !== $weekday) {
return false; return false;
} }
@@ -121,7 +123,7 @@ class DayOfWeekField extends AbstractField
$dayCount = 0; $dayCount = 0;
$currentDay = 1; $currentDay = 1;
while ($currentDay < $lastDayOfMonth + 1) { while ($currentDay < $lastDayOfMonth + 1) {
if ($tdate->format('N') == $weekday) { if ((int) $tdate->format('N') === $weekday) {
if (++$dayCount >= $nth) { if (++$dayCount >= $nth) {
break; break;
} }
@@ -129,23 +131,25 @@ class DayOfWeekField extends AbstractField
$tdate = $tdate->setDate($currentYear, $currentMonth, ++$currentDay); $tdate = $tdate->setDate($currentYear, $currentMonth, ++$currentDay);
} }
return $date->format('j') == $currentDay; return (int) $date->format('j') === $currentDay;
} }
// Handle day of the week values // Handle day of the week values
if (strpos($value, '-')) { if (false !== strpos($value, '-')) {
$parts = explode('-', $value); $parts = explode('-', $value);
if ($parts[0] == '7') { if ('7' === $parts[0]) {
$parts[0] = '0'; $parts[0] = 0;
} elseif ($parts[1] == '0') { } elseif ('0' === $parts[1]) {
$parts[1] = '7'; $parts[1] = 7;
} }
$value = implode('-', $parts); $value = implode('-', $parts);
} }
// Test to see which Sunday to use -- 0 == 7 == Sunday // Test to see which Sunday to use -- 0 == 7 == Sunday
$format = in_array(7, str_split($value)) ? 'N' : 'w'; $format = \in_array(7, array_map(function ($value) {
$fieldValue = $date->format($format); return (int) $value;
}, str_split($value)), true) ? 'N' : 'w';
$fieldValue = (int) $date->format($format);
return $this->isSatisfied($fieldValue, $value); return $this->isSatisfied($fieldValue, $value);
} }
@@ -153,9 +157,9 @@ class DayOfWeekField extends AbstractField
/** /**
* @inheritDoc * @inheritDoc
* *
* @param \DateTime|\DateTimeImmutable &$date * @param \DateTime|\DateTimeImmutable $date
*/ */
public function increment(DateTimeInterface &$date, $invert = false) public function increment(DateTimeInterface &$date, $invert = false, $parts = null): FieldInterface
{ {
if ($invert) { if ($invert) {
$date = $date->modify('-1 day')->setTime(23, 59, 0); $date = $date->modify('-1 day')->setTime(23, 59, 0);
@@ -167,19 +171,23 @@ class DayOfWeekField extends AbstractField
} }
/** /**
* @inheritDoc * {@inheritdoc}
*/ */
public function validate($value) public function validate(string $value): bool
{ {
$basicChecks = parent::validate($value); $basicChecks = parent::validate($value);
if (!$basicChecks) { if (!$basicChecks) {
if ('?' === $value) {
return true;
}
// Handle the # value // Handle the # value
if (strpos($value, '#') !== false) { if (false !== strpos($value, '#')) {
$chunks = explode('#', $value); $chunks = explode('#', $value);
$chunks[0] = $this->convertLiterals($chunks[0]); $chunks[0] = $this->convertLiterals($chunks[0]);
if (parent::validate($chunks[0]) && is_numeric($chunks[1]) && in_array($chunks[1], $this->nthRange)) { if (parent::validate($chunks[0]) && is_numeric($chunks[1]) && \in_array((int) $chunks[1], $this->nthRange, true)) {
return true; return true;
} }
} }

View File

@@ -1,54 +1,52 @@
<?php <?php
declare(strict_types=1);
namespace Cron; namespace Cron;
use InvalidArgumentException; use InvalidArgumentException;
/** /**
* CRON field factory implementing a flyweight factory * CRON field factory implementing a flyweight factory.
* @link http://en.wikipedia.org/wiki/Cron *
* @see http://en.wikipedia.org/wiki/Cron
*/ */
class FieldFactory class FieldFactory implements FieldFactoryInterface
{ {
/** /**
* @var array Cache of instantiated fields * @var array Cache of instantiated fields
*/ */
private $fields = array(); private $fields = [];
/** /**
* Get an instance of a field object for a cron expression position * Get an instance of a field object for a cron expression position.
* *
* @param int $position CRON expression position value to retrieve * @param int $position CRON expression position value to retrieve
* *
* @return FieldInterface
* @throws InvalidArgumentException if a position is not valid * @throws InvalidArgumentException if a position is not valid
*/ */
public function getField($position) public function getField(int $position): FieldInterface
{
return $this->fields[$position] ?? $this->fields[$position] = $this->instantiateField($position);
}
private function instantiateField(int $position): FieldInterface
{ {
if (!isset($this->fields[$position])) {
switch ($position) { switch ($position) {
case 0: case CronExpression::MINUTE:
$this->fields[$position] = new MinutesField(); return new MinutesField();
break; case CronExpression::HOUR:
case 1: return new HoursField();
$this->fields[$position] = new HoursField(); case CronExpression::DAY:
break; return new DayOfMonthField();
case 2: case CronExpression::MONTH:
$this->fields[$position] = new DayOfMonthField(); return new MonthField();
break; case CronExpression::WEEKDAY:
case 3: return new DayOfWeekField();
$this->fields[$position] = new MonthField(); }
break;
case 4:
$this->fields[$position] = new DayOfWeekField();
break;
default:
throw new InvalidArgumentException( throw new InvalidArgumentException(
($position + 1) . ' is not a valid position' ($position + 1) . ' is not a valid position'
); );
} }
}
return $this->fields[$position];
}
} }

View File

@@ -0,0 +1,8 @@
<?php
namespace Cron;
interface FieldFactoryInterface
{
public function getField(int $position): FieldInterface;
}

View File

@@ -1,41 +1,44 @@
<?php <?php
declare(strict_types=1);
namespace Cron; namespace Cron;
use DateTimeInterface; use DateTimeInterface;
/** /**
* CRON field interface * CRON field interface.
*/ */
interface FieldInterface interface FieldInterface
{ {
/** /**
* Check if the respective value of a DateTime field satisfies a CRON exp * Check if the respective value of a DateTime field satisfies a CRON exp.
* *
* @param DateTimeInterface $date DateTime object to check * @param DateTimeInterface $date DateTime object to check
* @param string $value CRON expression to test against * @param string $value CRON expression to test against
* *
* @return bool Returns TRUE if satisfied, FALSE otherwise * @return bool Returns TRUE if satisfied, FALSE otherwise
*/ */
public function isSatisfiedBy(DateTimeInterface $date, $value); public function isSatisfiedBy(DateTimeInterface $date, $value): bool;
/** /**
* When a CRON expression is not satisfied, this method is used to increment * 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 * or decrement a DateTime object by the unit of the cron field.
* *
* @param DateTimeInterface &$date DateTime object to change * @param DateTimeInterface $date DateTime object to change
* @param bool $invert (optional) Set to TRUE to decrement * @param bool $invert (optional) Set to TRUE to decrement
* @param string|null $parts (optional) Set parts to use
* *
* @return FieldInterface * @return FieldInterface
*/ */
public function increment(DateTimeInterface &$date, $invert = false); public function increment(DateTimeInterface &$date, $invert = false, $parts = null): FieldInterface;
/** /**
* Validates a CRON expression for a given field * Validates a CRON expression for a given field.
* *
* @param string $value CRON expression value to validate * @param string $value CRON expression value to validate
* *
* @return bool Returns TRUE if valid, FALSE otherwise * @return bool Returns TRUE if valid, FALSE otherwise
*/ */
public function validate($value); public function validate(string $value): bool;
} }

View File

@@ -1,82 +1,81 @@
<?php <?php
declare(strict_types=1);
namespace Cron; namespace Cron;
use DateTimeInterface; use DateTimeInterface;
use DateTimeZone; use DateTimeZone;
/** /**
* Hours field. Allows: * , / - * Hours field. Allows: * , / -.
*/ */
class HoursField extends AbstractField class HoursField extends AbstractField
{ {
/** /**
* @inheritDoc * {@inheritdoc}
*/ */
protected $rangeStart = 0; protected $rangeStart = 0;
/** /**
* @inheritDoc * {@inheritdoc}
*/ */
protected $rangeEnd = 23; protected $rangeEnd = 23;
/** /**
* @inheritDoc * {@inheritdoc}
*/ */
public function isSatisfiedBy(DateTimeInterface $date, $value) public function isSatisfiedBy(DateTimeInterface $date, $value): bool
{ {
if ($value == '?') { return $this->isSatisfied((int) $date->format('H'), $value);
return true;
}
return $this->isSatisfied($date->format('H'), $value);
} }
/** /**
* {@inheritDoc} * {@inheritdoc}
* *
* @param \DateTime|\DateTimeImmutable &$date * @param \DateTime|\DateTimeImmutable $date
* @param string|null $parts * @param string|null $parts
*/ */
public function increment(DateTimeInterface &$date, $invert = false, $parts = null) public function increment(DateTimeInterface &$date, $invert = false, $parts = null): FieldInterface
{ {
// Change timezone to UTC temporarily. This will // Change timezone to UTC temporarily. This will
// allow us to go back or forwards and hour even // allow us to go back or forwards and hour even
// if DST will be changed between the hours. // if DST will be changed between the hours.
if (is_null($parts) || $parts == '*') { if (null === $parts || '*' === $parts) {
$timezone = $date->getTimezone(); $timezone = $date->getTimezone();
$date = $date->setTimezone(new DateTimeZone('UTC')); $date = $date->setTimezone(new DateTimeZone('UTC'));
$date = $date->modify(($invert ? '-' : '+') . '1 hour'); $date = $date->modify(($invert ? '-' : '+') . '1 hour');
$date = $date->setTimezone($timezone); $date = $date->setTimezone($timezone);
$date = $date->setTime($date->format('H'), $invert ? 59 : 0); $date = $date->setTime((int)$date->format('H'), $invert ? 59 : 0);
return $this; return $this;
} }
$parts = strpos($parts, ',') !== false ? explode(',', $parts) : array($parts); $parts = false !== strpos($parts, ',') ? explode(',', $parts) : [$parts];
$hours = array(); $hours = [];
foreach ($parts as $part) { foreach ($parts as $part) {
$hours = array_merge($hours, $this->getRangeForExpression($part, 23)); $hours = array_merge($hours, $this->getRangeForExpression($part, 23));
} }
$current_hour = $date->format('H'); $current_hour = $date->format('H');
$position = $invert ? count($hours) - 1 : 0; $position = $invert ? \count($hours) - 1 : 0;
if (count($hours) > 1) { $countHours = \count($hours);
for ($i = 0; $i < count($hours) - 1; $i++) { if ($countHours > 1) {
for ($i = 0; $i < $countHours - 1; ++$i) {
if ((!$invert && $current_hour >= $hours[$i] && $current_hour < $hours[$i + 1]) || if ((!$invert && $current_hour >= $hours[$i] && $current_hour < $hours[$i + 1]) ||
($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; $position = $invert ? $i : $i + 1;
break; break;
} }
} }
} }
$hour = $hours[$position]; $hour = (int) $hours[$position];
if ((!$invert && $date->format('H') >= $hour) || ($invert && $date->format('H') <= $hour)) { if ((!$invert && (int) $date->format('H') >= $hour) || ($invert && (int) $date->format('H') <= $hour)) {
$date = $date->modify(($invert ? '-' : '+') . '1 day'); $date = $date->modify(($invert ? '-' : '+') . '1 day');
$date = $date->setTime($invert ? 23 : 0, $invert ? 59 : 0); $date = $date->setTime($invert ? 23 : 0, $invert ? 59 : 0);
} } else {
else {
$date = $date->setTime($hour, $invert ? 59 : 0); $date = $date->setTime($hour, $invert ? 59 : 0);
} }

View File

@@ -1,62 +1,66 @@
<?php <?php
declare(strict_types=1);
namespace Cron; namespace Cron;
use DateTimeInterface; use DateTimeInterface;
/** /**
* Minutes field. Allows: * , / - * Minutes field. Allows: * , / -.
*/ */
class MinutesField extends AbstractField class MinutesField extends AbstractField
{ {
/** /**
* @inheritDoc * {@inheritdoc}
*/ */
protected $rangeStart = 0; protected $rangeStart = 0;
/** /**
* @inheritDoc * {@inheritdoc}
*/ */
protected $rangeEnd = 59; protected $rangeEnd = 59;
/** /**
* @inheritDoc * {@inheritdoc}
*/ */
public function isSatisfiedBy(DateTimeInterface $date, $value) public function isSatisfiedBy(DateTimeInterface $date, $value):bool
{ {
if ($value == '?') { if ($value == '?') {
return true; return true;
} }
return $this->isSatisfied($date->format('i'), $value); return $this->isSatisfied((int)$date->format('i'), $value);
} }
/** /**
* {@inheritdoc}
* {@inheritDoc} * {@inheritDoc}
* *
* @param \DateTime|\DateTimeImmutable &$date * @param \DateTime|\DateTimeImmutable $date
* @param string|null $parts * @param string|null $parts
*/ */
public function increment(DateTimeInterface &$date, $invert = false, $parts = null) public function increment(DateTimeInterface &$date, $invert = false, $parts = null): FieldInterface
{ {
if (is_null($parts)) { if (is_null($parts)) {
$date = $date->modify(($invert ? '-' : '+') . '1 minute'); $date = $date->modify(($invert ? '-' : '+') . '1 minute');
return $this; return $this;
} }
$parts = strpos($parts, ',') !== false ? explode(',', $parts) : array($parts); $parts = false !== strpos($parts, ',') ? explode(',', $parts) : [$parts];
$minutes = array(); $minutes = [];
foreach ($parts as $part) { foreach ($parts as $part) {
$minutes = array_merge($minutes, $this->getRangeForExpression($part, 59)); $minutes = array_merge($minutes, $this->getRangeForExpression($part, 59));
} }
$current_minute = $date->format('i'); $current_minute = $date->format('i');
$position = $invert ? count($minutes) - 1 : 0; $position = $invert ? \count($minutes) - 1 : 0;
if (count($minutes) > 1) { if (\count($minutes) > 1) {
for ($i = 0; $i < count($minutes) - 1; $i++) { for ($i = 0; $i < \count($minutes) - 1; ++$i) {
if ((!$invert && $current_minute >= $minutes[$i] && $current_minute < $minutes[$i + 1]) || if ((!$invert && $current_minute >= $minutes[$i] && $current_minute < $minutes[$i + 1]) ||
($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; $position = $invert ? $i : $i + 1;
break; break;
} }
} }
@@ -64,10 +68,9 @@ class MinutesField extends AbstractField
if ((!$invert && $current_minute >= $minutes[$position]) || ($invert && $current_minute <= $minutes[$position])) { if ((!$invert && $current_minute >= $minutes[$position]) || ($invert && $current_minute <= $minutes[$position])) {
$date = $date->modify(($invert ? '-' : '+') . '1 hour'); $date = $date->modify(($invert ? '-' : '+') . '1 hour');
$date = $date->setTime($date->format('H'), $invert ? 59 : 0); $date = $date->setTime((int) $date->format('H'), $invert ? 59 : 0);
} } else {
else { $date = $date->setTime((int) $date->format('H'), (int) $minutes[$position]);
$date = $date->setTime($date->format('H'), $minutes[$position]);
} }
return $this; return $this;

View File

@@ -1,34 +1,36 @@
<?php <?php
declare(strict_types=1);
namespace Cron; namespace Cron;
use DateTimeInterface; use DateTimeInterface;
/** /**
* Month field. Allows: * , / - * Month field. Allows: * , / -.
*/ */
class MonthField extends AbstractField class MonthField extends AbstractField
{ {
/** /**
* @inheritDoc * {@inheritdoc}
*/ */
protected $rangeStart = 1; protected $rangeStart = 1;
/** /**
* @inheritDoc * {@inheritdoc}
*/ */
protected $rangeEnd = 12; protected $rangeEnd = 12;
/** /**
* @inheritDoc * {@inheritdoc}
*/ */
protected $literals = [1 => 'JAN', 2 => 'FEB', 3 => 'MAR', 4 => 'APR', 5 => 'MAY', 6 => 'JUN', 7 => 'JUL', 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']; 8 => 'AUG', 9 => 'SEP', 10 => 'OCT', 11 => 'NOV', 12 => 'DEC', ];
/** /**
* @inheritDoc * {@inheritdoc}
*/ */
public function isSatisfiedBy(DateTimeInterface $date, $value) public function isSatisfiedBy(DateTimeInterface $date, $value): bool
{ {
if ($value == '?') { if ($value == '?') {
return true; return true;
@@ -36,15 +38,15 @@ class MonthField extends AbstractField
$value = $this->convertLiterals($value); $value = $this->convertLiterals($value);
return $this->isSatisfied($date->format('m'), $value); return $this->isSatisfied((int) $date->format('m'), $value);
} }
/** /**
* @inheritDoc * @inheritDoc
* *
* @param \DateTime|\DateTimeImmutable &$date * @param \DateTime|\DateTimeImmutable $date
*/ */
public function increment(DateTimeInterface &$date, $invert = false) public function increment(DateTimeInterface &$date, $invert = false, $parts = null): FieldInterface
{ {
if ($invert) { if ($invert) {
$date = $date->modify('last day of previous month')->setTime(23, 59); $date = $date->modify('last day of previous month')->setTime(23, 59);
@@ -54,6 +56,4 @@ class MonthField extends AbstractField
return $this; return $this;
} }
} }

View File

@@ -1,139 +0,0 @@
<?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));
}
}

View File

@@ -1,589 +0,0 @@
<?php
namespace Cron\Tests;
use Cron\CronExpression;
use Cron\MonthField;
use DateTime;
use DateTimeImmutable;
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
*/
public function testParsesCronScheduleThrowsAnException()
{
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('Invalid CRON field value A at position 0');
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
*/
public function testInvalidCronsWillFail()
{
$this->expectException(\InvalidArgumentException::class);
// Only four values
$cron = CronExpression::factory('* * * 1');
}
/**
* @covers \Cron\CronExpression::setPart
*/
public function testInvalidPartsWillFail()
{
$this->expectException(\InvalidArgumentException::class);
// 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')));
$this->assertTrue($cron->isDue(new DateTimeImmutable('now')));
}
/**
* @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 testGetRunDateHandlesDifferentDates()
{
$cron = CronExpression::factory('@weekly');
$date = new DateTime("2019-03-10 00:00:00");
$this->assertEquals($date, $cron->getNextRunDate("2019-03-03 08:00:00"));
$this->assertEquals($date, $cron->getNextRunDate(new DateTime("2019-03-03 08:00:00")));
$this->assertEquals($date, $cron->getNextRunDate(new DateTimeImmutable("2019-03-03 08: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'));
}
/**
* When there is an issue with a field, we should report the human readable position
*
* @see https://github.com/dragonmantank/cron-expression/issues/29
*/
public function testFieldPositionIsHumanAdjusted()
{
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage("6 is not a valid position");
$e = CronExpression::factory('0 * * * * ? *');
}
}

View File

@@ -1,77 +0,0 @@
<?php
namespace Cron\Tests;
use Cron\DayOfMonthField;
use DateTime;
use DateTimeImmutable;
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(), '?'));
$this->assertTrue($f->isSatisfiedBy(new DateTimeImmutable(), '?'));
}
/**
* @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'));
}
/**
* @covers \Cron\DayOfMonthField::increment
*/
public function testIncrementsDateTimeImmutable()
{
$d = new DateTimeImmutable('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'));
}
/**
* 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));
}
}

View File

@@ -1,156 +0,0 @@
<?php
namespace Cron\Tests;
use Cron\DayOfWeekField;
use DateTime;
use DateTimeImmutable;
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(), '?'));
$this->assertTrue($f->isSatisfiedBy(new DateTimeImmutable(), '?'));
}
/**
* @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::increment
*/
public function testIncrementsDateTimeImmutable()
{
$d = new DateTimeImmutable('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'));
}
/**
* @covers \Cron\DayOfWeekField::isSatisfiedBy
*/
public function testValidatesHashValueWeekday()
{
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('Weekday must be a value between 0 and 7. 12 given');
$f = new DayOfWeekField();
$this->assertTrue($f->isSatisfiedBy(new DateTime(), '12#1'));
}
/**
* @covers \Cron\DayOfWeekField::isSatisfiedBy
*/
public function testValidatesHashValueNth()
{
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('There are never more than 5 or less than 1 of a given weekday in a month');
$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'));
}
/**
* @covers \Cron\DayOfWeekField::isSatisfiedBy
*/
public function testHandlesLastWeekdayOfTheMonth()
{
$f = new DayOfWeekField();
$this->assertTrue($f->isSatisfiedBy(new DateTime('2018-12-28 00:00:00'), 'FRIL'));
$this->assertTrue($f->isSatisfiedBy(new DateTime('2018-12-28 00:00:00'), '5L'));
$this->assertFalse($f->isSatisfiedBy(new DateTime('2018-12-21 00:00:00'), 'FRIL'));
$this->assertFalse($f->isSatisfiedBy(new DateTime('2018-12-21 00:00:00'), '5L'));
}
/**
* @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));
}
}

View File

@@ -1,43 +0,0 @@
<?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
*/
public function testValidatesFieldPosition()
{
$this->expectException(\InvalidArgumentException::class);
$f = new FieldFactory();
$f->getField(-1);
}
}

View File

@@ -1,99 +0,0 @@
<?php
namespace Cron\Tests;
use Cron\HoursField;
use DateTime;
use DateTimeImmutable;
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::isSatisfiedBy
*/
public function testChecksIfSatisfied()
{
$f = new HoursField();
$this->assertTrue($f->isSatisfiedBy(new DateTime(), '?'));
$this->assertTrue($f->isSatisfiedBy(new DateTimeImmutable(), '?'));
}
/**
* @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 testIncrementsDateTimeImmutable()
{
$d = new DateTimeImmutable('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'));
}
/**
* @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);
}
}

View File

@@ -1,73 +0,0 @@
<?php
namespace Cron\Tests;
use Cron\MinutesField;
use DateTime;
use DateTimeImmutable;
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::isSatisfiedBy
*/
public function testChecksIfSatisfied()
{
$f = new MinutesField();
$this->assertTrue($f->isSatisfiedBy(new DateTime(), '?'));
$this->assertTrue($f->isSatisfiedBy(new DateTimeImmutable(), '?'));
}
/**
* @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'));
}
/**
* @covers \Cron\MinutesField::increment
*/
public function testIncrementsDateTimeImmutable()
{
$d = new DateTimeImmutable('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'));
}
/**
* 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'));
}
}

View File

@@ -1,103 +0,0 @@
<?php
namespace Cron\Tests;
use Cron\MonthField;
use DateTime;
use DateTimeImmutable;
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::isSatisfiedBy
*/
public function testChecksIfSatisfied()
{
$f = new MonthField();
$this->assertTrue($f->isSatisfiedBy(new DateTime(), '?'));
$this->assertTrue($f->isSatisfiedBy(new DateTimeImmutable(), '?'));
}
/**
* @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 testIncrementsDateTimeImmutable()
{
$d = new DateTimeImmutable('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'));
}
/**
* @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'));
}
}

View File

@@ -6,7 +6,7 @@ enabled:
- no_empty_comment - no_empty_comment
disabled: disabled:
- psr12_braces - laravel_braces
- concat_without_spaces - concat_without_spaces
- phpdoc_no_package - phpdoc_no_package
- no_blank_lines_after_class_opening - no_blank_lines_after_class_opening

View File

@@ -3,7 +3,7 @@
/* /*
* This file is part of SeAT * This file is part of SeAT
* *
* Copyright (C) 2015 to 2020 Leon Jacobs * Copyright (C) 2015 to 2021 Leon Jacobs
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -36,7 +36,7 @@ function redirect_to_new()
{ {
header('Location: ' . $_SERVER['PHP_SELF'] . '?action=new'); header('Location: ' . $_SERVER['PHP_SELF'] . '?action=new');
die(); exit();
} }
/** /**
@@ -333,7 +333,7 @@ switch ($_GET['action']) {
echo 'All fields are mandatory!<br>' . PHP_EOL; echo 'All fields are mandatory!<br>' . PHP_EOL;
echo '<a href="' . $_SERVER['PHP_SELF'] . '?action=new">Start again</a>'; echo '<a href="' . $_SERVER['PHP_SELF'] . '?action=new">Start again</a>';
die(); exit();
} }
$_SESSION['clientid'] = $_REQUEST['clientid']; $_SESSION['clientid'] = $_REQUEST['clientid'];
@@ -355,7 +355,7 @@ switch ($_GET['action']) {
echo 'Invalid State! You will have to start again!<br>'; echo 'Invalid State! You will have to start again!<br>';
echo '<a href="' . $_SERVER['PHP_SELF'] . '?action=new">Start again</a>'; echo '<a href="' . $_SERVER['PHP_SELF'] . '?action=new">Start again</a>';
die(); exit();
} }
// Clear the state value. // Clear the state value.

View File

@@ -8,7 +8,7 @@
"ext-json": "*", "ext-json": "*",
"ext-mbstring": "*", "ext-mbstring": "*",
"ext-openssl": "*", "ext-openssl": "*",
"guzzlehttp/guzzle": "^6.2", "guzzlehttp/guzzle": "^6.2|^7.0",
"nesbot/carbon": "^2.0", "nesbot/carbon": "^2.0",
"monolog/monolog": "^2.0", "monolog/monolog": "^2.0",
"predis/predis": "^1.1", "predis/predis": "^1.1",
@@ -18,8 +18,9 @@
"web-token/jwt-signature-algorithm-ecdsa": "^2.1" "web-token/jwt-signature-algorithm-ecdsa": "^2.1"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "^5.7", "phpunit/phpunit": "^8.0|^9.0",
"mikey179/vfsstream": "~1", "mikey179/vfsstream": "~1",
"m6web/redis-mock": "^5.0",
"codeclimate/php-test-reporter": "dev-master" "codeclimate/php-test-reporter": "dev-master"
}, },
"license": "GPL-2.0", "license": "GPL-2.0",

View File

@@ -3,7 +3,7 @@
/* /*
* This file is part of SeAT * This file is part of SeAT
* *
* Copyright (C) 2015 to 2020 Leon Jacobs * Copyright (C) 2015 to 2021 Leon Jacobs
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
* This file is part of SeAT * This file is part of SeAT
* *
* Copyright (C) 2015 to 2020 Leon Jacobs * Copyright (C) 2015 to 2021 Leon Jacobs
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
* This file is part of SeAT * This file is part of SeAT
* *
* Copyright (C) 2015 to 2020 Leon Jacobs * Copyright (C) 2015 to 2021 Leon Jacobs
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
* This file is part of SeAT * This file is part of SeAT
* *
* Copyright (C) 2015 to 2020 Leon Jacobs * Copyright (C) 2015 to 2021 Leon Jacobs
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
* This file is part of SeAT * This file is part of SeAT
* *
* Copyright (C) 2015 to 2020 Leon Jacobs * Copyright (C) 2015 to 2021 Leon Jacobs
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
* This file is part of SeAT * This file is part of SeAT
* *
* Copyright (C) 2015 to 2020 Leon Jacobs * Copyright (C) 2015 to 2021 Leon Jacobs
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
* This file is part of SeAT * This file is part of SeAT
* *
* Copyright (C) 2015 to 2020 Leon Jacobs * Copyright (C) 2015 to 2021 Leon Jacobs
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
* This file is part of SeAT * This file is part of SeAT
* *
* Copyright (C) 2015 to 2020 Leon Jacobs * Copyright (C) 2015 to 2021 Leon Jacobs
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
* This file is part of SeAT * This file is part of SeAT
* *
* Copyright (C) 2015 to 2020 Leon Jacobs * Copyright (C) 2015 to 2021 Leon Jacobs
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
* This file is part of SeAT * This file is part of SeAT
* *
* Copyright (C) 2015 to 2020 Leon Jacobs * Copyright (C) 2015 to 2021 Leon Jacobs
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
* This file is part of SeAT * This file is part of SeAT
* *
* Copyright (C) 2015 to 2020 Leon Jacobs * Copyright (C) 2015 to 2021 Leon Jacobs
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
* This file is part of SeAT * This file is part of SeAT
* *
* Copyright (C) 2015 to 2020 Leon Jacobs * Copyright (C) 2015 to 2021 Leon Jacobs
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
* This file is part of SeAT * This file is part of SeAT
* *
* Copyright (C) 2015 to 2020 Leon Jacobs * Copyright (C) 2015 to 2021 Leon Jacobs
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
* This file is part of SeAT * This file is part of SeAT
* *
* Copyright (C) 2015 to 2020 Leon Jacobs * Copyright (C) 2015 to 2021 Leon Jacobs
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
* This file is part of SeAT * This file is part of SeAT
* *
* Copyright (C) 2015 to 2020 Leon Jacobs * Copyright (C) 2015 to 2021 Leon Jacobs
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
* This file is part of SeAT * This file is part of SeAT
* *
* Copyright (C) 2015 to 2020 Leon Jacobs * Copyright (C) 2015 to 2021 Leon Jacobs
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by

Some files were not shown because too many files have changed in this diff Show More