dependencies-upgrade

This commit is contained in:
RafficMohammed
2023-01-08 02:20:59 +05:30
parent 7870479b18
commit 49021a4497
1711 changed files with 74994 additions and 70803 deletions

6
.idea/community.iml generated
View File

@@ -60,7 +60,6 @@
<excludeFolder url="file://$MODULE_DIR$/vendor/fruitcake/laravel-cors" /> <excludeFolder url="file://$MODULE_DIR$/vendor/fruitcake/laravel-cors" />
<excludeFolder url="file://$MODULE_DIR$/vendor/maennchen/zipstream-php" /> <excludeFolder url="file://$MODULE_DIR$/vendor/maennchen/zipstream-php" />
<excludeFolder url="file://$MODULE_DIR$/vendor/vsmoraes/laravel-pdf" /> <excludeFolder url="file://$MODULE_DIR$/vendor/vsmoraes/laravel-pdf" />
<excludeFolder url="file://$MODULE_DIR$/vendor/fideloper/proxy" />
<excludeFolder url="file://$MODULE_DIR$/vendor/neitanod/forceutf8" /> <excludeFolder url="file://$MODULE_DIR$/vendor/neitanod/forceutf8" />
<excludeFolder url="file://$MODULE_DIR$/vendor/unisharp/laravel-filemanager" /> <excludeFolder url="file://$MODULE_DIR$/vendor/unisharp/laravel-filemanager" />
<excludeFolder url="file://$MODULE_DIR$/vendor/hamcrest/hamcrest-php" /> <excludeFolder url="file://$MODULE_DIR$/vendor/hamcrest/hamcrest-php" />
@@ -142,7 +141,6 @@
<excludeFolder url="file://$MODULE_DIR$/vendor/league/flysystem" /> <excludeFolder url="file://$MODULE_DIR$/vendor/league/flysystem" />
<excludeFolder url="file://$MODULE_DIR$/vendor/league/oauth1-client" /> <excludeFolder url="file://$MODULE_DIR$/vendor/league/oauth1-client" />
<excludeFolder url="file://$MODULE_DIR$/vendor/league/iso3166" /> <excludeFolder url="file://$MODULE_DIR$/vendor/league/iso3166" />
<excludeFolder url="file://$MODULE_DIR$/vendor/guzzle/guzzle" />
<excludeFolder url="file://$MODULE_DIR$/vendor/league/mime-type-detection" /> <excludeFolder url="file://$MODULE_DIR$/vendor/league/mime-type-detection" />
<excludeFolder url="file://$MODULE_DIR$/vendor/facade/ignition-contracts" /> <excludeFolder url="file://$MODULE_DIR$/vendor/facade/ignition-contracts" />
<excludeFolder url="file://$MODULE_DIR$/vendor/flowjs/flow-php-server" /> <excludeFolder url="file://$MODULE_DIR$/vendor/flowjs/flow-php-server" />
@@ -162,6 +160,10 @@
<excludeFolder url="file://$MODULE_DIR$/vendor/voku/portable-ascii" /> <excludeFolder url="file://$MODULE_DIR$/vendor/voku/portable-ascii" />
<excludeFolder url="file://$MODULE_DIR$/vendor/psy/psysh" /> <excludeFolder url="file://$MODULE_DIR$/vendor/psy/psysh" />
<excludeFolder url="file://$MODULE_DIR$/vendor/filp/whoops" /> <excludeFolder url="file://$MODULE_DIR$/vendor/filp/whoops" />
<excludeFolder url="file://$MODULE_DIR$/vendor/laravel/serializable-closure" />
<excludeFolder url="file://$MODULE_DIR$/vendor/graham-campbell/result-type" />
<excludeFolder url="file://$MODULE_DIR$/vendor/maximebf/debugbar" />
<excludeFolder url="file://$MODULE_DIR$/vendor/barryvdh/laravel-debugbar" />
</content> </content>
<orderEntry type="inheritedJdk" /> <orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />

6
.idea/php.xml generated
View File

@@ -57,7 +57,6 @@
<path value="$PROJECT_DIR$/vendor/fruitcake/laravel-cors" /> <path value="$PROJECT_DIR$/vendor/fruitcake/laravel-cors" />
<path value="$PROJECT_DIR$/vendor/maennchen/zipstream-php" /> <path value="$PROJECT_DIR$/vendor/maennchen/zipstream-php" />
<path value="$PROJECT_DIR$/vendor/vsmoraes/laravel-pdf" /> <path value="$PROJECT_DIR$/vendor/vsmoraes/laravel-pdf" />
<path value="$PROJECT_DIR$/vendor/fideloper/proxy" />
<path value="$PROJECT_DIR$/vendor/neitanod/forceutf8" /> <path value="$PROJECT_DIR$/vendor/neitanod/forceutf8" />
<path value="$PROJECT_DIR$/vendor/unisharp/laravel-filemanager" /> <path value="$PROJECT_DIR$/vendor/unisharp/laravel-filemanager" />
<path value="$PROJECT_DIR$/vendor/hamcrest/hamcrest-php" /> <path value="$PROJECT_DIR$/vendor/hamcrest/hamcrest-php" />
@@ -139,7 +138,6 @@
<path value="$PROJECT_DIR$/vendor/league/flysystem" /> <path value="$PROJECT_DIR$/vendor/league/flysystem" />
<path value="$PROJECT_DIR$/vendor/league/oauth1-client" /> <path value="$PROJECT_DIR$/vendor/league/oauth1-client" />
<path value="$PROJECT_DIR$/vendor/league/iso3166" /> <path value="$PROJECT_DIR$/vendor/league/iso3166" />
<path value="$PROJECT_DIR$/vendor/guzzle/guzzle" />
<path value="$PROJECT_DIR$/vendor/league/mime-type-detection" /> <path value="$PROJECT_DIR$/vendor/league/mime-type-detection" />
<path value="$PROJECT_DIR$/vendor/facade/ignition-contracts" /> <path value="$PROJECT_DIR$/vendor/facade/ignition-contracts" />
<path value="$PROJECT_DIR$/vendor/flowjs/flow-php-server" /> <path value="$PROJECT_DIR$/vendor/flowjs/flow-php-server" />
@@ -159,6 +157,10 @@
<path value="$PROJECT_DIR$/vendor/voku/portable-ascii" /> <path value="$PROJECT_DIR$/vendor/voku/portable-ascii" />
<path value="$PROJECT_DIR$/vendor/psy/psysh" /> <path value="$PROJECT_DIR$/vendor/psy/psysh" />
<path value="$PROJECT_DIR$/vendor/filp/whoops" /> <path value="$PROJECT_DIR$/vendor/filp/whoops" />
<path value="$PROJECT_DIR$/vendor/laravel/serializable-closure" />
<path value="$PROJECT_DIR$/vendor/graham-campbell/result-type" />
<path value="$PROJECT_DIR$/vendor/maximebf/debugbar" />
<path value="$PROJECT_DIR$/vendor/barryvdh/laravel-debugbar" />
</include_path> </include_path>
</component> </component>
<component name="PhpProjectSharedConfiguration" php_language_level="7.2" /> <component name="PhpProjectSharedConfiguration" php_language_level="7.2" />

View File

@@ -45,7 +45,8 @@
"nunomaduro/collision": "^5.10", "nunomaduro/collision": "^5.10",
"mockery/mockery": "^1.4.4", "mockery/mockery": "^1.4.4",
"fakerphp/faker": "^1.9.1", "fakerphp/faker": "^1.9.1",
"facade/ignition": "^2.5" "facade/ignition": "^2.5",
"barryvdh/laravel-debugbar": "^3.7"
}, },
"autoload": { "autoload": {
"classmap": [ "classmap": [

911
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -180,7 +180,7 @@ return [
App\FaveoStorage\StorageServiceProvider::class, App\FaveoStorage\StorageServiceProvider::class,
Yajra\Datatables\DatatablesServiceProvider::class, Yajra\Datatables\DatatablesServiceProvider::class,
\App\Api\ApiServiceProvider::class, \App\Api\ApiServiceProvider::class,
Barryvdh\Debugbar\ServiceProvider::class,
], ],
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
@@ -204,6 +204,7 @@ return [
'Crypt' => 'Illuminate\Support\Facades\Crypt', 'Crypt' => 'Illuminate\Support\Facades\Crypt',
'Date' => Illuminate\Support\Facades\Date::class, 'Date' => Illuminate\Support\Facades\Date::class,
'DB' => 'Illuminate\Support\Facades\DB', 'DB' => 'Illuminate\Support\Facades\DB',
'Debugbar' => Barryvdh\Debugbar\Facades\Debugbar::class,
'Eloquent' => 'Illuminate\Database\Eloquent\Model', 'Eloquent' => 'Illuminate\Database\Eloquent\Model',
'Event' => 'Illuminate\Support\Facades\Event', 'Event' => 'Illuminate\Support\Facades\Event',
'File' => 'Illuminate\Support\Facades\File', 'File' => 'Illuminate\Support\Facades\File',

2
vendor/autoload.php vendored
View File

@@ -9,4 +9,4 @@ if (PHP_VERSION_ID < 50600) {
require_once __DIR__ . '/composer/autoload_real.php'; require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInit9da6744efcb5435630815fb416a6752c::getLoader(); return ComposerAutoloaderInite3a664ccc4def6142d1c80482606ee61::getLoader();

View File

@@ -0,0 +1,19 @@
Copyright (C) 2013-present Barry vd. Heuvel
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,5 @@
# Security Policy
## Reporting a Vulnerability
Please report security issues to `barryvdh@gmail.com`

View File

@@ -0,0 +1,59 @@
{
"name": "barryvdh/laravel-debugbar",
"description": "PHP Debugbar integration for Laravel",
"keywords": ["laravel", "debugbar", "profiler", "debug", "webprofiler"],
"license": "MIT",
"authors": [
{
"name": "Barry vd. Heuvel",
"email": "barryvdh@gmail.com"
}
],
"require": {
"php": ">=7.2.5",
"maximebf/debugbar": "^1.17.2",
"illuminate/routing": "^7|^8|^9",
"illuminate/session": "^7|^8|^9",
"illuminate/support": "^7|^8|^9",
"symfony/finder": "^5|^6"
},
"require-dev": {
"mockery/mockery": "^1.3.3",
"orchestra/testbench-dusk": "^5|^6|^7",
"phpunit/phpunit": "^8.5|^9.0",
"squizlabs/php_codesniffer": "^3.5"
},
"autoload": {
"psr-4": {
"Barryvdh\\Debugbar\\": "src/"
},
"files": [
"src/helpers.php"
]
},
"autoload-dev": {
"psr-4": {
"Barryvdh\\Debugbar\\Tests\\": "tests"
}
},
"minimum-stability": "dev",
"prefer-stable": true,
"extra": {
"branch-alias": {
"dev-master": "3.6-dev"
},
"laravel": {
"providers": [
"Barryvdh\\Debugbar\\ServiceProvider"
],
"aliases": {
"Debugbar": "Barryvdh\\Debugbar\\Facades\\Debugbar"
}
}
},
"scripts": {
"check-style": "phpcs -p --standard=PSR12 config/ src/ tests/",
"fix-style": "phpcbf -p --standard=PSR12 config/ src/ tests/",
"test": "phpunit"
}
}

View File

@@ -0,0 +1,275 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Debugbar Settings
|--------------------------------------------------------------------------
|
| Debugbar is enabled by default, when debug is set to true in app.php.
| You can override the value by setting enable to true or false instead of null.
|
| You can provide an array of URI's that must be ignored (eg. 'api/*')
|
*/
'enabled' => env('DEBUGBAR_ENABLED', null),
'except' => [
'telescope*',
'horizon*',
],
/*
|--------------------------------------------------------------------------
| Storage settings
|--------------------------------------------------------------------------
|
| DebugBar stores data for session/ajax requests.
| You can disable this, so the debugbar stores data in headers/session,
| but this can cause problems with large data collectors.
| By default, file storage (in the storage folder) is used. Redis and PDO
| can also be used. For PDO, run the package migrations first.
|
*/
'storage' => [
'enabled' => true,
'driver' => 'file', // redis, file, pdo, socket, custom
'path' => storage_path('debugbar'), // For file driver
'connection' => null, // Leave null for default connection (Redis/PDO)
'provider' => '', // Instance of StorageInterface for custom driver
'hostname' => '127.0.0.1', // Hostname to use with the "socket" driver
'port' => 2304, // Port to use with the "socket" driver
],
/*
|--------------------------------------------------------------------------
| Editor
|--------------------------------------------------------------------------
|
| Choose your preferred editor to use when clicking file name.
|
| Supported: "phpstorm", "vscode", "vscode-insiders", "vscode-remote",
| "vscode-insiders-remote", "vscodium", "textmate", "emacs",
| "sublime", "atom", "nova", "macvim", "idea", "netbeans",
| "xdebug", "espresso"
|
*/
'editor' => env('DEBUGBAR_EDITOR', 'phpstorm'),
/*
|--------------------------------------------------------------------------
| Remote Path Mapping
|--------------------------------------------------------------------------
|
| If you are using a remote dev server, like Laravel Homestead, Docker, or
| even a remote VPS, it will be necessary to specify your path mapping.
|
| Leaving one, or both of these, empty or null will not trigger the remote
| URL changes and Debugbar will treat your editor links as local files.
|
| "remote_sites_path" is an absolute base path for your sites or projects
| in Homestead, Vagrant, Docker, or another remote development server.
|
| Example value: "/home/vagrant/Code"
|
| "local_sites_path" is an absolute base path for your sites or projects
| on your local computer where your IDE or code editor is running on.
|
| Example values: "/Users/<name>/Code", "C:\Users\<name>\Documents\Code"
|
*/
'remote_sites_path' => env('DEBUGBAR_REMOTE_SITES_PATH', ''),
'local_sites_path' => env('DEBUGBAR_LOCAL_SITES_PATH', ''),
/*
|--------------------------------------------------------------------------
| Vendors
|--------------------------------------------------------------------------
|
| Vendor files are included by default, but can be set to false.
| This can also be set to 'js' or 'css', to only include javascript or css vendor files.
| Vendor files are for css: font-awesome (including fonts) and highlight.js (css files)
| and for js: jquery and and highlight.js
| So if you want syntax highlighting, set it to true.
| jQuery is set to not conflict with existing jQuery scripts.
|
*/
'include_vendors' => true,
/*
|--------------------------------------------------------------------------
| Capture Ajax Requests
|--------------------------------------------------------------------------
|
| The Debugbar can capture Ajax requests and display them. If you don't want this (ie. because of errors),
| you can use this option to disable sending the data through the headers.
|
| Optionally, you can also send ServerTiming headers on ajax requests for the Chrome DevTools.
|
| Note for your request to be identified as ajax requests they must either send the header
| X-Requested-With with the value XMLHttpRequest (most JS libraries send this), or have application/json as a Accept header.
*/
'capture_ajax' => true,
'add_ajax_timing' => false,
/*
|--------------------------------------------------------------------------
| Custom Error Handler for Deprecated warnings
|--------------------------------------------------------------------------
|
| When enabled, the Debugbar shows deprecated warnings for Symfony components
| in the Messages tab.
|
*/
'error_handler' => false,
/*
|--------------------------------------------------------------------------
| Clockwork integration
|--------------------------------------------------------------------------
|
| The Debugbar can emulate the Clockwork headers, so you can use the Chrome
| Extension, without the server-side code. It uses Debugbar collectors instead.
|
*/
'clockwork' => false,
/*
|--------------------------------------------------------------------------
| DataCollectors
|--------------------------------------------------------------------------
|
| Enable/disable DataCollectors
|
*/
'collectors' => [
'phpinfo' => true, // Php version
'messages' => true, // Messages
'time' => true, // Time Datalogger
'memory' => true, // Memory usage
'exceptions' => true, // Exception displayer
'log' => true, // Logs from Monolog (merged in messages if enabled)
'db' => true, // Show database (PDO) queries and bindings
'views' => true, // Views with their data
'route' => true, // Current route information
'auth' => false, // Display Laravel authentication status
'gate' => true, // Display Laravel Gate checks
'session' => true, // Display session data
'symfony_request' => true, // Only one can be enabled..
'mail' => true, // Catch mail messages
'laravel' => false, // Laravel version and environment
'events' => false, // All events fired
'default_request' => false, // Regular or special Symfony request logger
'logs' => false, // Add the latest log messages
'files' => false, // Show the included files
'config' => false, // Display config settings
'cache' => false, // Display cache events
'models' => true, // Display models
'livewire' => true, // Display Livewire (when available)
],
/*
|--------------------------------------------------------------------------
| Extra options
|--------------------------------------------------------------------------
|
| Configure some DataCollectors
|
*/
'options' => [
'auth' => [
'show_name' => true, // Also show the users name/email in the debugbar
],
'db' => [
'with_params' => true, // Render SQL with the parameters substituted
'backtrace' => true, // Use a backtrace to find the origin of the query in your files.
'backtrace_exclude_paths' => [], // Paths to exclude from backtrace. (in addition to defaults)
'timeline' => false, // Add the queries to the timeline
'duration_background' => true, // Show shaded background on each query relative to how long it took to execute.
'explain' => [ // Show EXPLAIN output on queries
'enabled' => false,
'types' => ['SELECT'], // Deprecated setting, is always only SELECT
],
'hints' => false, // Show hints for common mistakes
'show_copy' => false, // Show copy button next to the query
],
'mail' => [
'full_log' => false,
],
'views' => [
'timeline' => false, // Add the views to the timeline (Experimental)
'data' => false, //Note: Can slow down the application, because the data can be quite large..
],
'route' => [
'label' => true, // show complete route on bar
],
'logs' => [
'file' => null,
],
'cache' => [
'values' => true, // collect cache values
],
],
/*
|--------------------------------------------------------------------------
| Inject Debugbar in Response
|--------------------------------------------------------------------------
|
| Usually, the debugbar is added just before </body>, by listening to the
| Response after the App is done. If you disable this, you have to add them
| in your template yourself. See http://phpdebugbar.com/docs/rendering.html
|
*/
'inject' => true,
/*
|--------------------------------------------------------------------------
| DebugBar route prefix
|--------------------------------------------------------------------------
|
| Sometimes you want to set route prefix to be used by DebugBar to load
| its resources from. Usually the need comes from misconfigured web server or
| from trying to overcome bugs like this: http://trac.nginx.org/nginx/ticket/97
|
*/
'route_prefix' => '_debugbar',
/*
|--------------------------------------------------------------------------
| DebugBar route domain
|--------------------------------------------------------------------------
|
| By default DebugBar route served from the same domain that request served.
| To override default domain, specify it as a non-empty value.
*/
'route_domain' => null,
/*
|--------------------------------------------------------------------------
| DebugBar theme
|--------------------------------------------------------------------------
|
| Switches between light and dark theme. If set to auto it will respect system preferences
| Possible values: auto, light, dark
*/
'theme' => env('DEBUGBAR_THEME', 'auto'),
/*
|--------------------------------------------------------------------------
| Backtrace stack limit
|--------------------------------------------------------------------------
|
| By default, the DebugBar limits the number of frames returned by the 'debug_backtrace()' function.
| If you need larger stacktraces, you can increase this number. Setting it to 0 will result in no limit.
*/
'debug_backtrace_limit' => 50,
];

View File

@@ -0,0 +1,42 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreatePhpdebugbarStorageTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('phpdebugbar', function (Blueprint $table) {
$table->string('id');
$table->longText('data');
$table->string('meta_utime');
$table->dateTime('meta_datetime');
$table->string('meta_uri');
$table->string('meta_ip');
$table->string('meta_method');
$table->primary('id');
$table->index('meta_utime');
$table->index('meta_datetime');
$table->index('meta_uri');
$table->index('meta_ip');
$table->index('meta_method');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop('phpdebugbar');
}
}

View File

@@ -0,0 +1,213 @@
## Laravel Debugbar
![Unit Tests](https://github.com/barryvdh/laravel-debugbar/workflows/Unit%20Tests/badge.svg)
[![Packagist License](https://poser.pugx.org/barryvdh/laravel-debugbar/license.png)](http://choosealicense.com/licenses/mit/)
[![Latest Stable Version](https://poser.pugx.org/barryvdh/laravel-debugbar/version.png)](https://packagist.org/packages/barryvdh/laravel-debugbar)
[![Total Downloads](https://poser.pugx.org/barryvdh/laravel-debugbar/d/total.png)](https://packagist.org/packages/barryvdh/laravel-debugbar)
[![Fruitcake](https://img.shields.io/badge/Powered%20By-Fruitcake-b2bc35.svg)](https://fruitcake.nl/)
This is a package to integrate [PHP Debug Bar](http://phpdebugbar.com/) with Laravel.
It includes a ServiceProvider to register the debugbar and attach it to the output. You can publish assets and configure it through Laravel.
It bootstraps some Collectors to work with Laravel and implements a couple custom DataCollectors, specific for Laravel.
It is configured to display Redirects and (jQuery) Ajax Requests. (Shown in a dropdown)
Read [the documentation](http://phpdebugbar.com/docs/) for more configuration options.
![Debugbar 3.3 Screenshot](https://user-images.githubusercontent.com/973269/79428890-196cc680-7fc7-11ea-8229-189f5eac9009.png)
Note: Use the DebugBar only in development. It can slow the application down (because it has to gather data). So when experiencing slowness, try disabling some of the collectors.
This package includes some custom collectors:
- QueryCollector: Show all queries, including binding + timing
- RouteCollector: Show information about the current Route.
- ViewCollector: Show the currently loaded views. (Optionally: display the shared data)
- EventsCollector: Show all events
- LaravelCollector: Show the Laravel version and Environment. (disabled by default)
- SymfonyRequestCollector: replaces the RequestCollector with more information about the request/response
- LogsCollector: Show the latest log entries from the storage logs. (disabled by default)
- FilesCollector: Show the files that are included/required by PHP. (disabled by default)
- ConfigCollector: Display the values from the config files. (disabled by default)
- CacheCollector: Display all cache events. (disabled by default)
Bootstraps the following collectors for Laravel:
- LogCollector: Show all Log messages
- SwiftMailCollector and SwiftLogCollector for Mail
And the default collectors:
- PhpInfoCollector
- MessagesCollector
- TimeDataCollector (With Booting and Application timing)
- MemoryCollector
- ExceptionsCollector
It also provides a facade interface (`Debugbar`) for easy logging Messages, Exceptions and Time
## Installation
Require this package with composer. It is recommended to only require the package for development.
```shell
composer require barryvdh/laravel-debugbar --dev
```
Laravel uses Package Auto-Discovery, so doesn't require you to manually add the ServiceProvider.
The Debugbar will be enabled when `APP_DEBUG` is `true`.
> If you use a catch-all/fallback route, make sure you load the Debugbar ServiceProvider before your own App ServiceProviders.
### Laravel without auto-discovery:
If you don't use auto-discovery, add the ServiceProvider to the providers array in config/app.php
```php
Barryvdh\Debugbar\ServiceProvider::class,
```
If you want to use the facade to log messages, add this to your facades in app.php:
```php
'Debugbar' => Barryvdh\Debugbar\Facades\Debugbar::class,
```
The profiler is enabled by default, if you have APP_DEBUG=true. You can override that in the config (`debugbar.enabled`) or by setting `DEBUGBAR_ENABLED` in your `.env`. See more options in `config/debugbar.php`
You can also set in your config if you want to include/exclude the vendor files also (FontAwesome, Highlight.js and jQuery). If you already use them in your site, set it to false.
You can also only display the js or css vendors, by setting it to 'js' or 'css'. (Highlight.js requires both css + js, so set to `true` for syntax highlighting)
#### Copy the package config to your local config with the publish command:
```shell
php artisan vendor:publish --provider="Barryvdh\Debugbar\ServiceProvider"
```
### Laravel with Octane:
Make sure to add LaravelDebugbar to your flush list in `config/octane.php`.
```php
'flush' => [
\Barryvdh\Debugbar\LaravelDebugbar::class,
],
```
### Lumen:
For Lumen, register a different Provider in `bootstrap/app.php`:
```php
if (env('APP_DEBUG')) {
$app->register(Barryvdh\Debugbar\LumenServiceProvider::class);
}
```
To change the configuration, copy the file to your config folder and enable it:
```php
$app->configure('debugbar');
```
## Usage
You can now add messages using the Facade (when added), using the PSR-3 levels (debug, info, notice, warning, error, critical, alert, emergency):
```php
Debugbar::info($object);
Debugbar::error('Error!');
Debugbar::warning('Watch out…');
Debugbar::addMessage('Another message', 'mylabel');
```
And start/stop timing:
```php
Debugbar::startMeasure('render','Time for rendering');
Debugbar::stopMeasure('render');
Debugbar::addMeasure('now', LARAVEL_START, microtime(true));
Debugbar::measure('My long operation', function() {
// Do something…
});
```
Or log exceptions:
```php
try {
throw new Exception('foobar');
} catch (Exception $e) {
Debugbar::addThrowable($e);
}
```
There are also helper functions available for the most common calls:
```php
// All arguments will be dumped as a debug message
debug($var1, $someString, $intValue, $object);
// `$collection->debug()` will return the collection and dump it as a debug message. Like `$collection->dump()`
collect([$var1, $someString])->debug();
start_measure('render','Time for rendering');
stop_measure('render');
add_measure('now', LARAVEL_START, microtime(true));
measure('My long operation', function() {
// Do something…
});
```
If you want you can add your own DataCollectors, through the Container or the Facade:
```php
Debugbar::addCollector(new DebugBar\DataCollector\MessagesCollector('my_messages'));
//Or via the App container:
$debugbar = App::make('debugbar');
$debugbar->addCollector(new DebugBar\DataCollector\MessagesCollector('my_messages'));
```
By default, the Debugbar is injected just before `</body>`. If you want to inject the Debugbar yourself,
set the config option 'inject' to false and use the renderer yourself and follow http://phpdebugbar.com/docs/rendering.html
```php
$renderer = Debugbar::getJavascriptRenderer();
```
Note: Not using the auto-inject, will disable the Request information, because that is added After the response.
You can add the default_request datacollector in the config as alternative.
## Enabling/Disabling on run time
You can enable or disable the debugbar during run time.
```php
\Debugbar::enable();
\Debugbar::disable();
```
NB. Once enabled, the collectors are added (and could produce extra overhead), so if you want to use the debugbar in production, disable in the config and only enable when needed.
## Twig Integration
Laravel Debugbar comes with two Twig Extensions. These are tested with [rcrowe/TwigBridge](https://github.com/rcrowe/TwigBridge) 0.6.x
Add the following extensions to your TwigBridge config/extensions.php (or register the extensions manually)
```php
'Barryvdh\Debugbar\Twig\Extension\Debug',
'Barryvdh\Debugbar\Twig\Extension\Dump',
'Barryvdh\Debugbar\Twig\Extension\Stopwatch',
```
The Dump extension will replace the [dump function](http://twig.sensiolabs.org/doc/functions/dump.html) to output variables using the DataFormatter. The Debug extension adds a `debug()` function which passes variables to the Message Collector,
instead of showing it directly in the template. It dumps the arguments, or when empty; all context variables.
```twig
{{ debug() }}
{{ debug(user, categories) }}
```
The Stopwatch extension adds a [stopwatch tag](http://symfony.com/blog/new-in-symfony-2-4-a-stopwatch-tag-for-twig) similar to the one in Symfony/Silex Twigbridge.
```twig
{% stopwatch "foo" %}
…some things that gets timed
{% endstopwatch %}
```

View File

@@ -0,0 +1,39 @@
<?php
namespace Barryvdh\Debugbar\Console;
use DebugBar\DebugBar;
use Illuminate\Console\Command;
class ClearCommand extends Command
{
protected $name = 'debugbar:clear';
protected $description = 'Clear the Debugbar Storage';
protected $debugbar;
public function __construct(DebugBar $debugbar)
{
$this->debugbar = $debugbar;
parent::__construct();
}
public function handle()
{
$this->debugbar->boot();
if ($storage = $this->debugbar->getStorage()) {
try {
$storage->clear();
} catch (\InvalidArgumentException $e) {
// hide InvalidArgumentException if storage location does not exist
if (strpos($e->getMessage(), 'does not exist') === false) {
throw $e;
}
}
$this->info('Debugbar Storage cleared!');
} else {
$this->error('No Debugbar Storage found..');
}
}
}

View File

@@ -0,0 +1,64 @@
<?php
namespace Barryvdh\Debugbar\Controllers;
use Illuminate\Http\Response;
class AssetController extends BaseController
{
/**
* Return the javascript for the Debugbar
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function js()
{
$renderer = $this->debugbar->getJavascriptRenderer();
$content = $renderer->dumpAssetsToString('js');
$response = new Response(
$content,
200,
[
'Content-Type' => 'text/javascript',
]
);
return $this->cacheResponse($response);
}
/**
* Return the stylesheets for the Debugbar
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function css()
{
$renderer = $this->debugbar->getJavascriptRenderer();
$content = $renderer->dumpAssetsToString('css');
$response = new Response(
$content,
200,
[
'Content-Type' => 'text/css',
]
);
return $this->cacheResponse($response);
}
/**
* Cache the response 1 year (31536000 sec)
*/
protected function cacheResponse(Response $response)
{
$response->setSharedMaxAge(31536000);
$response->setMaxAge(31536000);
$response->setExpires(new \DateTime('+1 year'));
return $response;
}
}

View File

@@ -0,0 +1,49 @@
<?php
namespace Barryvdh\Debugbar\Controllers;
use Barryvdh\Debugbar\LaravelDebugbar;
use Illuminate\Routing\Controller;
use Illuminate\Http\Request;
use Laravel\Telescope\Telescope;
// phpcs:ignoreFile
if (class_exists('Illuminate\Routing\Controller')) {
class BaseController extends Controller
{
protected $debugbar;
public function __construct(Request $request, LaravelDebugbar $debugbar)
{
$this->debugbar = $debugbar;
if ($request->hasSession()) {
$request->session()->reflash();
}
$this->middleware(function ($request, $next) {
if (class_exists(Telescope::class)) {
Telescope::stopRecording();
}
return $next($request);
});
}
}
} else {
class BaseController
{
protected $debugbar;
public function __construct(Request $request, LaravelDebugbar $debugbar)
{
$this->debugbar = $debugbar;
if ($request->hasSession()) {
$request->session()->reflash();
}
}
}
}

View File

@@ -0,0 +1,28 @@
<?php
namespace Barryvdh\Debugbar\Controllers;
use Illuminate\Http\Response;
class CacheController extends BaseController
{
/**
* Forget a cache key
*
*/
public function delete($key, $tags = '')
{
$cache = app('cache');
if (!empty($tags)) {
$tags = json_decode($tags, true);
$cache = $cache->tags($tags);
} else {
unset($tags);
}
$success = $cache->forget($key);
return response()->json(compact('success'));
}
}

View File

@@ -0,0 +1,49 @@
<?php
namespace Barryvdh\Debugbar\Controllers;
use Barryvdh\Debugbar\Support\Clockwork\Converter;
use DebugBar\OpenHandler;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
class OpenHandlerController extends BaseController
{
public function handle(Request $request)
{
$openHandler = new OpenHandler($this->debugbar);
$data = $openHandler->handle($request->input(), false, false);
return new Response(
$data,
200,
[
'Content-Type' => 'application/json'
]
);
}
/**
* Return Clockwork output
*
* @param $id
* @return mixed
* @throws \DebugBar\DebugBarException
*/
public function clockwork($id)
{
$request = [
'op' => 'get',
'id' => $id,
];
$openHandler = new OpenHandler($this->debugbar);
$data = $openHandler->handle($request, false, false);
// Convert to Clockwork
$converter = new Converter();
$output = $converter->convert(json_decode($data, true));
return response()->json($output);
}
}

View File

@@ -0,0 +1,23 @@
<?php
namespace Barryvdh\Debugbar\Controllers;
use Barryvdh\Debugbar\Support\Clockwork\Converter;
use DebugBar\OpenHandler;
use Illuminate\Http\Response;
use Laravel\Telescope\Contracts\EntriesRepository;
use Laravel\Telescope\IncomingEntry;
use Laravel\Telescope\Storage\EntryQueryOptions;
use Laravel\Telescope\Telescope;
class TelescopeController extends BaseController
{
public function show(EntriesRepository $storage, $uuid)
{
$entry = $storage->find($uuid);
$result = $storage->get('request', (new EntryQueryOptions())->batchId($entry->batchId))->first();
return redirect(config('telescope.path') . '/requests/' . $result->id);
}
}

View File

@@ -0,0 +1,96 @@
<?php
namespace Barryvdh\Debugbar\DataCollector;
use DebugBar\DataCollector\TimeDataCollector;
use Illuminate\Cache\Events\CacheEvent;
use Illuminate\Cache\Events\CacheHit;
use Illuminate\Cache\Events\CacheMissed;
use Illuminate\Cache\Events\KeyForgotten;
use Illuminate\Cache\Events\KeyWritten;
use Illuminate\Events\Dispatcher;
class CacheCollector extends TimeDataCollector
{
/** @var bool */
protected $collectValues;
/** @var array */
protected $classMap = [
CacheHit::class => 'hit',
CacheMissed::class => 'missed',
KeyWritten::class => 'written',
KeyForgotten::class => 'forgotten',
];
public function __construct($requestStartTime, $collectValues)
{
parent::__construct();
$this->collectValues = $collectValues;
}
public function onCacheEvent(CacheEvent $event)
{
$class = get_class($event);
$params = get_object_vars($event);
$label = $this->classMap[$class];
if (isset($params['value'])) {
if ($this->collectValues) {
$params['value'] = htmlspecialchars($this->getDataFormatter()->formatVar($event->value));
} else {
unset($params['value']);
}
}
if (!empty($params['key']) && in_array($label, ['hit', 'written'])) {
$params['delete'] = route('debugbar.cache.delete', [
'key' => urlencode($params['key']),
'tags' => !empty($params['tags']) ? json_encode($params['tags']) : '',
]);
}
$time = microtime(true);
$this->addMeasure($label . "\t" . $event->key, $time, $time, $params);
}
public function subscribe(Dispatcher $dispatcher)
{
foreach ($this->classMap as $eventClass => $type) {
$dispatcher->listen($eventClass, [$this, 'onCacheEvent']);
}
}
public function collect()
{
$data = parent::collect();
$data['nb_measures'] = count($data['measures']);
return $data;
}
public function getName()
{
return 'cache';
}
public function getWidgets()
{
return [
'cache' => [
'icon' => 'clipboard',
'widget' => 'PhpDebugBar.Widgets.LaravelCacheWidget',
'map' => 'cache',
'default' => '{}',
],
'cache:badge' => [
'map' => 'cache.nb_measures',
'default' => 'null',
],
];
}
}

View File

@@ -0,0 +1,116 @@
<?php
namespace Barryvdh\Debugbar\DataCollector;
use Barryvdh\Debugbar\DataFormatter\SimpleFormatter;
use DebugBar\DataCollector\TimeDataCollector;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Support\Str;
use Symfony\Component\VarDumper\Cloner\VarCloner;
class EventCollector extends TimeDataCollector
{
/** @var Dispatcher */
protected $events;
/** @var integer */
protected $previousTime;
public function __construct($requestStartTime = null)
{
parent::__construct($requestStartTime);
$this->previousTime = microtime(true);
$this->setDataFormatter(new SimpleFormatter());
}
public function onWildcardEvent($name = null, $data = [])
{
$params = $this->prepareParams($data);
$currentTime = microtime(true);
// Find all listeners for the current event
foreach ($this->events->getListeners($name) as $i => $listener) {
// Check if it's an object + method name
if (is_array($listener) && count($listener) > 1 && is_object($listener[0])) {
list($class, $method) = $listener;
// Skip this class itself
if ($class instanceof static) {
continue;
}
// Format the listener to readable format
$listener = get_class($class) . '@' . $method;
// Handle closures
} elseif ($listener instanceof \Closure) {
$reflector = new \ReflectionFunction($listener);
// Skip our own listeners
if ($reflector->getNamespaceName() == 'Barryvdh\Debugbar') {
continue;
}
// Format the closure to a readable format
$filename = ltrim(str_replace(base_path(), '', $reflector->getFileName()), '/');
$lines = $reflector->getStartLine() . '-' . $reflector->getEndLine();
$listener = $reflector->getName() . ' (' . $filename . ':' . $lines . ')';
} else {
// Not sure if this is possible, but to prevent edge cases
$listener = $this->getDataFormatter()->formatVar($listener);
}
$params['listeners.' . $i] = $listener;
}
$this->addMeasure($name, $this->previousTime, $currentTime, $params);
$this->previousTime = $currentTime;
}
public function subscribe(Dispatcher $events)
{
$this->events = $events;
$events->listen('*', [$this, 'onWildcardEvent']);
}
protected function prepareParams($params)
{
$data = [];
foreach ($params as $key => $value) {
if (is_object($value) && Str::is('Illuminate\*\Events\*', get_class($value))) {
$value = $this->prepareParams(get_object_vars($value));
}
$data[$key] = htmlentities($this->getDataFormatter()->formatVar($value), ENT_QUOTES, 'UTF-8', false);
}
return $data;
}
public function collect()
{
$data = parent::collect();
$data['nb_measures'] = count($data['measures']);
return $data;
}
public function getName()
{
return 'event';
}
public function getWidgets()
{
return [
"events" => [
"icon" => "tasks",
"widget" => "PhpDebugBar.Widgets.TimelineWidget",
"map" => "event",
"default" => "{}",
],
'events:badge' => [
'map' => 'event.nb_measures',
'default' => 0,
],
];
}
}

View File

@@ -0,0 +1,136 @@
<?php
namespace Barryvdh\Debugbar\DataCollector;
use DebugBar\DataCollector\DataCollector;
use DebugBar\DataCollector\Renderable;
use Illuminate\Container\Container;
class FilesCollector extends DataCollector implements Renderable
{
/** @var \Illuminate\Container\Container */
protected $app;
protected $basePath;
/**
* @param \Illuminate\Container\Container $app
*/
public function __construct(Container $app = null)
{
$this->app = $app;
$this->basePath = base_path();
}
/**
* {@inheritDoc}
*/
public function collect()
{
$files = $this->getIncludedFiles();
$compiled = $this->getCompiledFiles();
$included = [];
$alreadyCompiled = [];
foreach ($files as $file) {
// Skip the files from Debugbar, they are only loaded for Debugging and confuse the output.
// Of course some files are stil always loaded (ServiceProvider, Facade etc)
if (
strpos($file, 'vendor/maximebf/debugbar/src') !== false || strpos(
$file,
'vendor/barryvdh/laravel-debugbar/src'
) !== false
) {
continue;
} elseif (!in_array($file, $compiled)) {
$included[] = [
'message' => "'" . $this->stripBasePath($file) . "',",
// Use PHP syntax so we can copy-paste to compile config file.
'is_string' => true,
];
} else {
$alreadyCompiled[] = [
'message' => "* '" . $this->stripBasePath($file) . "',",
// Mark with *, so know they are compiled anyways.
'is_string' => true,
];
}
}
// First the included files, then those that are going to be compiled.
$messages = array_merge($included, $alreadyCompiled);
return [
'messages' => $messages,
'count' => count($included),
];
}
/**
* Get the files included on load.
*
* @return array
*/
protected function getIncludedFiles()
{
return get_included_files();
}
/**
* Get the files that are going to be compiled, so they aren't as important.
*
* @return array
*/
protected function getCompiledFiles()
{
if ($this->app && class_exists('Illuminate\Foundation\Console\OptimizeCommand')) {
$reflector = new \ReflectionClass('Illuminate\Foundation\Console\OptimizeCommand');
$path = dirname($reflector->getFileName()) . '/Optimize/config.php';
if (file_exists($path)) {
$app = $this->app;
$core = require $path;
return array_merge($core, $app['config']['compile']);
}
}
return [];
}
/**
* Remove the basePath from the paths, so they are relative to the base
*
* @param $path
* @return string
*/
protected function stripBasePath($path)
{
return ltrim(str_replace($this->basePath, '', $path), '/');
}
/**
* {@inheritDoc}
*/
public function getWidgets()
{
$name = $this->getName();
return [
"$name" => [
"icon" => "files-o",
"widget" => "PhpDebugBar.Widgets.MessagesWidget",
"map" => "$name.messages",
"default" => "{}"
],
"$name:badge" => [
"map" => "$name.count",
"default" => "null"
]
];
}
/**
* {@inheritDoc}
*/
public function getName()
{
return 'files';
}
}

View File

@@ -0,0 +1,54 @@
<?php
namespace Barryvdh\Debugbar\DataCollector;
use Barryvdh\Debugbar\DataFormatter\SimpleFormatter;
use DebugBar\DataCollector\MessagesCollector;
use Illuminate\Auth\Access\Response;
use Illuminate\Contracts\Auth\Access\Gate;
use Illuminate\Contracts\Auth\Authenticatable;
use Symfony\Component\VarDumper\Cloner\VarCloner;
use Illuminate\Support\Str;
/**
* Collector for Laravel's Auth provider
*/
class GateCollector extends MessagesCollector
{
/**
* @param Gate $gate
*/
public function __construct(Gate $gate)
{
parent::__construct('gate');
$this->setDataFormatter(new SimpleFormatter());
$gate->after(function ($user, $ability, $result, $arguments = []) {
$this->addCheck($user, $ability, $result, $arguments);
});
}
public function addCheck($user, $ability, $result, $arguments = [])
{
$userKey = 'user';
$userId = null;
if ($user) {
$userKey = Str::snake(class_basename($user));
$userId = $user instanceof Authenticatable ? $user->getAuthIdentifier() : $user->id;
}
$label = $result ? 'success' : 'error';
// Response::allowed() was added in Laravel 6.x
if ($result instanceof Response && method_exists($result, 'allowed')) {
$label = $result->allowed() ? 'success' : 'error';
}
$this->addMessage([
'ability' => $ability,
'result' => $result,
$userKey => $userId,
'arguments' => $this->getDataFormatter()->formatVar($arguments),
], $label, false);
}
}

View File

@@ -0,0 +1,71 @@
<?php
namespace Barryvdh\Debugbar\DataCollector;
use DebugBar\DataCollector\DataCollector;
use DebugBar\DataCollector\Renderable;
use Illuminate\Foundation\Application;
class LaravelCollector extends DataCollector implements Renderable
{
/** @var \Illuminate\Foundation\Application $app */
protected $app;
/**
* @param Application $app
*/
public function __construct(Application $app = null)
{
$this->app = $app;
}
/**
* {@inheritDoc}
*/
public function collect()
{
// Fallback if not injected
$app = $this->app ?: app();
return [
"version" => $app::VERSION,
"environment" => $app->environment(),
"locale" => $app->getLocale(),
];
}
/**
* {@inheritDoc}
*/
public function getName()
{
return 'laravel';
}
/**
* {@inheritDoc}
*/
public function getWidgets()
{
return [
"version" => [
"icon" => "github",
"tooltip" => "Laravel Version",
"map" => "laravel.version",
"default" => ""
],
"environment" => [
"icon" => "desktop",
"tooltip" => "Environment",
"map" => "laravel.environment",
"default" => ""
],
"locale" => [
"icon" => "flag",
"tooltip" => "Current locale",
"map" => "laravel.locale",
"default" => "",
],
];
}
}

View File

@@ -0,0 +1,82 @@
<?php
namespace Barryvdh\Debugbar\DataCollector;
use DebugBar\DataCollector\DataCollector;
use DebugBar\DataCollector\DataCollectorInterface;
use DebugBar\DataCollector\Renderable;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Contracts\View\View;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use Illuminate\Support\Fluent;
use Illuminate\Support\Str;
use Livewire\Livewire;
/**
* Collector for Models.
*/
class LivewireCollector extends DataCollector implements DataCollectorInterface, Renderable
{
public $data = [];
public function __construct(Request $request)
{
// Listen to Livewire views
Livewire::listen('view:render', function (View $view) use ($request) {
/** @var \Livewire\Component $component */
$component = $view->getData()['_instance'];
// Create an unique name for each compoent
$key = $component->getName() . ' #' . $component->id;
$data = [
'data' => $component->getPublicPropertiesDefinedBySubClass(),
];
if ($request->request->get('id') == $component->id) {
$data['oldData'] = $request->request->get('data');
$data['actionQueue'] = $request->request->get('actionQueue');
}
$data['name'] = $component->getName();
$data['view'] = $view->name();
$data['component'] = get_class($component);
$data['id'] = $component->id;
$this->data[$key] = $this->formatVar($data);
});
}
public function collect()
{
return ['data' => $this->data, 'count' => count($this->data)];
}
/**
* {@inheritDoc}
*/
public function getName()
{
return 'livewire';
}
/**
* {@inheritDoc}
*/
public function getWidgets()
{
return [
"livewire" => [
"icon" => "bolt",
"widget" => "PhpDebugBar.Widgets.VariableListWidget",
"map" => "livewire.data",
"default" => "{}"
],
'livewire:badge' => [
'map' => 'livewire.count',
'default' => 0
]
];
}
}

View File

@@ -0,0 +1,143 @@
<?php
namespace Barryvdh\Debugbar\DataCollector;
use DebugBar\DataCollector\MessagesCollector;
use Psr\Log\LogLevel;
use ReflectionClass;
class LogsCollector extends MessagesCollector
{
protected $lines = 124;
public function __construct($path = null, $name = 'logs')
{
parent::__construct($name);
$path = $path ?: $this->getLogsFile();
$this->getStorageLogs($path);
}
/**
* Get the path to the logs file
*
* @return string
*/
public function getLogsFile()
{
// default daily rotating logs (Laravel 5.0)
$path = storage_path() . '/logs/laravel-' . date('Y-m-d') . '.log';
// single file logs
if (!file_exists($path)) {
$path = storage_path() . '/logs/laravel.log';
}
return $path;
}
/**
* get logs apache in app/storage/logs
* only 24 last of current day
*
* @param string $path
*
* @return array
*/
public function getStorageLogs($path)
{
if (!file_exists($path)) {
return;
}
//Load the latest lines, guessing about 15x the number of log entries (for stack traces etc)
$file = implode("", $this->tailFile($path, $this->lines));
foreach ($this->getLogs($file) as $log) {
$this->addMessage($log['header'] . $log['stack'], $log['level'], false);
}
}
/**
* By Ain Tohvri (ain)
* http://tekkie.flashbit.net/php/tail-functionality-in-php
* @param string $file
* @param int $lines
* @return array
*/
protected function tailFile($file, $lines)
{
$handle = fopen($file, "r");
$linecounter = $lines;
$pos = -2;
$beginning = false;
$text = [];
while ($linecounter > 0) {
$t = " ";
while ($t != "\n") {
if (fseek($handle, $pos, SEEK_END) == -1) {
$beginning = true;
break;
}
$t = fgetc($handle);
$pos--;
}
$linecounter--;
if ($beginning) {
rewind($handle);
}
$text[$lines - $linecounter - 1] = fgets($handle);
if ($beginning) {
break;
}
}
fclose($handle);
return array_reverse($text);
}
/**
* Search a string for log entries
* Based on https://github.com/mikemand/logviewer/blob/master/src/Kmd/Logviewer/Logviewer.php by mikemand
*
* @param $file
* @return array
*/
public function getLogs($file)
{
$pattern = "/\[\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\].*/";
$log_levels = $this->getLevels();
// There has GOT to be a better way of doing this...
preg_match_all($pattern, $file, $headings);
$log_data = preg_split($pattern, $file);
$log = [];
foreach ($headings as $h) {
for ($i = 0, $j = count($h); $i < $j; $i++) {
foreach ($log_levels as $ll) {
if (strpos(strtolower($h[$i]), strtolower('.' . $ll))) {
$log[] = ['level' => $ll, 'header' => $h[$i], 'stack' => $log_data[$i]];
}
}
}
}
$log = array_reverse($log);
return $log;
}
/**
* Get the log levels from psr/log.
* Based on https://github.com/mikemand/logviewer/blob/master/src/Kmd/Logviewer/Logviewer.php by mikemand
*
* @access public
* @return array
*/
public function getLevels()
{
$class = new ReflectionClass(new LogLevel());
return $class->getConstants();
}
}

View File

@@ -0,0 +1,65 @@
<?php
namespace Barryvdh\Debugbar\DataCollector;
use DebugBar\DataCollector\DataCollector;
use DebugBar\DataCollector\DataCollectorInterface;
use DebugBar\DataCollector\Renderable;
use Illuminate\Contracts\Events\Dispatcher;
/**
* Collector for Models.
*/
class ModelsCollector extends DataCollector implements DataCollectorInterface, Renderable
{
public $models = [];
public $count = 0;
/**
* @param Dispatcher $events
*/
public function __construct(Dispatcher $events)
{
$events->listen('eloquent.retrieved:*', function ($event, $models) {
foreach (array_filter($models) as $model) {
$class = get_class($model);
$this->models[$class] = ($this->models[$class] ?? 0) + 1;
$this->count++;
}
});
}
public function collect()
{
ksort($this->models, SORT_NUMERIC);
return ['data' => array_reverse($this->models), 'count' => $this->count];
}
/**
* {@inheritDoc}
*/
public function getName()
{
return 'models';
}
/**
* {@inheritDoc}
*/
public function getWidgets()
{
return [
"models" => [
"icon" => "cubes",
"widget" => "PhpDebugBar.Widgets.HtmlVariableListWidget",
"map" => "models.data",
"default" => "{}"
],
'models:badge' => [
'map' => 'models.count',
'default' => 0
]
];
}
}

View File

@@ -0,0 +1,168 @@
<?php
namespace Barryvdh\Debugbar\DataCollector;
use DebugBar\DataCollector\DataCollector;
use DebugBar\DataCollector\Renderable;
use Illuminate\Auth\Recaller;
use Illuminate\Auth\SessionGuard;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Contracts\Auth\Guard;
use Illuminate\Support\Str;
use Illuminate\Contracts\Support\Arrayable;
/**
* Collector for Laravel's Auth provider
*/
class MultiAuthCollector extends DataCollector implements Renderable
{
/** @var array $guards */
protected $guards;
/** @var \Illuminate\Auth\AuthManager */
protected $auth;
/** @var bool */
protected $showName = false;
/**
* @param \Illuminate\Auth\AuthManager $auth
* @param array $guards
*/
public function __construct($auth, $guards)
{
$this->auth = $auth;
$this->guards = $guards;
}
/**
* Set to show the users name/email
* @param bool $showName
*/
public function setShowName($showName)
{
$this->showName = (bool) $showName;
}
/**
* @{inheritDoc}
*/
public function collect()
{
$data = [
'guards' => [],
];
$names = '';
foreach ($this->guards as $guardName => $config) {
try {
$guard = $this->auth->guard($guardName);
if ($this->hasUser($guard)) {
$user = $guard->user();
if (!is_null($user)) {
$data['guards'][$guardName] = $this->getUserInformation($user);
$names .= $guardName . ": " . $data['guards'][$guardName]['name'] . ', ';
}
} else {
$data['guards'][$guardName] = null;
}
} catch (\Exception $e) {
continue;
}
}
foreach ($data['guards'] as $key => $var) {
if (!is_string($data['guards'][$key])) {
$data['guards'][$key] = $this->formatVar($var);
}
}
$data['names'] = rtrim($names, ', ');
return $data;
}
private function hasUser(Guard $guard)
{
if (method_exists($guard, 'hasUser')) {
return $guard->hasUser();
}
// For Laravel 5.5
if (method_exists($guard, 'alreadyAuthenticated')) {
return $guard->alreadyAuthenticated();
}
return false;
}
/**
* Get displayed user information
* @param \Illuminate\Auth\UserInterface $user
* @return array
*/
protected function getUserInformation($user = null)
{
// Defaults
if (is_null($user)) {
return [
'name' => 'Guest',
'user' => ['guest' => true],
];
}
// The default auth identifer is the ID number, which isn't all that
// useful. Try username and email.
$identifier = $user instanceof Authenticatable ? $user->getAuthIdentifier() : $user->id;
if (is_numeric($identifier)) {
try {
if (isset($user->username)) {
$identifier = $user->username;
} elseif (isset($user->email)) {
$identifier = $user->email;
}
} catch (\Throwable $e) {
}
}
return [
'name' => $identifier,
'user' => $user instanceof Arrayable ? $user->toArray() : $user,
];
}
/**
* @{inheritDoc}
*/
public function getName()
{
return 'auth';
}
/**
* @{inheritDoc}
*/
public function getWidgets()
{
$widgets = [
"auth" => [
"icon" => "lock",
"widget" => "PhpDebugBar.Widgets.VariableListWidget",
"map" => "auth.guards",
"default" => "{}"
]
];
if ($this->showName) {
$widgets['auth.name'] = [
'icon' => 'user',
'tooltip' => 'Auth status',
'map' => 'auth.names',
'default' => '',
];
}
return $widgets;
}
}

View File

@@ -0,0 +1,18 @@
<?php
namespace Barryvdh\Debugbar\DataCollector;
use DebugBar\DataCollector\PhpInfoCollector as DebugBarPhpInfoCollector;
class PhpInfoCollector extends DebugBarPhpInfoCollector
{
/**
* @inheritDoc
*/
public function getWidgets()
{
return tap(parent::getWidgets(), function (&$widgets) {
data_set($widgets, 'php_version.tooltip', 'PHP Version');
});
}
}

View File

@@ -0,0 +1,589 @@
<?php
namespace Barryvdh\Debugbar\DataCollector;
use DebugBar\DataCollector\PDO\PDOCollector;
use DebugBar\DataCollector\TimeDataCollector;
use Illuminate\Support\Str;
/**
* Collects data about SQL statements executed with PDO
*/
class QueryCollector extends PDOCollector
{
protected $timeCollector;
protected $queries = [];
protected $renderSqlWithParams = false;
protected $findSource = false;
protected $middleware = [];
protected $durationBackground = true;
protected $explainQuery = false;
protected $explainTypes = ['SELECT']; // ['SELECT', 'INSERT', 'UPDATE', 'DELETE']; for MySQL 5.6.3+
protected $showHints = false;
protected $showCopyButton = false;
protected $reflection = [];
protected $backtraceExcludePaths = [
'/vendor/laravel/framework/src/Illuminate/Support',
'/vendor/laravel/framework/src/Illuminate/Database',
'/vendor/laravel/framework/src/Illuminate/Events',
'/vendor/october/rain',
'/vendor/barryvdh/laravel-debugbar',
];
/**
* @param TimeDataCollector $timeCollector
*/
public function __construct(TimeDataCollector $timeCollector = null)
{
$this->timeCollector = $timeCollector;
}
/**
* Renders the SQL of traced statements with params embedded
*
* @param boolean $enabled
* @param string $quotationChar NOT USED
*/
public function setRenderSqlWithParams($enabled = true, $quotationChar = "'")
{
$this->renderSqlWithParams = $enabled;
}
/**
* Show or hide the hints in the parameters
*
* @param boolean $enabled
*/
public function setShowHints($enabled = true)
{
$this->showHints = $enabled;
}
/**
* Show or hide copy button next to the queries
*
* @param boolean $enabled
*/
public function setShowCopyButton($enabled = true)
{
$this->showCopyButton = $enabled;
}
/**
* Enable/disable finding the source
*
* @param bool $value
* @param array $middleware
*/
public function setFindSource($value, array $middleware)
{
$this->findSource = (bool) $value;
$this->middleware = $middleware;
}
/**
* Set additional paths to exclude from the backtrace
*
* @param array $excludePaths Array of file paths to exclude from backtrace
*/
public function mergeBacktraceExcludePaths(array $excludePaths)
{
$this->backtraceExcludePaths = array_merge($this->backtraceExcludePaths, $excludePaths);
}
/**
* Enable/disable the shaded duration background on queries
*
* @param bool $enabled
*/
public function setDurationBackground($enabled)
{
$this->durationBackground = $enabled;
}
/**
* Enable/disable the EXPLAIN queries
*
* @param bool $enabled
* @param array|null $types Array of types to explain queries (select/insert/update/delete)
*/
public function setExplainSource($enabled, $types)
{
$this->explainQuery = $enabled;
// workaround ['SELECT'] only. https://github.com/barryvdh/laravel-debugbar/issues/888
// if($types){
// $this->explainTypes = $types;
// }
}
/**
*
* @param string $query
* @param array $bindings
* @param float $time
* @param \Illuminate\Database\Connection $connection
*/
public function addQuery($query, $bindings, $time, $connection)
{
$explainResults = [];
$time = $time / 1000;
$endTime = microtime(true);
$startTime = $endTime - $time;
$hints = $this->performQueryAnalysis($query);
$pdo = null;
try {
$pdo = $connection->getPdo();
} catch (\Exception $e) {
// ignore error for non-pdo laravel drivers
}
$bindings = $connection->prepareBindings($bindings);
// Run EXPLAIN on this query (if needed)
if ($this->explainQuery && $pdo && preg_match('/^\s*(' . implode('|', $this->explainTypes) . ') /i', $query)) {
$statement = $pdo->prepare('EXPLAIN ' . $query);
$statement->execute($bindings);
$explainResults = $statement->fetchAll(\PDO::FETCH_CLASS);
}
$bindings = $this->getDataFormatter()->checkBindings($bindings);
if (!empty($bindings) && $this->renderSqlWithParams) {
foreach ($bindings as $key => $binding) {
// This regex matches placeholders only, not the question marks,
// nested in quotes, while we iterate through the bindings
// and substitute placeholders by suitable values.
$regex = is_numeric($key)
? "/(?<!\?)\?(?=(?:[^'\\\']*'[^'\\']*')*[^'\\\']*$)(?!\?)/"
: "/:{$key}(?=(?:[^'\\\']*'[^'\\\']*')*[^'\\\']*$)/";
// Mimic bindValue and only quote non-integer and non-float data types
if (!is_int($binding) && !is_float($binding)) {
if ($pdo) {
try {
$binding = $pdo->quote((string) $binding);
} catch (\Exception $e) {
$binding = $this->emulateQuote($binding);
}
} else {
$binding = $this->emulateQuote($binding);
}
}
$query = preg_replace($regex, addcslashes($binding, '$'), $query, 1);
}
}
$source = [];
if ($this->findSource) {
try {
$source = array_slice($this->findSource(), 0, 5);
} catch (\Exception $e) {
}
}
$this->queries[] = [
'query' => $query,
'type' => 'query',
'bindings' => $this->getDataFormatter()->escapeBindings($bindings),
'time' => $time,
'source' => $source,
'explain' => $explainResults,
'connection' => $connection->getDatabaseName(),
'driver' => $connection->getConfig('driver'),
'hints' => $this->showHints ? $hints : null,
'show_copy' => $this->showCopyButton,
];
if ($this->timeCollector !== null) {
$this->timeCollector->addMeasure(Str::limit($query, 100), $startTime, $endTime);
}
}
/**
* Mimic mysql_real_escape_string
*
* @param string $value
* @return string
*/
protected function emulateQuote($value)
{
$search = ["\\", "\x00", "\n", "\r", "'", '"', "\x1a"];
$replace = ["\\\\","\\0","\\n", "\\r", "\'", '\"', "\\Z"];
return "'" . str_replace($search, $replace, (string) $value) . "'";
}
/**
* Explainer::performQueryAnalysis()
*
* Perform simple regex analysis on the code
*
* @package xplain (https://github.com/rap2hpoutre/mysql-xplain-xplain)
* @author e-doceo
* @copyright 2014
* @version $Id$
* @access public
* @param string $query
* @return string[]
*/
protected function performQueryAnalysis($query)
{
// @codingStandardsIgnoreStart
$hints = [];
if (preg_match('/^\\s*SELECT\\s*`?[a-zA-Z0-9]*`?\\.?\\*/i', $query)) {
$hints[] = 'Use <code>SELECT *</code> only if you need all columns from table';
}
if (preg_match('/ORDER BY RAND()/i', $query)) {
$hints[] = '<code>ORDER BY RAND()</code> is slow, try to avoid if you can.
You can <a href="http://stackoverflow.com/questions/2663710/how-does-mysqls-order-by-rand-work" target="_blank">read this</a>
or <a href="http://stackoverflow.com/questions/1244555/how-can-i-optimize-mysqls-order-by-rand-function" target="_blank">this</a>';
}
if (strpos($query, '!=') !== false) {
$hints[] = 'The <code>!=</code> operator is not standard. Use the <code>&lt;&gt;</code> operator to test for inequality instead.';
}
if (stripos($query, 'WHERE') === false && preg_match('/^(SELECT) /i', $query)) {
$hints[] = 'The <code>SELECT</code> statement has no <code>WHERE</code> clause and could examine many more rows than intended';
}
if (preg_match('/LIMIT\\s/i', $query) && stripos($query, 'ORDER BY') === false) {
$hints[] = '<code>LIMIT</code> without <code>ORDER BY</code> causes non-deterministic results, depending on the query execution plan';
}
if (preg_match('/LIKE\\s[\'"](%.*?)[\'"]/i', $query, $matches)) {
$hints[] = 'An argument has a leading wildcard character: <code>' . $matches[1] . '</code>.
The predicate with this argument is not sargable and cannot use an index if one exists.';
}
return $hints;
// @codingStandardsIgnoreEnd
}
/**
* Use a backtrace to search for the origins of the query.
*
* @return array
*/
protected function findSource()
{
$stack = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS | DEBUG_BACKTRACE_PROVIDE_OBJECT, app('config')->get('debugbar.debug_backtrace_limit', 50));
$sources = [];
foreach ($stack as $index => $trace) {
$sources[] = $this->parseTrace($index, $trace);
}
return array_filter($sources);
}
/**
* Parse a trace element from the backtrace stack.
*
* @param int $index
* @param array $trace
* @return object|bool
*/
protected function parseTrace($index, array $trace)
{
$frame = (object) [
'index' => $index,
'namespace' => null,
'name' => null,
'line' => isset($trace['line']) ? $trace['line'] : '?',
];
if (isset($trace['function']) && $trace['function'] == 'substituteBindings') {
$frame->name = 'Route binding';
return $frame;
}
if (
isset($trace['class']) &&
isset($trace['file']) &&
!$this->fileIsInExcludedPath($trace['file'])
) {
$file = $trace['file'];
if (isset($trace['object']) && is_a($trace['object'], 'Twig_Template')) {
list($file, $frame->line) = $this->getTwigInfo($trace);
} elseif (strpos($file, storage_path()) !== false) {
$hash = pathinfo($file, PATHINFO_FILENAME);
if (! $frame->name = $this->findViewFromHash($hash)) {
$frame->name = $hash;
}
$frame->namespace = 'view';
return $frame;
} elseif (strpos($file, 'Middleware') !== false) {
$frame->name = $this->findMiddlewareFromFile($file);
if ($frame->name) {
$frame->namespace = 'middleware';
} else {
$frame->name = $this->normalizeFilename($file);
}
return $frame;
}
$frame->name = $this->normalizeFilename($file);
return $frame;
}
return false;
}
/**
* Check if the given file is to be excluded from analysis
*
* @param string $file
* @return bool
*/
protected function fileIsInExcludedPath($file)
{
$normalizedPath = str_replace('\\', '/', $file);
foreach ($this->backtraceExcludePaths as $excludedPath) {
if (strpos($normalizedPath, $excludedPath) !== false) {
return true;
}
}
return false;
}
/**
* Find the middleware alias from the file.
*
* @param string $file
* @return string|null
*/
protected function findMiddlewareFromFile($file)
{
$filename = pathinfo($file, PATHINFO_FILENAME);
foreach ($this->middleware as $alias => $class) {
if (strpos($class, $filename) !== false) {
return $alias;
}
}
}
/**
* Find the template name from the hash.
*
* @param string $hash
* @return null|string
*/
protected function findViewFromHash($hash)
{
$finder = app('view')->getFinder();
if (isset($this->reflection['viewfinderViews'])) {
$property = $this->reflection['viewfinderViews'];
} else {
$reflection = new \ReflectionClass($finder);
$property = $reflection->getProperty('views');
$property->setAccessible(true);
$this->reflection['viewfinderViews'] = $property;
}
foreach ($property->getValue($finder) as $name => $path) {
if (sha1($path) == $hash || md5($path) == $hash) {
return $name;
}
}
}
/**
* Get the filename/line from a Twig template trace
*
* @param array $trace
* @return array The file and line
*/
protected function getTwigInfo($trace)
{
$file = $trace['object']->getTemplateName();
if (isset($trace['line'])) {
foreach ($trace['object']->getDebugInfo() as $codeLine => $templateLine) {
if ($codeLine <= $trace['line']) {
return [$file, $templateLine];
}
}
}
return [$file, -1];
}
/**
* Shorten the path by removing the relative links and base dir
*
* @param string $path
* @return string
*/
protected function normalizeFilename($path)
{
if (file_exists($path)) {
$path = realpath($path);
}
return str_replace(base_path(), '', $path);
}
/**
* Collect a database transaction event.
* @param string $event
* @param \Illuminate\Database\Connection $connection
* @return array
*/
public function collectTransactionEvent($event, $connection)
{
$source = [];
if ($this->findSource) {
try {
$source = $this->findSource();
} catch (\Exception $e) {
}
}
$this->queries[] = [
'query' => $event,
'type' => 'transaction',
'bindings' => [],
'time' => 0,
'source' => $source,
'explain' => [],
'connection' => $connection->getDatabaseName(),
'driver' => $connection->getConfig('driver'),
'hints' => null,
'show_copy' => false,
];
}
/**
* Reset the queries.
*/
public function reset()
{
$this->queries = [];
}
/**
* {@inheritDoc}
*/
public function collect()
{
$totalTime = 0;
$queries = $this->queries;
$statements = [];
foreach ($queries as $query) {
$totalTime += $query['time'];
$statements[] = [
'sql' => $this->getDataFormatter()->formatSql($query['query']),
'type' => $query['type'],
'params' => [],
'bindings' => $query['bindings'],
'hints' => $query['hints'],
'show_copy' => $query['show_copy'],
'backtrace' => array_values($query['source']),
'duration' => $query['time'],
'duration_str' => ($query['type'] == 'transaction') ? '' : $this->formatDuration($query['time']),
'stmt_id' => $this->getDataFormatter()->formatSource(reset($query['source'])),
'connection' => $query['connection'],
];
// Add the results from the explain as new rows
if ($query['driver'] === 'pgsql') {
$explainer = trim(implode("\n", array_map(function ($explain) {
return $explain->{'QUERY PLAN'};
}, $query['explain'])));
if ($explainer) {
$statements[] = [
'sql' => " - EXPLAIN: {$explainer}",
'type' => 'explain',
];
}
} else {
foreach ($query['explain'] as $explain) {
$statements[] = [
'sql' => " - EXPLAIN # {$explain->id}: `{$explain->table}` ({$explain->select_type})",
'type' => 'explain',
'params' => $explain,
'row_count' => $explain->rows,
'stmt_id' => $explain->id,
];
}
}
}
if ($this->durationBackground) {
if ($totalTime > 0) {
// For showing background measure on Queries tab
$start_percent = 0;
foreach ($statements as $i => $statement) {
if (!isset($statement['duration'])) {
continue;
}
$width_percent = $statement['duration'] / $totalTime * 100;
$statements[$i] = array_merge($statement, [
'start_percent' => round($start_percent, 3),
'width_percent' => round($width_percent, 3),
]);
$start_percent += $width_percent;
}
}
}
$nb_statements = array_filter($queries, function ($query) {
return $query['type'] === 'query';
});
$data = [
'nb_statements' => count($nb_statements),
'nb_failed_statements' => 0,
'accumulated_duration' => $totalTime,
'accumulated_duration_str' => $this->formatDuration($totalTime),
'statements' => $statements
];
return $data;
}
/**
* {@inheritDoc}
*/
public function getName()
{
return 'queries';
}
/**
* {@inheritDoc}
*/
public function getWidgets()
{
return [
"queries" => [
"icon" => "database",
"widget" => "PhpDebugBar.Widgets.LaravelSQLQueriesWidget",
"map" => "queries",
"default" => "[]"
],
"queries:badge" => [
"map" => "queries.nb_statements",
"default" => 0
]
];
}
}

View File

@@ -0,0 +1,199 @@
<?php
namespace Barryvdh\Debugbar\DataCollector;
use DebugBar\DataCollector\DataCollector;
use DebugBar\DataCollector\DataCollectorInterface;
use DebugBar\DataCollector\Renderable;
use Illuminate\Support\Str;
use Laravel\Telescope\IncomingEntry;
use Laravel\Telescope\Telescope;
use Symfony\Component\HttpFoundation\Response;
/**
*
* Based on \Symfony\Component\HttpKernel\DataCollector\RequestDataCollector by Fabien Potencier <fabien@symfony.com>
*
*/
class RequestCollector extends DataCollector implements DataCollectorInterface, Renderable
{
/** @var \Symfony\Component\HttpFoundation\Request $request */
protected $request;
/** @var \Symfony\Component\HttpFoundation\Request $response */
protected $response;
/** @var \Symfony\Component\HttpFoundation\Session\SessionInterface $session */
protected $session;
/** @var string|null */
protected $currentRequestId;
/**
* Create a new SymfonyRequestCollector
*
* @param \Symfony\Component\HttpFoundation\Request $request
* @param \Symfony\Component\HttpFoundation\Response $response
* @param \Symfony\Component\HttpFoundation\Session\SessionInterface $session
*/
public function __construct($request, $response, $session = null, $currentRequestId = null)
{
$this->request = $request;
$this->response = $response;
$this->session = $session;
$this->currentRequestId = $currentRequestId;
}
/**
* {@inheritDoc}
*/
public function getName()
{
return 'request';
}
/**
* {@inheritDoc}
*/
public function getWidgets()
{
return [
"request" => [
"icon" => "tags",
"widget" => "PhpDebugBar.Widgets.HtmlVariableListWidget",
"map" => "request",
"default" => "{}"
]
];
}
/**
* {@inheritdoc}
*/
public function collect()
{
$request = $this->request;
$response = $this->response;
$responseHeaders = $response->headers->all();
$cookies = [];
foreach ($response->headers->getCookies() as $cookie) {
$cookies[] = $this->getCookieHeader(
$cookie->getName(),
$cookie->getValue(),
$cookie->getExpiresTime(),
$cookie->getPath(),
$cookie->getDomain(),
$cookie->isSecure(),
$cookie->isHttpOnly()
);
}
if (count($cookies) > 0) {
$responseHeaders['Set-Cookie'] = $cookies;
}
$statusCode = $response->getStatusCode();
$data = [
'path_info' => $request->getPathInfo(),
'status_code' => $statusCode,
'status_text' => isset(Response::$statusTexts[$statusCode]) ? Response::$statusTexts[$statusCode] : '',
'format' => $request->getRequestFormat(),
'content_type' => $response->headers->get('Content-Type') ? $response->headers->get(
'Content-Type'
) : 'text/html',
'request_query' => $request->query->all(),
'request_request' => $request->request->all(),
'request_headers' => $request->headers->all(),
'request_server' => $request->server->all(),
'request_cookies' => $request->cookies->all(),
'response_headers' => $responseHeaders,
];
if ($this->session) {
$sessionAttributes = [];
foreach ($this->session->all() as $key => $value) {
$sessionAttributes[$key] = $value;
}
$data['session_attributes'] = $sessionAttributes;
}
foreach ($data['request_server'] as $key => $value) {
if (
Str::is('*_KEY', $key) || Str::is('*_PASSWORD', $key)
|| Str::is('*_SECRET', $key) || Str::is('*_PW', $key)
|| Str::is('*_TOKEN', $key) || Str::is('*_PASS', $key)
) {
$data['request_server'][$key] = '******';
}
}
if (isset($data['request_headers']['php-auth-pw'])) {
$data['request_headers']['php-auth-pw'] = '******';
}
if (isset($data['request_server']['PHP_AUTH_PW'])) {
$data['request_server']['PHP_AUTH_PW'] = '******';
}
;
foreach ($data as $key => $var) {
if (!is_string($data[$key])) {
$data[$key] = DataCollector::getDefaultVarDumper()->renderVar($var);
} else {
$data[$key] = e($data[$key]);
}
}
$htmlData = [];
if (class_exists(Telescope::class)) {
$entry = IncomingEntry::make([
'requestId' => $this->currentRequestId,
])->type('debugbar');
Telescope::$entriesQueue[] = $entry;
$url = route('debugbar.telescope', [$entry->uuid]);
$htmlData['telescope'] = '<a href="' . $url . '" target="_blank">View in Telescope</a>';
}
return $htmlData + $data;
}
private function getCookieHeader($name, $value, $expires, $path, $domain, $secure, $httponly)
{
$cookie = sprintf('%s=%s', $name, urlencode($value));
if (0 !== $expires) {
if (is_numeric($expires)) {
$expires = (int) $expires;
} elseif ($expires instanceof \DateTime) {
$expires = $expires->getTimestamp();
} else {
$expires = strtotime($expires);
if (false === $expires || -1 == $expires) {
throw new \InvalidArgumentException(
sprintf('The "expires" cookie parameter is not valid.', $expires)
);
}
}
$cookie .= '; expires=' . substr(
\DateTime::createFromFormat('U', $expires, new \DateTimeZone('UTC'))->format('D, d-M-Y H:i:s T'),
0,
-5
);
}
if ($domain) {
$cookie .= '; domain=' . $domain;
}
$cookie .= '; path=' . $path;
if ($secure) {
$cookie .= '; secure';
}
if ($httponly) {
$cookie .= '; httponly';
}
return $cookie;
}
}

View File

@@ -0,0 +1,220 @@
<?php
namespace Barryvdh\Debugbar\DataCollector;
use Closure;
use DebugBar\DataCollector\DataCollector;
use DebugBar\DataCollector\Renderable;
use Illuminate\Http\Request;
use Illuminate\Routing\Route;
use Illuminate\Routing\Router;
use Illuminate\Support\Facades\Config;
use InvalidArgumentException;
/**
* Based on Illuminate\Foundation\Console\RoutesCommand for Taylor Otwell
* https://github.com/laravel/framework/blob/master/src/Illuminate/Foundation/Console/RoutesCommand.php
*
*/
class RouteCollector extends DataCollector implements Renderable
{
/**
* The router instance.
*
* @var \Illuminate\Routing\Router
*/
protected $router;
/**
* A list of known editor strings.
*
* @var array
*/
protected $editors = [
'sublime' => 'subl://open?url=file://%file&line=%line',
'textmate' => 'txmt://open?url=file://%file&line=%line',
'emacs' => 'emacs://open?url=file://%file&line=%line',
'macvim' => 'mvim://open/?url=file://%file&line=%line',
'phpstorm' => 'phpstorm://open?file=%file&line=%line',
'idea' => 'idea://open?file=%file&line=%line',
'vscode' => 'vscode://file/%file:%line',
'vscode-insiders' => 'vscode-insiders://file/%file:%line',
'vscode-remote' => 'vscode://vscode-remote/%file:%line',
'vscode-insiders-remote' => 'vscode-insiders://vscode-remote/%file:%line',
'vscodium' => 'vscodium://file/%file:%line',
'nova' => 'nova://core/open/file?filename=%file&line=%line',
'xdebug' => 'xdebug://%file@%line',
'atom' => 'atom://core/open/file?filename=%file&line=%line',
'espresso' => 'x-espresso://open?filepath=%file&lines=%line',
'netbeans' => 'netbeans://open/?f=%file:%line',
];
public function __construct(Router $router)
{
$this->router = $router;
}
/**
* {@inheritDoc}
*/
public function collect()
{
$route = $this->router->current();
return $this->getRouteInformation($route);
}
/**
* Get the route information for a given route.
*
* @param \Illuminate\Routing\Route $route
* @return array
*/
protected function getRouteInformation($route)
{
if (!is_a($route, 'Illuminate\Routing\Route')) {
return [];
}
$uri = head($route->methods()) . ' ' . $route->uri();
$action = $route->getAction();
$result = [
'uri' => $uri ?: '-',
];
$result = array_merge($result, $action);
if (
isset($action['controller'])
&& is_string($action['controller'])
&& strpos($action['controller'], '@') !== false
) {
list($controller, $method) = explode('@', $action['controller']);
if (class_exists($controller) && method_exists($controller, $method)) {
$reflector = new \ReflectionMethod($controller, $method);
}
unset($result['uses']);
} elseif (isset($action['uses']) && $action['uses'] instanceof \Closure) {
$reflector = new \ReflectionFunction($action['uses']);
$result['uses'] = $this->formatVar($result['uses']);
}
if (isset($reflector)) {
$filename = ltrim(str_replace(base_path(), '', $reflector->getFileName()), '/');
if ($href = $this->getEditorHref($reflector->getFileName(), $reflector->getStartLine())) {
$result['file'] = sprintf('<a href="%s">%s:%s-%s</a>', $href, $filename, $reflector->getStartLine(), $reflector->getEndLine());
} else {
$result['file'] = sprintf('%s:%s-%s', $filename, $reflector->getStartLine(), $reflector->getEndLine());
}
}
if ($middleware = $this->getMiddleware($route)) {
$result['middleware'] = $middleware;
}
return $result;
}
/**
* Get middleware
*
* @param \Illuminate\Routing\Route $route
* @return string
*/
protected function getMiddleware($route)
{
return implode(', ', array_map(function ($middleware) {
return $middleware instanceof Closure ? 'Closure' : $middleware;
}, $route->middleware()));
}
/**
* {@inheritDoc}
*/
public function getName()
{
return 'route';
}
/**
* {@inheritDoc}
*/
public function getWidgets()
{
$widgets = [
"route" => [
"icon" => "share",
"widget" => "PhpDebugBar.Widgets.HtmlVariableListWidget",
"map" => "route",
"default" => "{}"
]
];
if (Config::get('debugbar.options.route.label', true)) {
$widgets['currentroute'] = [
"icon" => "share",
"tooltip" => "Route",
"map" => "route.uri",
"default" => ""
];
}
return $widgets;
}
/**
* Display the route information on the console.
*
* @param array $routes
* @return void
*/
protected function displayRoutes(array $routes)
{
$this->table->setHeaders($this->headers)->setRows($routes);
$this->table->render($this->getOutput());
}
/**
* Get the editor href for a given file and line, if available.
*
* @param string $filePath
* @param int $line
*
* @throws InvalidArgumentException If editor resolver does not return a string
*
* @return null|string
*/
protected function getEditorHref($filePath, $line)
{
if (empty(config('debugbar.editor'))) {
return null;
}
if (empty($this->editors[config('debugbar.editor')])) {
throw new InvalidArgumentException(
'Unknown editor identifier: ' . config('debugbar.editor') . '. Known editors:' .
implode(', ', array_keys($this->editors))
);
}
$filePath = $this->replaceSitesPath($filePath);
$url = str_replace(['%file', '%line'], [$filePath, $line], $this->editors[config('debugbar.editor')]);
return $url;
}
/**
* Replace remote path
*
* @param string $filePath
*
* @return string
*/
protected function replaceSitesPath($filePath)
{
return str_replace(config('debugbar.remote_sites_path'), config('debugbar.local_sites_path'), $filePath);
}
}

View File

@@ -0,0 +1,58 @@
<?php
namespace Barryvdh\Debugbar\DataCollector;
use DebugBar\DataCollector\DataCollector;
use DebugBar\DataCollector\DataCollectorInterface;
use DebugBar\DataCollector\Renderable;
class SessionCollector extends DataCollector implements DataCollectorInterface, Renderable
{
/** @var \Symfony\Component\HttpFoundation\Session\SessionInterface|\Illuminate\Contracts\Session\Session $session */
protected $session;
/**
* Create a new SessionCollector
*
* @param \Symfony\Component\HttpFoundation\Session\SessionInterface|\Illuminate\Contracts\Session\Session $session
*/
public function __construct($session)
{
$this->session = $session;
}
/**
* {@inheritdoc}
*/
public function collect()
{
$data = [];
foreach ($this->session->all() as $key => $value) {
$data[$key] = is_string($value) ? $value : $this->formatVar($value);
}
return $data;
}
/**
* {@inheritDoc}
*/
public function getName()
{
return 'session';
}
/**
* {@inheritDoc}
*/
public function getWidgets()
{
return [
"session" => [
"icon" => "archive",
"widget" => "PhpDebugBar.Widgets.VariableListWidget",
"map" => "session",
"default" => "{}"
]
];
}
}

View File

@@ -0,0 +1,107 @@
<?php
namespace Barryvdh\Debugbar\DataCollector;
use Barryvdh\Debugbar\DataFormatter\SimpleFormatter;
use DebugBar\Bridge\Twig\TwigCollector;
use Illuminate\View\View;
use Symfony\Component\VarDumper\Cloner\VarCloner;
class ViewCollector extends TwigCollector
{
protected $templates = [];
protected $collect_data;
/**
* Create a ViewCollector
*
* @param bool $collectData Collects view data when tru
*/
public function __construct($collectData = true)
{
$this->setDataFormatter(new SimpleFormatter());
$this->collect_data = $collectData;
$this->name = 'views';
$this->templates = [];
}
public function getName()
{
return 'views';
}
public function getWidgets()
{
return [
'views' => [
'icon' => 'leaf',
'widget' => 'PhpDebugBar.Widgets.TemplatesWidget',
'map' => 'views',
'default' => '[]'
],
'views:badge' => [
'map' => 'views.nb_templates',
'default' => 0
]
];
}
/**
* Add a View instance to the Collector
*
* @param \Illuminate\View\View $view
*/
public function addView(View $view)
{
$name = $view->getName();
$path = $view->getPath();
if (!is_object($path)) {
if ($path) {
$path = ltrim(str_replace(base_path(), '', realpath($path)), '/');
}
if (substr($path, -10) == '.blade.php') {
$type = 'blade';
} else {
$type = pathinfo($path, PATHINFO_EXTENSION);
}
} else {
$type = get_class($view);
$path = '';
}
if (!$this->collect_data) {
$params = array_keys($view->getData());
} else {
$data = [];
foreach ($view->getData() as $key => $value) {
$data[$key] = $this->getDataFormatter()->formatVar($value);
}
$params = $data;
}
$template = [
'name' => $path ? sprintf('%s (%s)', $name, $path) : $name,
'param_count' => count($params),
'params' => $params,
'type' => $type,
];
if ($this->getXdebugLink($path)) {
$template['xdebug_link'] = $this->getXdebugLink(realpath($view->getPath()));
}
$this->templates[] = $template;
}
public function collect()
{
$templates = $this->templates;
return [
'nb_templates' => count($templates),
'templates' => $templates,
];
}
}

View File

@@ -0,0 +1,87 @@
<?php
namespace Barryvdh\Debugbar\DataFormatter;
use DebugBar\DataFormatter\DataFormatter;
class QueryFormatter extends DataFormatter
{
/**
* Removes extra spaces at the beginning and end of the SQL query and its lines.
*
* @param string $sql
* @return string
*/
public function formatSql($sql)
{
$sql = preg_replace("/\?(?=(?:[^'\\\']*'[^'\\']*')*[^'\\\']*$)(?:\?)/", '?', $sql);
$sql = trim(preg_replace("/\s*\n\s*/", "\n", $sql));
return $sql;
}
/**
* Check bindings for illegal (non UTF-8) strings, like Binary data.
*
* @param $bindings
* @return mixed
*/
public function checkBindings($bindings)
{
foreach ($bindings as &$binding) {
if (is_string($binding) && !mb_check_encoding($binding, 'UTF-8')) {
$binding = '[BINARY DATA]';
}
if (is_array($binding)) {
$binding = $this->checkBindings($binding);
$binding = '[' . implode(',', $binding) . ']';
}
if (is_object($binding)) {
$binding = json_encode($binding);
}
}
return $bindings;
}
/**
* Make the bindings safe for outputting.
*
* @param array $bindings
* @return array
*/
public function escapeBindings($bindings)
{
foreach ($bindings as &$binding) {
$binding = htmlentities((string) $binding, ENT_QUOTES, 'UTF-8', false);
}
return $bindings;
}
/**
* Format a source object.
*
* @param object|null $source If the backtrace is disabled, the $source will be null.
* @return string
*/
public function formatSource($source)
{
if (! is_object($source)) {
return '';
}
$parts = [];
if ($source->namespace) {
$parts['namespace'] = $source->namespace . '::';
}
$parts['name'] = $source->name;
$parts['line'] = ':' . $source->line;
return implode($parts);
}
}

View File

@@ -0,0 +1,106 @@
<?php
namespace Barryvdh\Debugbar\DataFormatter;
use DebugBar\DataFormatter\DataFormatter;
/**
* Simple DataFormatter based on the deprecated Symfony ValueExporter
*
* @see https://github.com/symfony/symfony/blob/v3.4.4/src/Symfony/Component/HttpKernel/DataCollector/Util/ValueExporter.php
*/
class SimpleFormatter extends DataFormatter
{
/**
* @param $data
* @return string
*/
public function formatVar($data)
{
return $this->exportValue($data);
}
/**
* Converts a PHP value to a string.
*
* @param mixed $value The PHP value
* @param int $depth Only for internal usage
* @param bool $deep Only for internal usage
*
* @return string The string representation of the given value
* @author Bernhard Schussek <bschussek@gmail.com>
*/
private function exportValue($value, $depth = 1, $deep = false)
{
if ($value instanceof \__PHP_Incomplete_Class) {
return sprintf('__PHP_Incomplete_Class(%s)', $this->getClassNameFromIncomplete($value));
}
if (is_object($value)) {
if ($value instanceof \DateTimeInterface) {
return sprintf('Object(%s) - %s', get_class($value), $value->format(\DateTime::ATOM));
}
return sprintf('Object(%s)', get_class($value));
}
if (is_array($value)) {
if (empty($value)) {
return '[]';
}
$indent = str_repeat(' ', $depth);
$a = array();
foreach ($value as $k => $v) {
if (is_array($v)) {
$deep = true;
}
$a[] = sprintf('%s => %s', $k, $this->exportValue($v, $depth + 1, $deep));
}
if ($deep) {
$args = [$indent, implode(sprintf(", \n%s", $indent), $a), str_repeat(' ', $depth - 1)];
return sprintf("[\n%s%s\n%s]", ...$args);
}
$s = sprintf('[%s]', implode(', ', $a));
if (80 > strlen($s)) {
return $s;
}
return sprintf("[\n%s%s\n]", $indent, implode(sprintf(",\n%s", $indent), $a));
}
if (is_resource($value)) {
return sprintf('Resource(%s#%d)', get_resource_type($value), $value);
}
if (null === $value) {
return 'null';
}
if (false === $value) {
return 'false';
}
if (true === $value) {
return 'true';
}
return (string) $value;
}
/**
* @param \__PHP_Incomplete_Class $value
* @return mixed
* @author Bernhard Schussek <bschussek@gmail.com>
*/
private function getClassNameFromIncomplete(\__PHP_Incomplete_Class $value)
{
$array = new \ArrayObject($value);
return $array['__PHP_Incomplete_Class_Name'];
}
}

View File

@@ -0,0 +1,55 @@
<?php
declare(strict_types=1);
namespace Barryvdh\Debugbar;
use Illuminate\Contracts\View\Engine;
class DebugbarViewEngine implements Engine
{
/**
* @var Engine
*/
protected $engine;
/**
* @var LaravelDebugbar
*/
protected $laravelDebugbar;
/**
* @param Engine $engine
* @param LaravelDebugbar $laravelDebugbar
*/
public function __construct(Engine $engine, LaravelDebugbar $laravelDebugbar)
{
$this->engine = $engine;
$this->laravelDebugbar = $laravelDebugbar;
}
/**
* @param string $path
* @param array $data
* @return string
*/
public function get($path, array $data = [])
{
$shortPath = ltrim(str_replace(base_path(), '', realpath($path)), '/');
return $this->laravelDebugbar->measure($shortPath, function () use ($path, $data) {
return $this->engine->get($path, $data);
});
}
/**
* NOTE: This is done to support other Engine swap (example: Livewire).
* @param $name
* @param $arguments
* @return mixed
*/
public function __call($name, $arguments)
{
return $this->engine->$name(...$arguments);
}
}

View File

@@ -0,0 +1,30 @@
<?php
namespace Barryvdh\Debugbar;
use DebugBar\DataCollector\DataCollectorInterface;
/**
* @method static LaravelDebugbar addCollector(DataCollectorInterface $collector)
* @method static void addMessage(mixed $message, string $label = 'info')
* @method static void alert(mixed $message)
* @method static void critical(mixed $message)
* @method static void debug(mixed $message)
* @method static void emergency(mixed $message)
* @method static void error(mixed $message)
* @method static LaravelDebugbar getCollector(string $name)
* @method static bool hasCollector(string $name)
* @method static void info(mixed $message)
* @method static void log(mixed $message)
* @method static void notice(mixed $message)
* @method static void warning(mixed $message)
* @method static mixed measure(string $label, \Closure $closure)
*
* @deprecated Renamed to \Barryvdh\Debugbar\Facades\Debugbar
* @see \Barryvdh\Debugbar\Facades\Debugbar
*
* @see \Barryvdh\Debugbar\LaravelDebugbar
*/
class Facade extends \Barryvdh\Debugbar\Facades\Debugbar
{
}

View File

@@ -0,0 +1,33 @@
<?php
namespace Barryvdh\Debugbar\Facades;
use DebugBar\DataCollector\DataCollectorInterface;
/**
* @method static LaravelDebugbar addCollector(DataCollectorInterface $collector)
* @method static void addMessage(mixed $message, string $label = 'info')
* @method static void alert(mixed $message)
* @method static void critical(mixed $message)
* @method static void debug(mixed $message)
* @method static void emergency(mixed $message)
* @method static void error(mixed $message)
* @method static LaravelDebugbar getCollector(string $name)
* @method static bool hasCollector(string $name)
* @method static void info(mixed $message)
* @method static void log(mixed $message)
* @method static void notice(mixed $message)
* @method static void warning(mixed $message)
*
* @see \Barryvdh\Debugbar\LaravelDebugbar
*/
class Debugbar extends \Illuminate\Support\Facades\Facade
{
/**
* {@inheritDoc}
*/
protected static function getFacadeAccessor()
{
return \Barryvdh\Debugbar\LaravelDebugbar::class;
}
}

View File

@@ -0,0 +1,155 @@
<?php
namespace Barryvdh\Debugbar;
use DebugBar\DebugBar;
use DebugBar\JavascriptRenderer as BaseJavascriptRenderer;
use Illuminate\Routing\UrlGenerator;
/**
* {@inheritdoc}
*/
class JavascriptRenderer extends BaseJavascriptRenderer
{
// Use XHR handler by default, instead of jQuery
protected $ajaxHandlerBindToJquery = false;
protected $ajaxHandlerBindToXHR = true;
public function __construct(DebugBar $debugBar, $baseUrl = null, $basePath = null)
{
parent::__construct($debugBar, $baseUrl, $basePath);
$this->cssFiles['laravel'] = __DIR__ . '/Resources/laravel-debugbar.css';
$this->cssVendors['fontawesome'] = __DIR__ . '/Resources/vendor/font-awesome/style.css';
$this->jsFiles['laravel-sql'] = __DIR__ . '/Resources/sqlqueries/widget.js';
$this->jsFiles['laravel-cache'] = __DIR__ . '/Resources/cache/widget.js';
$theme = config('debugbar.theme', 'auto');
switch ($theme) {
case 'dark':
$this->cssFiles['laravel-dark'] = __DIR__ . '/Resources/laravel-debugbar-dark-mode.css';
break;
case 'auto':
$this->cssFiles['laravel-dark-0'] = __DIR__ . '/Resources/laravel-debugbar-dark-mode-media-start.css';
$this->cssFiles['laravel-dark-1'] = __DIR__ . '/Resources/laravel-debugbar-dark-mode.css';
$this->cssFiles['laravel-dark-2'] = __DIR__ . '/Resources/laravel-debugbar-dark-mode-media-end.css';
}
}
/**
* Set the URL Generator
*
* @param \Illuminate\Routing\UrlGenerator $url
* @deprecated
*/
public function setUrlGenerator($url)
{
}
/**
* {@inheritdoc}
*/
public function renderHead()
{
$cssRoute = route('debugbar.assets.css', [
'v' => $this->getModifiedTime('css'),
'theme' => config('debugbar.theme', 'auto'),
]);
$jsRoute = route('debugbar.assets.js', [
'v' => $this->getModifiedTime('js')
]);
$cssRoute = preg_replace('/\Ahttps?:/', '', $cssRoute);
$jsRoute = preg_replace('/\Ahttps?:/', '', $jsRoute);
$html = "<link rel='stylesheet' type='text/css' property='stylesheet' href='{$cssRoute}' data-turbolinks-eval='false' data-turbo-eval='false'>";
$html .= "<script src='{$jsRoute}' data-turbolinks-eval='false' data-turbo-eval='false'></script>";
if ($this->isJqueryNoConflictEnabled()) {
$html .= '<script data-turbo-eval="false">jQuery.noConflict(true);</script>' . "\n";
}
$html .= $this->getInlineHtml();
return $html;
}
protected function getInlineHtml()
{
$html = '';
foreach (['head', 'css', 'js'] as $asset) {
foreach ($this->getAssets('inline_' . $asset) as $item) {
$html .= $item . "\n";
}
}
return $html;
}
/**
* Get the last modified time of any assets.
*
* @param string $type 'js' or 'css'
* @return int
*/
protected function getModifiedTime($type)
{
$files = $this->getAssets($type);
$latest = 0;
foreach ($files as $file) {
$mtime = filemtime($file);
if ($mtime > $latest) {
$latest = $mtime;
}
}
return $latest;
}
/**
* Return assets as a string
*
* @param string $type 'js' or 'css'
* @return string
*/
public function dumpAssetsToString($type)
{
$files = $this->getAssets($type);
$content = '';
foreach ($files as $file) {
$content .= file_get_contents($file) . "\n";
}
return $content;
}
/**
* Makes a URI relative to another
*
* @param string|array $uri
* @param string $root
* @return string
*/
protected function makeUriRelativeTo($uri, $root)
{
if (!$root) {
return $uri;
}
if (is_array($uri)) {
$uris = [];
foreach ($uri as $u) {
$uris[] = $this->makeUriRelativeTo($u, $root);
}
return $uris;
}
if (substr($uri ?? '', 0, 1) === '/' || preg_match('/^([a-zA-Z]+:\/\/|[a-zA-Z]:\/|[a-zA-Z]:\\\)/', $uri ?? '')) {
return $uri;
}
return rtrim($root, '/') . "/$uri";
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,51 @@
<?php
namespace Barryvdh\Debugbar;
use Laravel\Lumen\Application;
class LumenServiceProvider extends ServiceProvider
{
/** @var Application */
protected $app;
/**
* Get the active router.
*
* @return Application
*/
protected function getRouter()
{
return $this->app->router;
}
/**
* Get the config path
*
* @return string
*/
protected function getConfigPath()
{
return base_path('config/debugbar.php');
}
/**
* Register the Debugbar Middleware
*
* @param string $middleware
*/
protected function registerMiddleware($middleware)
{
$this->app->middleware([$middleware]);
}
/**
* Get the services provided by the provider.
*
* @return array
*/
public function provides()
{
return ['debugbar', 'command.debugbar.clear'];
}
}

View File

@@ -0,0 +1,43 @@
<?php
namespace Barryvdh\Debugbar\Middleware;
use Closure;
use Illuminate\Http\Request;
use Barryvdh\Debugbar\LaravelDebugbar;
class DebugbarEnabled
{
/**
* The DebugBar instance
*
* @var LaravelDebugbar
*/
protected $debugbar;
/**
* Create a new middleware instance.
*
* @param LaravelDebugbar $debugbar
*/
public function __construct(LaravelDebugbar $debugbar)
{
$this->debugbar = $debugbar;
}
/**
* Handle an incoming request.
*
* @param Request $request
* @param Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
if (!$this->debugbar->isEnabled()) {
abort(404);
}
return $next($request);
}
}

View File

@@ -0,0 +1,120 @@
<?php
namespace Barryvdh\Debugbar\Middleware;
use Closure;
use Exception;
use Illuminate\Http\Request;
use Barryvdh\Debugbar\LaravelDebugbar;
use Illuminate\Contracts\Container\Container;
use Illuminate\Contracts\Debug\ExceptionHandler;
use Throwable;
class InjectDebugbar
{
/**
* The App container
*
* @var Container
*/
protected $container;
/**
* The DebugBar instance
*
* @var LaravelDebugbar
*/
protected $debugbar;
/**
* The URIs that should be excluded.
*
* @var array
*/
protected $except = [];
/**
* Create a new middleware instance.
*
* @param Container $container
* @param LaravelDebugbar $debugbar
*/
public function __construct(Container $container, LaravelDebugbar $debugbar)
{
$this->container = $container;
$this->debugbar = $debugbar;
$this->except = config('debugbar.except') ?: [];
}
/**
* Handle an incoming request.
*
* @param Request $request
* @param Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
if (!$this->debugbar->isEnabled() || $this->inExceptArray($request)) {
return $next($request);
}
$this->debugbar->boot();
try {
/** @var \Illuminate\Http\Response $response */
$response = $next($request);
} catch (Throwable $e) {
$response = $this->handleException($request, $e);
}
// Modify the response to add the Debugbar
$this->debugbar->modifyResponse($request, $response);
return $response;
}
/**
* Handle the given exception.
*
* (Copy from Illuminate\Routing\Pipeline by Taylor Otwell)
*
* @param $passable
* @param Throwable $e
* @return mixed
* @throws Exception
*/
protected function handleException($passable, $e)
{
if (! $this->container->bound(ExceptionHandler::class) || ! $passable instanceof Request) {
throw $e;
}
$handler = $this->container->make(ExceptionHandler::class);
$handler->report($e);
return $handler->render($passable, $e);
}
/**
* Determine if the request has a URI that should be ignored.
*
* @param \Illuminate\Http\Request $request
* @return bool
*/
protected function inExceptArray($request)
{
foreach ($this->except as $except) {
if ($except !== '/') {
$except = trim($except, '/');
}
if ($request->is($except)) {
return true;
}
}
return false;
}
}

View File

@@ -0,0 +1,59 @@
(function ($) {
var csscls = PhpDebugBar.utils.makecsscls('phpdebugbar-widgets-');
/**
* Widget for the displaying cache events
*
* Options:
* - data
*/
var LaravelCacheWidget = PhpDebugBar.Widgets.LaravelCacheWidget = PhpDebugBar.Widgets.TimelineWidget.extend({
tagName: 'ul',
className: csscls('timeline cache'),
onForgetClick: function (e, el) {
e.stopPropagation();
$.ajax({
url: $(el).attr("data-url"),
type: 'DELETE',
success: function (result) {
$(el).fadeOut(200);
}
});
},
render: function () {
LaravelCacheWidget.__super__.render.apply(this);
this.bindAttr('data', function (data) {
if (data.measures) {
var self = this;
var lines = this.$el.find('.' + csscls('measure'));
for (var i = 0; i < data.measures.length; i++) {
var measure = data.measures[i];
var m = lines[i];
if (measure.params && !$.isEmptyObject(measure.params)) {
if (measure.params.delete && measure.params.key) {
$('<a />')
.addClass(csscls('forget'))
.text('forget')
.attr('data-url', measure.params.delete)
.one('click', function (e) {
self.onForgetClick(e, this); })
.appendTo(m);
}
}
}
}
});
}
});
})(PhpDebugBar.$);

View File

@@ -0,0 +1 @@
@media (prefers-color-scheme: dark) {

View File

@@ -0,0 +1,290 @@
/* Dark mode */
div.phpdebugbar,
div.phpdebugbar-openhandler {
--color-gray-100: #F7FAFC;
--color-gray-200: #EDF2F7;
--color-gray-300: #E2E8F0;
--color-gray-400: #CBD5E0;
--color-gray-500: #A0AEC0;
--color-gray-600: #718096;
--color-gray-700: #4A5568;
--color-gray-800: #2D3748;
--color-gray-900: #1A202C;
--color-red-vivid: #FF0040;
}
div.phpdebugbar,
div.phpdebugbar-openhandler {
background: var(--color-gray-800);
}
div.phpdebugbar,
div.phpdebugbar-openhandler,
div.phpdebugbar div.phpdebugbar-header > div > *,
div.phpdebugbar ul.phpdebugbar-widgets-timeline li span.phpdebugbar-widgets-label,
div.phpdebugbar ul.phpdebugbar-widgets-timeline li span.phpdebugbar-widgets-collector,
div.phpdebugbar code.phpdebugbar-widgets-sql span.hljs-keyword,
div.phpdebugbar-openhandler .phpdebugbar-openhandler-header,
div.phpdebugbar-openhandler .phpdebugbar-openhandler-header a {
color: var(--color-gray-200);
}
div.phpdebugbar-openhandler,
div.phpdebugbar div.phpdebugbar-widgets-messages div.phpdebugbar-widgets-toolbar,
div.phpdebugbar div.phpdebugbar-widgets-exceptions li.phpdebugbar-widgets-list-item pre.phpdebugbar-widgets-file,
div.phpdebugbar ul.phpdebugbar-widgets-list li.phpdebugbar-widgets-list-item table.phpdebugbar-widgets-params,
div.phpdebugbar-openhandler .phpdebugbar-openhandler-actions > a,
div.phpdebugbar-openhandler .phpdebugbar-openhandler-actions button,
div.phpdebugbar-openhandler .phpdebugbar-openhandler-actions > form input,
div.phpdebugbar-openhandler .phpdebugbar-openhandler-actions > form select {
border-color: var(--color-gray-600);
}
div.phpdebugbar div.phpdebugbar-header,
div.phpdebugbar div.phpdebugbar-panel div.phpdebugbar-widgets-status > span:first-child:before,
div.phpdebugbar-openhandler table th,
div.phpdebugbar-openhandler .phpdebugbar-openhandler-actions > a,
div.phpdebugbar-openhandler .phpdebugbar-openhandler-actions button,
div.phpdebugbar-openhandler .phpdebugbar-openhandler-actions > form input,
div.phpdebugbar-openhandler .phpdebugbar-openhandler-actions > form select {
text-shadow: 1px 1px var(--color-gray-700);
}
div.phpdebugbar div.phpdebugbar-header > div > select,
div.phpdebugbar ul.phpdebugbar-widgets-list li.phpdebugbar-widgets-list-item table.phpdebugbar-widgets-params,
div.phpdebugbar-openhandler .phpdebugbar-openhandler-actions > form input,
div.phpdebugbar-openhandler .phpdebugbar-openhandler-actions > form select,
div.phpdebugbar input[type='text'],
div.phpdebugbar input[type='password'] {
background-color: var(--color-gray-800);
}
div.phpdebugbar div.phpdebugbar-header,
div.phpdebugbar a.phpdebugbar-restore-btn,
div.phpdebugbar-openhandler .phpdebugbar-openhandler-header,
div.phpdebugbar dl.phpdebugbar-widgets-kvlist > :nth-child(4n-1),
div.phpdebugbar dl.phpdebugbar-widgets-kvlist > :nth-child(4n),
div.phpdebugbar ul.phpdebugbar-widgets-list li.phpdebugbar-widgets-list-item:nth-child(even),
div.phpdebugbar .hljs,
div.phpdebugbar div.phpdebugbar-widgets-sqlqueries table.phpdebugbar-widgets-params th,
div.phpdebugbar-openhandler .phpdebugbar-openhandler-actions > a,
div.phpdebugbar-openhandler .phpdebugbar-openhandler-actions button,
div.phpdebugbar div.phpdebugbar-widgets-templates table.phpdebugbar-widgets-params th {
background-color: var(--color-gray-900);
}
div.phpdebugbar .phpdebugbar-widgets-mails ul.phpdebugbar-widgets-list li.phpdebugbar-widgets-list-item .phpdebugbar-widgets-headers,
div.phpdebugbar ul.phpdebugbar-widgets-list li.phpdebugbar-widgets-list-item table.phpdebugbar-widgets-params {
border-left-color: var(--color-gray-600);
}
div.phpdebugbar a.phpdebugbar-tab:hover,
div.phpdebugbar span.phpdebugbar-indicator:hover,
div.phpdebugbar a.phpdebugbar-indicator:hover,
div.phpdebugbar a.phpdebugbar-close-btn:hover,
div.phpdebugbar a.phpdebugbar-minimize-btn:hover,
div.phpdebugbar a.phpdebugbar-maximize-btn:hover,
div.phpdebugbar a.phpdebugbar-open-btn:hover,
div.phpdebugbar-openhandler table th,
div.phpdebugbar-openhandler table tr:nth-child(2n),
div.phpdebugbar div.phpdebugbar-widgets-messages div.phpdebugbar-widgets-toolbar {
background-color: var(--color-gray-700);
}
div.phpdebugbar .phpdebugbar-indicator span.phpdebugbar-tooltip,
div.phpdebugbar div.phpdebugbar-mini-design a.phpdebugbar-tab:hover span.phpdebugbar-text,
div.phpdebugbar pre.sf-dump,
div.phpdebugbar .hljs,
div.phpdebugbar code.phpdebugbar-widgets-sql span.hljs-operator {
color: var(--color-gray-100);
}
div.phpdebugbar pre.sf-dump .sf-dump-public,
div.phpdebugbar pre.sf-dump .sf-dump-protected,
div.phpdebugbar pre.sf-dump .sf-dump-private {
color: var(--color-gray-100) !important;
}
div.phpdebugbar div.phpdebugbar-panel div.phpdebugbar-widgets-status > span:first-child:before,
div.phpdebugbar-openhandler a {
color: var(--color-gray-500);
}
div.phpdebugbar .phpdebugbar-indicator span.phpdebugbar-tooltip,
div.phpdebugbar div.phpdebugbar-mini-design a.phpdebugbar-tab:hover span.phpdebugbar-text {
background: var(--color-gray-900);
}
div.phpdebugbar .hljs-tag .hljs-value,
div.phpdebugbar .hljs-phpdoc,
div.phpdebugbar .tex .hljs-formula,
div.phpdebugbar div.phpdebugbar-widgets-exceptions li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-message {
color: var(--color-red-vivid);
}
div.phpdebugbar div.phpdebugbar-widgets-exceptions li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-filename,
div.phpdebugbar div.phpdebugbar-widgets-sqlqueries li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-database,
div.phpdebugbar div.phpdebugbar-widgets-sqlqueries li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-duration,
div.phpdebugbar div.phpdebugbar-widgets-sqlqueries li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-memory,
div.phpdebugbar div.phpdebugbar-widgets-sqlqueries li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-row-count,
div.phpdebugbar div.phpdebugbar-widgets-sqlqueries li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-copy-clipboard,
div.phpdebugbar div.phpdebugbar-widgets-sqlqueries li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-stmt-id,
div.phpdebugbar .phpdebugbar-widgets-callgraph pre,
div.phpdebugbar .phpdebugbar-text-muted,
div.phpdebugbar-openhandler .phpdebugbar-text-muted
{
color: var(--color-gray-600);
}
div.phpdebugbar div.phpdebugbar-widgets-sqlqueries li.phpdebugbar-widgets-list-item.phpdebugbar-widgets-sql-duplicate {
background-color: #6f6200;
}
div.phpdebugbar-widgets-messages li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-value:before {
color: #7B7B7B;
}
div.phpdebugbar-openhandler {
border-top-color: #fa5661;
}
div.phpdebugbar div.phpdebugbar-header .phpdebugbar-tab {
border-left-color: var(--color-gray-800);
}
div.phpdebugbar div.phpdebugbar-body {
border-top-color: var(--color-gray-800);
}
div.phpdebugbar a.phpdebugbar-restore-btn {
border-right-color: var(--color-gray-800) !important;
}
div.phpdebugbar span.phpdebugbar-indicator,
div.phpdebugbar a.phpdebugbar-indicator,
div.phpdebugbar a.phpdebugbar-close-btn {
border-right-color: var(--color-gray-800);
}
div.phpdebugbar div.phpdebugbar-panel div.phpdebugbar-widgets-status {
background-color: var(--color-gray-900) !important;
border-bottom-color: var(--color-gray-800) !important;
}
div.phpdebugbar div.phpdebugbar-widgets-templates div.phpdebugbar-widgets-status {
background: var(--color-gray-900) !important;
}
div.phpdebugbar div.phpdebugbar-panel div.phpdebugbar-widgets-status > * {
color: var(--color-gray-200) !important;
}
div.phpdebugbar div.phpdebugbar-widgets-templates span.phpdebugbar-widgets-render-time,
div.phpdebugbar div.phpdebugbar-widgets-templates span.phpdebugbar-widgets-memory,
div.phpdebugbar div.phpdebugbar-widgets-templates span.phpdebugbar-widgets-param-count,
div.phpdebugbar div.phpdebugbar-widgets-templates span.phpdebugbar-widgets-type {
color: var(--color-gray-600) !important;
}
div.phpdebugbar div.phpdebugbar-widgets-sqlqueries table.phpdebugbar-widgets-params td {
border-color: var(--color-gray-600) !important;
}
div.phpdebugbar code,
div.phpdebugbar pre {
color: #FFF;
}
div.phpdebugbar-openhandler .phpdebugbar-openhandler-actions > a,
div.phpdebugbar-openhandler .phpdebugbar-openhandler-actions button,
div.phpdebugbar-openhandler .phpdebugbar-openhandler-actions > form input,
div.phpdebugbar-openhandler .phpdebugbar-openhandler-actions > form select,
div.phpdebugbar input[type='text'],
div.phpdebugbar input[type='password'] {
color: var(--color-gray-300);
}
div.phpdebugbar div.phpdebugbar-widgets-exceptions li.phpdebugbar-widgets-list-item.phpdebugbar-widgets-sql-duplicate span.phpdebugbar-widgets-filename,
div.phpdebugbar div.phpdebugbar-widgets-sqlqueries li.phpdebugbar-widgets-list-item.phpdebugbar-widgets-sql-duplicate span.phpdebugbar-widgets-database,
div.phpdebugbar div.phpdebugbar-widgets-sqlqueries li.phpdebugbar-widgets-list-item.phpdebugbar-widgets-sql-duplicate span.phpdebugbar-widgets-duration,
div.phpdebugbar div.phpdebugbar-widgets-sqlqueries li.phpdebugbar-widgets-list-item.phpdebugbar-widgets-sql-duplicate span.phpdebugbar-widgets-memory,
div.phpdebugbar div.phpdebugbar-widgets-sqlqueries li.phpdebugbar-widgets-list-item.phpdebugbar-widgets-sql-duplicate span.phpdebugbar-widgets-row-count,
div.phpdebugbar div.phpdebugbar-widgets-sqlqueries li.phpdebugbar-widgets-list-item.phpdebugbar-widgets-sql-duplicate span.phpdebugbar-widgets-copy-clipboard,
div.phpdebugbar div.phpdebugbar-widgets-sqlqueries li.phpdebugbar-widgets-list-item.phpdebugbar-widgets-sql-duplicate span.phpdebugbar-widgets-stmt-id {
color: var(--color-gray-500);
}
div.phpdebugbar a.phpdebugbar-minimize-btn {
background: url(data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%201792%201792%22%20id%3D%22chevron-down%22%3E%3Cpath%20d%3D%22M1683%20808l-742%20741q-19%2019-45%2019t-45-19l-742-741q-19-19-19-45.5t19-45.5l166-165q19-19%2045-19t45%2019l531%20531%20531-531q19-19%2045-19t45%2019l166%20165q19%2019%2019%2045.5t-19%2045.5z%22%20style%3D%22fill%3A%20%23EDF2F7%22%2F%3E%3C%2Fsvg%3E) no-repeat 6px 6px / 14px 14px;
}
div.phpdebugbar a.phpdebugbar-maximize-btn {
background: url(data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%201792%201792%22%20id%3D%22chevron-up%22%3E%3Cpath%20d%3D%22M1683%201331l-166%20165q-19%2019-45%2019t-45-19l-531-531-531%20531q-19%2019-45%2019t-45-19l-166-165q-19-19-19-45.5t19-45.5l742-741q19-19%2045-19t45%2019l742%20741q19%2019%2019%2045.5t-19%2045.5z%22%20style%3D%22fill%3A%20%23EDF2F7%22%2F%3E%3C%2Fsvg%3E) no-repeat 6px 6px / 14px 14px;
}
div.phpdebugbar a.phpdebugbar-open-btn {
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAOCAYAAADJ7fe0AAABL0lEQVQ4T63RvWqEQBAA4LkjdX46WQh5hoDpFnyAgGzKWKQJdgFfIT8vIKSwCSEQHyJN4AptomAlZMXAVRuxWAwibqMGBUVygdtAplmWmf1mmVnAP8RiNDjne0KINQDsz9wCIXSwrc+AMMa6tm0hz3PozzGWyyUoirJhIISm5n1yuIRh2G3rNs+rqvo7IoTIMMbnkthqXjf9JAiCO0LIR9d1T5JQXzbMbEA8z/vEGB9TSt/KsjyURZIkeTQM43JAHMe5JYS8Zlm2appG1gDXdbFt2/44IIVS+lCW5amswBh70XX9DADEuOIjzvlaCCFrgO/7F5ZlPU8rTtP0viiKK1mhqqpU07STfrATEsfxV13Xu7JIFEU3pmlej/XjTDAA7MgiAPAOANlP5A/vN0u/AXUIgA+u4l6FAAAAAElFTkSuQmCC) no-repeat 8px 6px;
}
div.phpdebugbar a.phpdebugbar-close-btn {
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAABUElEQVQ4T52SMUsDMRTH3xUPChHCxeko3YrUqeFGEexym3boJ9DBufhJpLODfoIbTrcuFcSxxMki3Uq5yZRAAweRVp70HdfWQZolb3i/l/x/iQd7Lm9PDjbA2Wz24HmerFarbSGEwaFaa57n+XC1WqlarXZNBxUgQsaYK+ccCCHeGWPn2GStfdFat3zfB875I8EFOBqNPpbLZRObsQnh9YktHIarUqmMoyg6wboApZTtfr9/zxhrEIw7QdbaSa/Xu1FKDTdAADiQUp6VYcpTgl4B4HsbhCRJjsIwfPN9/7hs2zn3mWXZabfb/dqRg/ZIBF2PmigzCiPbRcbpdKrQXjkTguXMKKxer8uNqw4Gg6cgCC7WT/ArAuty5vl8/hzH8eV2xmaapnec88baHooAEmaMmXQ6nVsAGO/IAQB8x0MAUGQPbSMPAAuC/gL//XV/ALsvnQ+MsaHgAAAAAElFTkSuQmCC) no-repeat 9px 6px;
}
/* Dracula Theme v1.2.5
*
* https://github.com/dracula/highlightjs
*
* Copyright 2016-present, All rights reserved
*
* Code licensed under the MIT license
*
* @author Denis Ciccale <dciccale@gmail.com>
* @author Zeno Rocha <hi@zenorocha.com>
*/
div.phpdebugbar .hljs-built_in,
div.phpdebugbar .hljs-selector-tag,
div.phpdebugbar .hljs-section,
div.phpdebugbar .hljs-link {
color: #8be9fd;
}
div.phpdebugbar .hljs-keyword {
color: #ff79c6;
}
div.phpdebugbar .hljs,
div.phpdebugbar .hljs-subst {
color: #f8f8f2;
}
div.phpdebugbar .hljs-title {
color: #50fa7b;
}
div.phpdebugbar .hljs-string,
div.phpdebugbar .hljs-meta,
div.phpdebugbar .hljs-name,
div.phpdebugbar .hljs-type,
div.phpdebugbar .hljs-attr,
div.phpdebugbar .hljs-symbol,
div.phpdebugbar .hljs-bullet,
div.phpdebugbar .hljs-addition,
div.phpdebugbar .hljs-variable,
div.phpdebugbar .hljs-template-tag,
div.phpdebugbar .hljs-template-variable {
color: #f1fa8c;
}
div.phpdebugbar .hljs-comment,
div.phpdebugbar .hljs-quote,
div.phpdebugbar .hljs-deletion {
color: #6272a4;
}
div.phpdebugbar .hljs-literal,
div.phpdebugbar .hljs-number {
color: #bd93f9;
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,274 @@
(function ($) {
var csscls = PhpDebugBar.utils.makecsscls('phpdebugbar-widgets-');
/**
* Widget for the displaying sql queries
*
* Options:
* - data
*/
var LaravelSQLQueriesWidget = PhpDebugBar.Widgets.LaravelSQLQueriesWidget = PhpDebugBar.Widget.extend({
className: csscls('sqlqueries'),
onFilterClick: function (el) {
$(el).toggleClass(csscls('excluded'));
var excludedLabels = [];
this.$toolbar.find(csscls('.filter') + csscls('.excluded')).each(function () {
excludedLabels.push(this.rel);
});
this.$list.$el.find("li[connection=" + $(el).attr("rel") + "]").toggle();
this.set('exclude', excludedLabels);
},
onCopyToClipboard: function (el) {
var code = $(el).parent('li').find('code').get(0);
var copy = function () {
try {
document.execCommand('copy');
alert('Query copied to the clipboard');
} catch (err) {
console.log('Oops, unable to copy');
}
};
var select = function (node) {
if (document.selection) {
var range = document.body.createTextRange();
range.moveToElementText(node);
range.select();
} else if (window.getSelection) {
var range = document.createRange();
range.selectNodeContents(node);
window.getSelection().removeAllRanges();
window.getSelection().addRange(range);
}
copy();
window.getSelection().removeAllRanges();
};
select(code);
},
render: function () {
this.$status = $('<div />').addClass(csscls('status')).appendTo(this.$el);
this.$toolbar = $('<div></div>').addClass(csscls('toolbar')).appendTo(this.$el);
var filters = [], self = this;
this.$list = new PhpDebugBar.Widgets.ListWidget({ itemRenderer: function (li, stmt) {
if (stmt.type === 'transaction') {
$('<strong />').addClass(csscls('sql')).addClass(csscls('name')).text(stmt.sql).appendTo(li);
} else {
$('<code />').addClass(csscls('sql')).html(PhpDebugBar.Widgets.highlight(stmt.sql, 'sql')).appendTo(li);
}
if (stmt.width_percent) {
$('<div></div>').addClass(csscls('bg-measure')).append(
$('<div></div>').addClass(csscls('value')).css({
left: stmt.start_percent + '%',
width: Math.max(stmt.width_percent, 0.01) + '%',
})
).appendTo(li);
}
if (stmt.duration_str) {
$('<span title="Duration" />').addClass(csscls('duration')).text(stmt.duration_str).appendTo(li);
}
if (stmt.memory_str) {
$('<span title="Memory usage" />').addClass(csscls('memory')).text(stmt.memory_str).appendTo(li);
}
if (typeof(stmt.row_count) != 'undefined') {
$('<span title="Row count" />').addClass(csscls('row-count')).text(stmt.row_count).appendTo(li);
}
if (typeof(stmt.stmt_id) != 'undefined' && stmt.stmt_id) {
$('<span title="Prepared statement ID" />').addClass(csscls('stmt-id')).text(stmt.stmt_id).appendTo(li);
}
if (stmt.connection) {
$('<span title="Connection" />').addClass(csscls('database')).text(stmt.connection).appendTo(li);
li.attr("connection",stmt.connection);
if ( $.inArray(stmt.connection, filters) == -1 ) {
filters.push(stmt.connection);
$('<a />')
.addClass(csscls('filter'))
.text(stmt.connection)
.attr('rel', stmt.connection)
.on('click', function () {
self.onFilterClick(this); })
.appendTo(self.$toolbar);
if (filters.length > 1) {
self.$toolbar.show();
self.$list.$el.css("margin-bottom","20px");
}
}
}
if (typeof(stmt.is_success) != 'undefined' && !stmt.is_success) {
li.addClass(csscls('error'));
li.append($('<span />').addClass(csscls('error')).text("[" + stmt.error_code + "] " + stmt.error_message));
}
if (stmt.show_copy) {
$('<span title="Copy to clipboard" />')
.addClass(csscls('copy-clipboard'))
.css('cursor', 'pointer')
.on('click', function (event) {
self.onCopyToClipboard(this);
event.stopPropagation();
})
.appendTo(li);
}
var table = $('<table><tr><th colspan="2">Metadata</th></tr></table>').addClass(csscls('params')).appendTo(li);
if (stmt.bindings && stmt.bindings.length) {
table.append(function () {
var icon = 'thumb-tack';
var $icon = '<i class="phpdebugbar-fa phpdebugbar-fa-' + icon + ' phpdebugbar-text-muted"></i>';
var $name = $('<td />').addClass(csscls('name')).html('Bindings ' + $icon);
var $value = $('<td />').addClass(csscls('value'));
var $span = $('<span />').addClass('phpdebugbar-text-muted');
var index = 0;
var $bindings = new PhpDebugBar.Widgets.ListWidget({ itemRenderer: function (li, binding) {
var $index = $span.clone().text(index++ + '.');
li.append($index, '&nbsp;', binding).removeClass(csscls('list-item')).addClass(csscls('table-list-item'));
}});
$bindings.set('data', stmt.bindings);
$bindings.$el
.removeClass(csscls('list'))
.addClass(csscls('table-list'))
.appendTo($value);
return $('<tr />').append($name, $value);
});
}
if (stmt.hints && stmt.hints.length) {
table.append(function () {
var icon = 'question-circle';
var $icon = '<i class="phpdebugbar-fa phpdebugbar-fa-' + icon + ' phpdebugbar-text-muted"></i>';
var $name = $('<td />').addClass(csscls('name')).html('Hints ' + $icon);
var $value = $('<td />').addClass(csscls('value'));
var $hints = new PhpDebugBar.Widgets.ListWidget({ itemRenderer: function (li, hint) {
li.append(hint).removeClass(csscls('list-item')).addClass(csscls('table-list-item'));
}});
$hints.set('data', stmt.hints);
$hints.$el
.removeClass(csscls('list'))
.addClass(csscls('table-list'))
.appendTo($value);
return $('<tr />').append($name, $value);
});
}
if (stmt.backtrace && stmt.backtrace.length) {
table.append(function () {
var icon = 'list-ul';
var $icon = '<i class="phpdebugbar-fa phpdebugbar-fa-' + icon + ' phpdebugbar-text-muted"></i>';
var $name = $('<td />').addClass(csscls('name')).html('Backtrace ' + $icon);
var $value = $('<td />').addClass(csscls('value'));
var $span = $('<span />').addClass('phpdebugbar-text-muted');
var $backtrace = new PhpDebugBar.Widgets.ListWidget({ itemRenderer: function (li, source) {
var $parts = [
$span.clone().text(source.index + '.'),
'&nbsp;',
];
if (source.namespace) {
$parts.push(source.namespace + '::');
}
$parts.push(source.name);
$parts.push($span.clone().text(':' + source.line));
li.append($parts).removeClass(csscls('list-item')).addClass(csscls('table-list-item'));
}});
$backtrace.set('data', stmt.backtrace);
$backtrace.$el
.removeClass(csscls('list'))
.addClass(csscls('table-list'))
.appendTo($value);
return $('<tr />').append($name, $value);
});
}
if (stmt.params && !$.isEmptyObject(stmt.params)) {
for (var key in stmt.params) {
if (typeof stmt.params[key] !== 'function') {
table.append('<tr><td class="' + csscls('name') + '">' + key + '</td><td class="' + csscls('value') +
'">' + stmt.params[key] + '</td></tr>');
}
}
}
li.css('cursor', 'pointer').click(function () {
if (table.is(':visible')) {
table.hide();
} else {
table.show();
}
});
}});
this.$list.$el.appendTo(this.$el);
this.bindAttr('data', function (data) {
this.$list.set('data', data.statements);
this.$status.empty();
var stmt;
// Search for duplicate statements.
for (var sql = {}, duplicate = 0, i = 0; i < data.statements.length; i++) {
if (data.statements[i].type === 'query') {
stmt = data.statements[i].sql;
if (data.statements[i].bindings && data.statements[i].bindings.length) {
stmt += JSON.stringify(data.statements[i].bindings);
}
if (data.statements[i].connection) {
stmt += '@' + data.statements[i].connection;
}
sql[stmt] = sql[stmt] || { keys: [] };
sql[stmt].keys.push(i);
}
}
// Add classes to all duplicate SQL statements.
for (stmt in sql) {
if (sql[stmt].keys.length > 1) {
duplicate += sql[stmt].keys.length;
for (i = 0; i < sql[stmt].keys.length; i++) {
this.$list.$el.find('.' + csscls('list-item')).eq(sql[stmt].keys[i])
.addClass(csscls('sql-duplicate'))
.addClass(csscls('sql-duplicate-' + duplicate));
}
}
}
var t = $('<span />').text(data.nb_statements + " statements were executed").appendTo(this.$status);
if (data.nb_failed_statements) {
t.append(", " + data.nb_failed_statements + " of which failed");
}
if (duplicate) {
t.append(", " + duplicate + " of which were duplicated");
t.append(", " + (data.nb_statements - duplicate) + " unique");
}
if (data.accumulated_duration_str) {
this.$status.append($('<span title="Accumulated duration" />').addClass(csscls('duration')).text(data.accumulated_duration_str));
}
if (data.memory_usage_str) {
this.$status.append($('<span title="Memory usage" />').addClass(csscls('memory')).text(data.memory_usage_str));
}
});
}
});
})(PhpDebugBar.$);

View File

@@ -0,0 +1,5 @@
# Font Squirrel Font-face Generator Configuration File
# Upload this file to the generator to recreate the settings
# you used to create these fonts.
{"mode":"expert","formats":["woff"],"tt_instructor":"keep","fallback":"none","fallback_custom":"100","options_subset":"none","subset_custom":"","subset_custom_range":"","subset_ot_features":"all","subset_ot_features_list":"","base64":"Y","css_stylesheet":"style.css","filename_suffix":"","emsquare":"2048","spacing_adjustment":"0","rememberme":"Y"}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,156 @@
<?php
namespace Barryvdh\Debugbar;
use Barryvdh\Debugbar\Middleware\DebugbarEnabled;
use Barryvdh\Debugbar\Middleware\InjectDebugbar;
use DebugBar\DataFormatter\DataFormatter;
use DebugBar\DataFormatter\DataFormatterInterface;
use Illuminate\Contracts\Http\Kernel;
use Illuminate\Foundation\Application;
use Illuminate\Routing\Router;
use Illuminate\Session\SessionManager;
use Illuminate\Support\Collection;
use Illuminate\View\Engines\EngineResolver;
use Barryvdh\Debugbar\Facade as DebugBar;
class ServiceProvider extends \Illuminate\Support\ServiceProvider
{
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
$configPath = __DIR__ . '/../config/debugbar.php';
$this->mergeConfigFrom($configPath, 'debugbar');
$this->app->alias(
DataFormatter::class,
DataFormatterInterface::class
);
$this->app->singleton(LaravelDebugbar::class, function ($app) {
$debugbar = new LaravelDebugbar($app);
if ($app->bound(SessionManager::class)) {
$sessionManager = $app->make(SessionManager::class);
$httpDriver = new SymfonyHttpDriver($sessionManager);
$debugbar->setHttpDriver($httpDriver);
}
return $debugbar;
});
$this->app->alias(LaravelDebugbar::class, 'debugbar');
$this->app->singleton(
'command.debugbar.clear',
function ($app) {
return new Console\ClearCommand($app['debugbar']);
}
);
$this->app->extend(
'view.engine.resolver',
function (EngineResolver $resolver, Application $application): EngineResolver {
$laravelDebugbar = $application->make(LaravelDebugbar::class);
$shouldTrackViewTime = $laravelDebugbar->isEnabled() &&
$laravelDebugbar->shouldCollect('time', true) &&
$laravelDebugbar->shouldCollect('views', true) &&
$application['config']->get('debugbar.options.views.timeline', false);
if (! $shouldTrackViewTime) {
/* Do not swap the engine to save performance */
return $resolver;
}
return new class ($resolver, $laravelDebugbar) extends EngineResolver {
private $laravelDebugbar;
public function __construct(EngineResolver $resolver, LaravelDebugbar $laravelDebugbar)
{
foreach ($resolver->resolvers as $engine => $resolver) {
$this->register($engine, $resolver);
}
$this->laravelDebugbar = $laravelDebugbar;
}
public function register($engine, \Closure $resolver)
{
parent::register($engine, function () use ($resolver) {
return new DebugbarViewEngine($resolver(), $this->laravelDebugbar);
});
}
};
}
);
Collection::macro('debug', function () {
debug($this);
return $this;
});
}
/**
* Bootstrap the application events.
*
* @return void
*/
public function boot()
{
$configPath = __DIR__ . '/../config/debugbar.php';
$this->publishes([$configPath => $this->getConfigPath()], 'config');
$this->loadRoutesFrom(realpath(__DIR__ . '/debugbar-routes.php'));
$this->registerMiddleware(InjectDebugbar::class);
if ($this->app->runningInConsole()) {
$this->commands(['command.debugbar.clear']);
}
}
/**
* Get the active router.
*
* @return Router
*/
protected function getRouter()
{
return $this->app['router'];
}
/**
* Get the config path
*
* @return string
*/
protected function getConfigPath()
{
return config_path('debugbar.php');
}
/**
* Publish the config file
*
* @param string $configPath
*/
protected function publishConfig($configPath)
{
$this->publishes([$configPath => config_path('debugbar.php')], 'config');
}
/**
* Register the Debugbar Middleware
*
* @param string $middleware
*/
protected function registerMiddleware($middleware)
{
$kernel = $this->app[Kernel::class];
$kernel->pushMiddleware($middleware);
}
}

View File

@@ -0,0 +1,144 @@
<?php
namespace Barryvdh\Debugbar\Storage;
use DebugBar\Storage\StorageInterface;
use Illuminate\Filesystem\Filesystem;
use Symfony\Component\Finder\Finder;
/**
* Stores collected data into files
*/
class FilesystemStorage implements StorageInterface
{
protected $dirname;
protected $files;
protected $gc_lifetime = 24; // Hours to keep collected data;
protected $gc_probability = 5; // Probability of GC being run on a save request. (5/100)
/**
* @param \Illuminate\Filesystem\Filesystem $files The filesystem
* @param string $dirname Directories where to store files
*/
public function __construct($files, $dirname)
{
$this->files = $files;
$this->dirname = rtrim($dirname, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
}
/**
* {@inheritDoc}
*/
public function save($id, $data)
{
if (!$this->files->isDirectory($this->dirname)) {
if ($this->files->makeDirectory($this->dirname, 0777, true)) {
$this->files->put($this->dirname . '.gitignore', "*\n!.gitignore\n");
} else {
throw new \Exception("Cannot create directory '$this->dirname'..");
}
}
try {
$this->files->put($this->makeFilename($id), json_encode($data));
} catch (\Exception $e) {
//TODO; error handling
}
// Randomly check if we should collect old files
if (rand(1, 100) <= $this->gc_probability) {
$this->garbageCollect();
}
}
/**
* Create the filename for the data, based on the id.
*
* @param $id
* @return string
*/
public function makeFilename($id)
{
return $this->dirname . basename($id) . ".json";
}
/**
* Delete files older then a certain age (gc_lifetime)
*/
protected function garbageCollect()
{
foreach (
Finder::create()->files()->name('*.json')->date('< ' . $this->gc_lifetime . ' hour ago')->in(
$this->dirname
) as $file
) {
$this->files->delete($file->getRealPath());
}
}
/**
* {@inheritDoc}
*/
public function get($id)
{
return json_decode($this->files->get($this->makeFilename($id)), true);
}
/**
* {@inheritDoc}
*/
public function find(array $filters = [], $max = 20, $offset = 0)
{
// Sort by modified time, newest first
$sort = function (\SplFileInfo $a, \SplFileInfo $b) {
return strcmp($b->getMTime(), $a->getMTime());
};
// Loop through .json files, filter the metadata and stop when max is found.
$i = 0;
$results = [];
foreach (Finder::create()->files()->name('*.json')->in($this->dirname)->sort($sort) as $file) {
if ($i++ < $offset && empty($filters)) {
$results[] = null;
continue;
}
$data = json_decode($file->getContents(), true);
$meta = $data['__meta'];
unset($data);
if ($this->filter($meta, $filters)) {
$results[] = $meta;
}
if (count($results) >= ($max + $offset)) {
break;
}
}
return array_slice($results, $offset, $max);
}
/**
* Filter the metadata for matches.
*
* @param $meta
* @param $filters
* @return bool
*/
protected function filter($meta, $filters)
{
foreach ($filters as $key => $value) {
if (!isset($meta[$key]) || fnmatch($value, $meta[$key]) === false) {
return false;
}
}
return true;
}
/**
* {@inheritDoc}
*/
public function clear()
{
foreach (Finder::create()->files()->name('*.json')->in($this->dirname) as $file) {
$this->files->delete($file->getRealPath());
}
}
}

View File

@@ -0,0 +1,99 @@
<?php
namespace Barryvdh\Debugbar\Storage;
use DebugBar\Storage\StorageInterface;
class SocketStorage implements StorageInterface
{
protected $hostname;
protected $port;
protected $socket;
/**
* @param string $hostname The hostname to use for the socket
* @param int $port The port to use for the socket
*/
public function __construct($hostname, $port)
{
$this->hostname = $hostname;
$this->port = $port;
}
/**
* @inheritDoc
*/
function save($id, $data)
{
$socketIsFresh = !$this->socket;
if (!$this->socket = $this->socket ?: $this->createSocket()) {
return false;
}
$encodedPayload = json_encode([
'id' => $id,
'base_path' => base_path(),
'app' => config('app.name'),
'data' => $data,
]);
$encodedPayload = strlen($encodedPayload) . '#' . $encodedPayload;
set_error_handler([self::class, 'nullErrorHandler']);
try {
if (-1 !== stream_socket_sendto($this->socket, $encodedPayload)) {
return true;
}
if (!$socketIsFresh) {
stream_socket_shutdown($this->socket, \STREAM_SHUT_RDWR);
fclose($this->socket);
$this->socket = $this->createSocket();
}
if (-1 !== stream_socket_sendto($this->socket, $encodedPayload)) {
return true;
}
} finally {
restore_error_handler();
}
}
private static function nullErrorHandler($t, $m)
{
// no-op
}
protected function createSocket()
{
set_error_handler([self::class, 'nullErrorHandler']);
try {
return stream_socket_client("tcp://{$this->hostname}:{$this->port}");
} finally {
restore_error_handler();
}
}
/**
* @inheritDoc
*/
function get($id)
{
//
}
/**
* @inheritDoc
*/
function find(array $filters = array(), $max = 20, $offset = 0)
{
//
}
/**
* @inheritDoc
*/
function clear()
{
//
}
}

View File

@@ -0,0 +1,90 @@
<?php
namespace Barryvdh\Debugbar\Support\Clockwork;
use DebugBar\DataCollector\DataCollector;
use DebugBar\DataCollector\DataCollectorInterface;
use DebugBar\DataCollector\Renderable;
use Symfony\Component\HttpFoundation\Response;
/**
*
* Based on \Symfony\Component\HttpKernel\DataCollector\RequestDataCollector by Fabien Potencier <fabien@symfony.com>
*
*/
class ClockworkCollector extends DataCollector implements DataCollectorInterface, Renderable
{
/** @var \Symfony\Component\HttpFoundation\Request $request */
protected $request;
/** @var \Symfony\Component\HttpFoundation\Request $response */
protected $response;
/** @var \Symfony\Component\HttpFoundation\Session\SessionInterface $session */
protected $session;
/**
* Create a new SymfonyRequestCollector
*
* @param \Symfony\Component\HttpFoundation\Request $request
* @param \Symfony\Component\HttpFoundation\Request $response
* @param \Symfony\Component\HttpFoundation\Session\SessionInterface $session
*/
public function __construct($request, $response, $session = null)
{
$this->request = $request;
$this->response = $response;
$this->session = $session;
}
/**
* {@inheritDoc}
*/
public function getName()
{
return 'clockwork';
}
/**
* {@inheritDoc}
*/
public function getWidgets()
{
return null;
}
/**
* {@inheritdoc}
*/
public function collect()
{
$request = $this->request;
$response = $this->response;
$data = [
'getData' => $request->query->all(),
'postData' => $request->request->all(),
'headers' => $request->headers->all(),
'cookies' => $request->cookies->all(),
'uri' => $request->getRequestUri(),
'method' => $request->getMethod(),
'responseStatus' => $response->getStatusCode(),
];
if ($this->session) {
$sessionAttributes = [];
foreach ($this->session->all() as $key => $value) {
$sessionAttributes[$key] = $value;
}
$data['sessionData'] = $sessionAttributes;
}
if (isset($data['postData']['php-auth-pw'])) {
$data['postData']['php-auth-pw'] = '******';
}
if (isset($data['postData']['PHP_AUTH_PW'])) {
$data['postData']['PHP_AUTH_PW'] = '******';
}
return $data;
}
}

View File

@@ -0,0 +1,139 @@
<?php
namespace Barryvdh\Debugbar\Support\Clockwork;
class Converter
{
/**
* Convert the phpdebugbar data to Clockwork format.
*
* @param array $data
* @return array
*/
public function convert($data)
{
$meta = $data['__meta'];
// Default output
$output = [
'id' => $meta['id'],
'method' => $meta['method'],
'uri' => $meta['uri'],
'time' => $meta['utime'],
'headers' => [],
'cookies' => [],
'emailsData' => [],
'getData' => [],
'log' => [],
'postData' => [],
'sessionData' => [],
'timelineData' => [],
'viewsData' => [],
'controller' => null,
'responseTime' => null,
'responseStatus' => null,
'responseDuration' => 0,
];
if (isset($data['clockwork'])) {
$output = array_merge($output, $data['clockwork']);
}
if (isset($data['time'])) {
$time = $data['time'];
$output['time'] = $time['start'];
$output['responseTime'] = $time['end'];
$output['responseDuration'] = $time['duration'] * 1000;
foreach ($time['measures'] as $measure) {
$output['timelineData'][] = [
'data' => [],
'description' => $measure['label'],
'duration' => $measure['duration'] * 1000,
'end' => $measure['end'],
'start' => $measure['start'],
'relative_start' => $measure['start'] - $time['start'],
];
}
}
if (isset($data['route'])) {
$route = $data['route'];
$controller = null;
if (isset($route['controller'])) {
$controller = $route['controller'];
} elseif (isset($route['uses'])) {
$controller = $route['uses'];
}
$output['controller'] = $controller;
list($method, $uri) = explode(' ', $route['uri'], 2);
$output['routes'][] = [
'action' => $controller,
'after' => isset($route['after']) ? $route['after'] : null,
'before' => isset($route['before']) ? $route['before'] : null,
'method' => $method,
'name' => isset($route['as']) ? $route['as'] : null,
'uri' => $uri,
];
}
if (isset($data['messages'])) {
foreach ($data['messages']['messages'] as $message) {
$output['log'][] = [
'message' => $message['message'],
'time' => $message['time'],
'level' => $message['label'],
];
}
}
if (isset($data['queries'])) {
$queries = $data['queries'];
foreach ($queries['statements'] as $statement) {
if ($statement['type'] === 'explain') {
continue;
}
$output['databaseQueries'][] = [
'query' => $statement['sql'],
'bindings' => $statement['params'],
'duration' => $statement['duration'] * 1000,
'connection' => $statement['connection']
];
}
$output['databaseDuration'] = $queries['accumulated_duration'] * 1000;
}
if (isset($data['views'])) {
foreach ($data['views']['templates'] as $view) {
$output['viewsData'][] = [
'description' => 'Rendering a view',
'duration' => 0,
'end' => 0,
'start' => 0,
'data' => [
'name' => $view['name'],
'data' => $view['params'],
],
];
}
}
if (isset($data['swiftmailer_mails'])) {
foreach ($data['swiftmailer_mails']['mails'] as $mail) {
$output['emailsData'][] = [
'data' => [
'to' => $mail['to'],
'subject' => $mail['subject'],
'headers' => isset($mail['headers']) ? explode("\n", $mail['headers']) : null,
],
];
}
}
return $output;
}
}

View File

@@ -0,0 +1,79 @@
<?php
namespace Barryvdh\Debugbar;
use DebugBar\HttpDriverInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\Session;
/**
* HTTP driver for Symfony Request/Session
*/
class SymfonyHttpDriver implements HttpDriverInterface
{
/** @var \Illuminate\Contracts\Session\Session|\Illuminate\Session\SessionManager */
protected $session;
/** @var \Symfony\Component\HttpFoundation\Response */
protected $response;
public function __construct($session, $response = null)
{
$this->session = $session;
$this->response = $response;
}
/**
* {@inheritDoc}
*/
public function setHeaders(array $headers)
{
if (!is_null($this->response)) {
$this->response->headers->add($headers);
}
}
/**
* {@inheritDoc}
*/
public function isSessionStarted()
{
if (!$this->session->isStarted()) {
$this->session->start();
}
return $this->session->isStarted();
}
/**
* {@inheritDoc}
*/
public function setSessionValue($name, $value)
{
$this->session->put($name, $value);
}
/**
* {@inheritDoc}
*/
public function hasSessionValue($name)
{
return $this->session->has($name);
}
/**
* {@inheritDoc}
*/
public function getSessionValue($name)
{
return $this->session->get($name);
}
/**
* {@inheritDoc}
*/
public function deleteSessionValue($name)
{
$this->session->remove($name);
}
}

View File

@@ -0,0 +1,92 @@
<?php
namespace Barryvdh\Debugbar\Twig\Extension;
use Illuminate\Foundation\Application;
use Twig_Environment;
use Twig_Extension;
use Twig_SimpleFunction;
/**
* Access Laravels auth class in your Twig templates.
*/
class Debug extends Twig_Extension
{
/**
* @var \Barryvdh\Debugbar\LaravelDebugbar
*/
protected $debugbar;
/**
* Create a new auth extension.
*
* @param \Illuminate\Foundation\Application $app
*/
public function __construct(Application $app)
{
if ($app->bound('debugbar')) {
$this->debugbar = $app['debugbar'];
} else {
$this->debugbar = null;
}
}
/**
* {@inheritDoc}
*/
public function getName()
{
return 'Laravel_Debugbar_Debug';
}
/**
* {@inheritDoc}
*/
public function getFunctions()
{
return [
new Twig_SimpleFunction(
'debug',
[$this, 'debug'],
['needs_context' => true, 'needs_environment' => true]
),
];
}
/**
* Based on Twig_Extension_Debug / twig_var_dump
* (c) 2011 Fabien Potencier
*
* @param Twig_Environment $env
* @param $context
*/
public function debug(Twig_Environment $env, $context)
{
if (!$env->isDebug() || !$this->debugbar) {
return;
}
$count = func_num_args();
if (2 === $count) {
$data = [];
foreach ($context as $key => $value) {
if (is_object($value)) {
if (method_exists($value, 'toArray')) {
$data[$key] = $value->toArray();
} else {
$data[$key] = "Object (" . get_class($value) . ")";
}
} else {
$data[$key] = $value;
}
}
$this->debugbar->addMessage($data);
} else {
for ($i = 2; $i < $count; $i++) {
$this->debugbar->addMessage(func_get_arg($i));
}
}
return;
}
}

View File

@@ -0,0 +1,88 @@
<?php
namespace Barryvdh\Debugbar\Twig\Extension;
use DebugBar\DataFormatter\DataFormatterInterface;
use Twig_Environment;
use Twig_Extension;
use Twig_SimpleFunction;
/**
* Dump variables using the DataFormatter
*/
class Dump extends Twig_Extension
{
/**
* @var \DebugBar\DataFormatter\DataFormatter
*/
protected $formatter;
/**
* Create a new auth extension.
*
* @param \DebugBar\DataFormatter\DataFormatterInterface $formatter
*/
public function __construct(DataFormatterInterface $formatter)
{
$this->formatter = $formatter;
}
/**
* {@inheritDoc}
*/
public function getName()
{
return 'Laravel_Debugbar_Dump';
}
/**
* {@inheritDoc}
*/
public function getFunctions()
{
return [
new Twig_SimpleFunction(
'dump',
[$this, 'dump'],
['is_safe' => ['html'], 'needs_context' => true, 'needs_environment' => true]
),
];
}
/**
* Based on Twig_Extension_Debug / twig_var_dump
* (c) 2011 Fabien Potencier
*
* @param Twig_Environment $env
* @param $context
*
* @return string
*/
public function dump(Twig_Environment $env, $context)
{
$output = '';
$count = func_num_args();
if (2 === $count) {
$data = [];
foreach ($context as $key => $value) {
if (is_object($value)) {
if (method_exists($value, 'toArray')) {
$data[$key] = $value->toArray();
} else {
$data[$key] = "Object (" . get_class($value) . ")";
}
} else {
$data[$key] = $value;
}
}
$output .= $this->formatter->formatVar($data);
} else {
for ($i = 2; $i < $count; $i++) {
$output .= $this->formatter->formatVar(func_get_arg($i));
}
}
return '<pre>' . $output . '</pre>';
}
}

View File

@@ -0,0 +1,58 @@
<?php
namespace Barryvdh\Debugbar\Twig\Extension;
use Barryvdh\Debugbar\Twig\TokenParser\StopwatchTokenParser;
use Illuminate\Foundation\Application;
use Twig_Extension;
/**
* Access Laravels auth class in your Twig templates.
* Based on Symfony\Bridge\Twig\Extension\StopwatchExtension
*/
class Stopwatch extends Twig_Extension
{
/**
* @var \Barryvdh\Debugbar\LaravelDebugbar
*/
protected $debugbar;
/**
* Create a new auth extension.
*
* @param \Illuminate\Foundation\Application $app
*/
public function __construct(Application $app)
{
if ($app->bound('debugbar')) {
$this->debugbar = $app['debugbar'];
} else {
$this->debugbar = null;
}
}
/**
* {@inheritDoc}
*/
public function getName()
{
return 'stopwatch';
}
public function getTokenParsers()
{
return [
/*
* {% stopwatch foo %}
* Some stuff which will be recorded on the timeline
* {% endstopwatch %}
*/
new StopwatchTokenParser($this->debugbar !== null),
];
}
public function getDebugbar()
{
return $this->debugbar;
}
}

View File

@@ -0,0 +1,39 @@
<?php
namespace Barryvdh\Debugbar\Twig\Node;
/**
* Represents a stopwatch node. Based on Symfony\Bridge\Twig\Node\StopwatchNode
*
* @author Wouter J <wouter@wouterj.nl>
*/
class StopwatchNode extends \Twig_Node
{
public function __construct(
\Twig_NodeInterface $name,
$body,
\Twig_Node_Expression_AssignName $var,
$lineno = 0,
$tag = null
) {
parent::__construct(['body' => $body, 'name' => $name, 'var' => $var], [], $lineno, $tag);
}
public function compile(\Twig_Compiler $compiler)
{
$compiler
->addDebugInfo($this)
->write('')
->subcompile($this->getNode('var'))
->raw(' = ')
->subcompile($this->getNode('name'))
->write(";\n")
->write("\$this->env->getExtension('stopwatch')->getDebugbar()->startMeasure(")
->subcompile($this->getNode('var'))
->raw(");\n")
->subcompile($this->getNode('body'))
->write("\$this->env->getExtension('stopwatch')->getDebugbar()->stopMeasure(")
->subcompile($this->getNode('var'))
->raw(");\n");
}
}

View File

@@ -0,0 +1,57 @@
<?php
namespace Barryvdh\Debugbar\Twig\TokenParser;
use Barryvdh\Debugbar\Twig\Node\StopwatchNode;
/**
* Token Parser for the stopwatch tag. Based on Symfony\Bridge\Twig\TokenParser\StopwatchTokenParser;
*
* @author Wouter J <wouter@wouterj.nl>
*/
class StopwatchTokenParser extends \Twig_TokenParser
{
protected $debugbarAvailable;
public function __construct($debugbarAvailable)
{
$this->debugbarAvailable = $debugbarAvailable;
}
public function parse(\Twig_Token $token)
{
$lineno = $token->getLine();
$stream = $this->parser->getStream();
// {% stopwatch 'bar' %}
$name = $this->parser->getExpressionParser()->parseExpression();
$stream->expect(\Twig_Token::BLOCK_END_TYPE);
// {% endstopwatch %}
$body = $this->parser->subparse([$this, 'decideStopwatchEnd'], true);
$stream->expect(\Twig_Token::BLOCK_END_TYPE);
if ($this->debugbarAvailable) {
return new StopwatchNode(
$name,
$body,
new \Twig_Node_Expression_AssignName($this->parser->getVarName(), $token->getLine()),
$lineno,
$this->getTag()
);
}
return $body;
}
public function getTag()
{
return 'stopwatch';
}
public function decideStopwatchEnd(\Twig_Token $token)
{
return $token->test('endstopwatch');
}
}

View File

@@ -0,0 +1,42 @@
<?php
$routeConfig = [
'namespace' => 'Barryvdh\Debugbar\Controllers',
'prefix' => app('config')->get('debugbar.route_prefix'),
'domain' => app('config')->get('debugbar.route_domain'),
'middleware' => [\Barryvdh\Debugbar\Middleware\DebugbarEnabled::class],
];
app('router')->group($routeConfig, function ($router) {
$router->get('open', [
'uses' => 'OpenHandlerController@handle',
'as' => 'debugbar.openhandler',
]);
$router->get('clockwork/{id}', [
'uses' => 'OpenHandlerController@clockwork',
'as' => 'debugbar.clockwork',
]);
if (class_exists(\Laravel\Telescope\Telescope::class)) {
$router->get('telescope/{id}', [
'uses' => 'TelescopeController@show',
'as' => 'debugbar.telescope',
]);
}
$router->get('assets/stylesheets', [
'uses' => 'AssetController@css',
'as' => 'debugbar.assets.css',
]);
$router->get('assets/javascript', [
'uses' => 'AssetController@js',
'as' => 'debugbar.assets.js',
]);
$router->delete('cache/{key}/{tags?}', [
'uses' => 'CacheController@delete',
'as' => 'debugbar.cache.delete',
]);
});

View File

@@ -0,0 +1,82 @@
<?php
if (!function_exists('debugbar')) {
/**
* Get the Debugbar instance
*
* @return \Barryvdh\Debugbar\LaravelDebugbar
*/
function debugbar()
{
return app(\Barryvdh\Debugbar\LaravelDebugbar::class);
}
}
if (!function_exists('debug')) {
/**
* Adds one or more messages to the MessagesCollector
*
* @param mixed ...$value
* @return string
*/
function debug($value)
{
$debugbar = debugbar();
foreach (func_get_args() as $value) {
$debugbar->addMessage($value, 'debug');
}
}
}
if (!function_exists('start_measure')) {
/**
* Starts a measure
*
* @param string $name Internal name, used to stop the measure
* @param string $label Public name
*/
function start_measure($name, $label = null)
{
debugbar()->startMeasure($name, $label);
}
}
if (!function_exists('stop_measure')) {
/**
* Stop a measure
*
* @param string $name Internal name, used to stop the measure
*/
function stop_measure($name)
{
debugbar()->stopMeasure($name);
}
}
if (!function_exists('add_measure')) {
/**
* Adds a measure
*
* @param string $label
* @param float $start
* @param float $end
*/
function add_measure($label, $start, $end)
{
debugbar()->addMeasure($label, $start, $end);
}
}
if (!function_exists('measure')) {
/**
* Utility function to measure the execution of a Closure
*
* @param string $label
* @param \Closure $closure
* @return mixed
*/
function measure($label, \Closure $closure)
{
return debugbar()->measure($label, $closure);
}
}

View File

@@ -49,6 +49,7 @@ return array(
'AddForeignKeysToTicketsTable' => $baseDir . '/database/migrations/2016_02_16_140454_add_foreign_keys_to_tickets_table.php', 'AddForeignKeysToTicketsTable' => $baseDir . '/database/migrations/2016_02_16_140454_add_foreign_keys_to_tickets_table.php',
'AddForeignKeysToUserAssignOrganizationTable' => $baseDir . '/database/migrations/2016_02_16_140454_add_foreign_keys_to_user_assign_organization_table.php', 'AddForeignKeysToUserAssignOrganizationTable' => $baseDir . '/database/migrations/2016_02_16_140454_add_foreign_keys_to_user_assign_organization_table.php',
'AddForeignKeysToUsersTable' => $baseDir . '/database/migrations/2016_02_16_140454_add_foreign_keys_to_users_table.php', 'AddForeignKeysToUsersTable' => $baseDir . '/database/migrations/2016_02_16_140454_add_foreign_keys_to_users_table.php',
'AddUuidToFailedJobsTable' => $baseDir . '/database/migrations/2023_01_07_000000_add_uuid_to_failed_jobs_table.php',
'Adobe_Font_Metrics' => $vendorDir . '/phenx/php-font-lib/classes/Adobe_Font_Metrics.php', 'Adobe_Font_Metrics' => $vendorDir . '/phenx/php-font-lib/classes/Adobe_Font_Metrics.php',
'AlterEmailsTableMakeUsernameColumnNullable' => $baseDir . '/database/migrations/2018_08_13_075015_alter_emails_table_make_username_column_nullable.php', 'AlterEmailsTableMakeUsernameColumnNullable' => $baseDir . '/database/migrations/2018_08_13_075015_alter_emails_table_make_username_column_nullable.php',
'AlterTicketSourceTable' => $baseDir . '/database/migrations/2016_08_16_104539_alter_ticket_source_table.php', 'AlterTicketSourceTable' => $baseDir . '/database/migrations/2016_08_16_104539_alter_ticket_source_table.php',
@@ -158,7 +159,10 @@ return array(
'DOMPDF' => $vendorDir . '/dompdf/dompdf/include/dompdf.cls.php', 'DOMPDF' => $vendorDir . '/dompdf/dompdf/include/dompdf.cls.php',
'DOMPDF_Exception' => $vendorDir . '/dompdf/dompdf/include/dompdf_exception.cls.php', 'DOMPDF_Exception' => $vendorDir . '/dompdf/dompdf/include/dompdf_exception.cls.php',
'DOMPDF_Image_Exception' => $vendorDir . '/dompdf/dompdf/include/dompdf_image_exception.cls.php', 'DOMPDF_Image_Exception' => $vendorDir . '/dompdf/dompdf/include/dompdf_image_exception.cls.php',
'DatabaseSeeder' => $baseDir . '/database/seeds/DatabaseSeeder.php', 'Database\\Seeders\\DatabaseSeeder' => $baseDir . '/database/seeders/DatabaseSeeder.php',
'Database\\Seeders\\OutboundMailSeeder' => $baseDir . '/database/seeders/OutboundMailSeeder.php',
'Database\\Seeders\\TicketSourceSeeder' => $baseDir . '/database/seeders/TicketSourceSeeder.php',
'Database\\Seeders\\UserSeeder' => $baseDir . '/database/seeders/UserSeeder.php',
'Encoding_Map' => $vendorDir . '/phenx/php-font-lib/classes/Encoding_Map.php', 'Encoding_Map' => $vendorDir . '/phenx/php-font-lib/classes/Encoding_Map.php',
'Fixed_Positioner' => $vendorDir . '/dompdf/dompdf/include/fixed_positioner.cls.php', 'Fixed_Positioner' => $vendorDir . '/dompdf/dompdf/include/fixed_positioner.cls.php',
'Font' => $vendorDir . '/phenx/php-font-lib/classes/Font.php', 'Font' => $vendorDir . '/phenx/php-font-lib/classes/Font.php',
@@ -292,7 +296,6 @@ return array(
'Null_Frame_Decorator' => $vendorDir . '/dompdf/dompdf/include/null_frame_decorator.cls.php', 'Null_Frame_Decorator' => $vendorDir . '/dompdf/dompdf/include/null_frame_decorator.cls.php',
'Null_Frame_Reflower' => $vendorDir . '/dompdf/dompdf/include/null_frame_reflower.cls.php', 'Null_Frame_Reflower' => $vendorDir . '/dompdf/dompdf/include/null_frame_reflower.cls.php',
'Null_Positioner' => $vendorDir . '/dompdf/dompdf/include/null_positioner.cls.php', 'Null_Positioner' => $vendorDir . '/dompdf/dompdf/include/null_positioner.cls.php',
'OutboundMailSeeder' => $baseDir . '/database/seeds/OutboundMailSeeder.php',
'PDFLib_Adapter' => $vendorDir . '/dompdf/dompdf/include/pdflib_adapter.cls.php', 'PDFLib_Adapter' => $vendorDir . '/dompdf/dompdf/include/pdflib_adapter.cls.php',
'PHPUnit\\Exception' => $vendorDir . '/phpunit/phpunit/src/Exception.php', 'PHPUnit\\Exception' => $vendorDir . '/phpunit/phpunit/src/Exception.php',
'PHPUnit\\Framework\\ActualValueIsNotAnObjectException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/ActualValueIsNotAnObjectException.php', 'PHPUnit\\Framework\\ActualValueIsNotAnObjectException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/ActualValueIsNotAnObjectException.php',
@@ -949,9 +952,7 @@ return array(
'TheSeer\\Tokenizer\\TokenCollectionException' => $vendorDir . '/theseer/tokenizer/src/TokenCollectionException.php', 'TheSeer\\Tokenizer\\TokenCollectionException' => $vendorDir . '/theseer/tokenizer/src/TokenCollectionException.php',
'TheSeer\\Tokenizer\\Tokenizer' => $vendorDir . '/theseer/tokenizer/src/Tokenizer.php', 'TheSeer\\Tokenizer\\Tokenizer' => $vendorDir . '/theseer/tokenizer/src/Tokenizer.php',
'TheSeer\\Tokenizer\\XMLSerializer' => $vendorDir . '/theseer/tokenizer/src/XMLSerializer.php', 'TheSeer\\Tokenizer\\XMLSerializer' => $vendorDir . '/theseer/tokenizer/src/XMLSerializer.php',
'TicketSourceSeeder' => $baseDir . '/database/seeds/TicketSourceSeeder.php',
'UnhandledMatchError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php', 'UnhandledMatchError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php',
'UserSeeder' => $baseDir . '/database/seeds/UserSeeder.php',
'ValueError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/ValueError.php', 'ValueError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/ValueError.php',
'Version1079table' => $baseDir . '/database/migrations/2016_06_28_141613_version1079table.php', 'Version1079table' => $baseDir . '/database/migrations/2016_06_28_141613_version1079table.php',
); );

View File

@@ -12,11 +12,11 @@ return array(
'320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php', '320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php',
'e69f7f6ee287b969198c3c9d6777bd38' => $vendorDir . '/symfony/polyfill-intl-normalizer/bootstrap.php', 'e69f7f6ee287b969198c3c9d6777bd38' => $vendorDir . '/symfony/polyfill-intl-normalizer/bootstrap.php',
'7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php', '7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php',
'0d59ee240a4cd96ddbb4ff164fccea4d' => $vendorDir . '/symfony/polyfill-php73/bootstrap.php',
'667aeda72477189d0494fecd327c3641' => $vendorDir . '/symfony/var-dumper/Resources/functions/dump.php', '667aeda72477189d0494fecd327c3641' => $vendorDir . '/symfony/var-dumper/Resources/functions/dump.php',
'25072dd6e2470089de65ae7bf11d3109' => $vendorDir . '/symfony/polyfill-php72/bootstrap.php', '0d59ee240a4cd96ddbb4ff164fccea4d' => $vendorDir . '/symfony/polyfill-php73/bootstrap.php',
'c964ee0ededf28c96ebd9db5099ef910' => $vendorDir . '/guzzlehttp/promises/src/functions_include.php', 'c964ee0ededf28c96ebd9db5099ef910' => $vendorDir . '/guzzlehttp/promises/src/functions_include.php',
'8825ede83f2f289127722d4e842cf7e8' => $vendorDir . '/symfony/polyfill-intl-grapheme/bootstrap.php', '8825ede83f2f289127722d4e842cf7e8' => $vendorDir . '/symfony/polyfill-intl-grapheme/bootstrap.php',
'25072dd6e2470089de65ae7bf11d3109' => $vendorDir . '/symfony/polyfill-php72/bootstrap.php',
'f598d06aa772fa33d905e87be6398fb1' => $vendorDir . '/symfony/polyfill-intl-idn/bootstrap.php', 'f598d06aa772fa33d905e87be6398fb1' => $vendorDir . '/symfony/polyfill-intl-idn/bootstrap.php',
'b6b991a57620e2fb6b2f66f03fe9ddc2' => $vendorDir . '/symfony/string/Resources/functions.php', 'b6b991a57620e2fb6b2f66f03fe9ddc2' => $vendorDir . '/symfony/string/Resources/functions.php',
'37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php', '37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php',
@@ -91,7 +91,10 @@ return array(
'e39a8b23c42d4e1452234d762b03835a' => $vendorDir . '/ramsey/uuid/src/functions.php', 'e39a8b23c42d4e1452234d762b03835a' => $vendorDir . '/ramsey/uuid/src/functions.php',
'2c102faa651ef8ea5874edb585946bce' => $vendorDir . '/swiftmailer/swiftmailer/lib/swift_required.php', '2c102faa651ef8ea5874edb585946bce' => $vendorDir . '/swiftmailer/swiftmailer/lib/swift_required.php',
'8a9dc1de0ca7e01f3e08231539562f61' => $vendorDir . '/aws/aws-sdk-php/src/functions.php', '8a9dc1de0ca7e01f3e08231539562f61' => $vendorDir . '/aws/aws-sdk-php/src/functions.php',
'4a1f389d6ce373bda9e57857d3b61c84' => $vendorDir . '/barryvdh/laravel-debugbar/src/helpers.php',
'ed962a97bd972bc82007176b647d4e36' => $vendorDir . '/facade/ignition/src/helpers.php', 'ed962a97bd972bc82007176b647d4e36' => $vendorDir . '/facade/ignition/src/helpers.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', 'f0906e6318348a765ffb6eb24e0d0938' => $vendorDir . '/laravel/framework/src/Illuminate/Foundation/helpers.php',
'58571171fd5812e6e447dce228f52f4d' => $vendorDir . '/laravel/framework/src/Illuminate/Support/helpers.php', '58571171fd5812e6e447dce228f52f4d' => $vendorDir . '/laravel/framework/src/Illuminate/Support/helpers.php',
'f18cc91337d49233e5754e93f3ed9ec3' => $vendorDir . '/laravelcollective/html/src/helpers.php', 'f18cc91337d49233e5754e93f3ed9ec3' => $vendorDir . '/laravelcollective/html/src/helpers.php',

View File

@@ -8,11 +8,8 @@ $baseDir = dirname($vendorDir);
return array( return array(
'thomaswelton\\GravatarLib\\' => array($vendorDir . '/thomaswelton/gravatarlib'), 'thomaswelton\\GravatarLib\\' => array($vendorDir . '/thomaswelton/gravatarlib'),
'PhpSpec' => array($vendorDir . '/phpspec/phpspec/src'), 'PhpSpec' => array($vendorDir . '/phpspec/phpspec/src'),
'Mremi\\UrlShortener' => array($vendorDir . '/mremi/url-shortener/src'),
'Mockery' => array($vendorDir . '/mockery/mockery/library'), 'Mockery' => array($vendorDir . '/mockery/mockery/library'),
'HTMLPurifier' => array($vendorDir . '/ezyang/htmlpurifier/library'), 'HTMLPurifier' => array($vendorDir . '/ezyang/htmlpurifier/library'),
'Guzzle\\Tests' => array($vendorDir . '/guzzle/guzzle/tests'),
'Guzzle' => array($vendorDir . '/guzzle/guzzle/src'),
'ForceUTF8\\' => array($vendorDir . '/neitanod/forceutf8/src'), 'ForceUTF8\\' => array($vendorDir . '/neitanod/forceutf8/src'),
'Flow' => array($vendorDir . '/flowjs/flow-php-server/src'), 'Flow' => array($vendorDir . '/flowjs/flow-php-server/src'),
'Fetch' => array($vendorDir . '/tedivm/fetch/src'), 'Fetch' => array($vendorDir . '/tedivm/fetch/src'),

View File

@@ -7,7 +7,7 @@ $baseDir = dirname($vendorDir);
return array( return array(
'voku\\' => array($vendorDir . '/voku/portable-ascii/src/voku'), 'voku\\' => array($vendorDir . '/voku/portable-ascii/src/voku'),
'phpDocumentor\\Reflection\\' => array($vendorDir . '/phpdocumentor/reflection-common/src', $vendorDir . '/phpdocumentor/reflection-docblock/src', $vendorDir . '/phpdocumentor/type-resolver/src'), 'phpDocumentor\\Reflection\\' => array($vendorDir . '/phpdocumentor/reflection-common/src', $vendorDir . '/phpdocumentor/type-resolver/src', $vendorDir . '/phpdocumentor/reflection-docblock/src'),
'libphonenumber\\' => array($vendorDir . '/giggsey/libphonenumber-for-php/src'), 'libphonenumber\\' => array($vendorDir . '/giggsey/libphonenumber-for-php/src'),
'ZipStream\\' => array($vendorDir . '/maennchen/zipstream-php/src'), 'ZipStream\\' => array($vendorDir . '/maennchen/zipstream-php/src'),
'Yajra\\DataTables\\' => array($vendorDir . '/yajra/laravel-datatables-oracle/src'), 'Yajra\\DataTables\\' => array($vendorDir . '/yajra/laravel-datatables-oracle/src'),
@@ -54,7 +54,7 @@ return array(
'Psy\\' => array($vendorDir . '/psy/psysh/src'), 'Psy\\' => array($vendorDir . '/psy/psysh/src'),
'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-factory/src', $vendorDir . '/psr/http-message/src'), 'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-message/src', $vendorDir . '/psr/http-factory/src'),
'Psr\\Http\\Client\\' => array($vendorDir . '/psr/http-client/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'),
@@ -69,6 +69,7 @@ return array(
'Nicolaslopezj\\Searchable\\' => array($vendorDir . '/nicolaslopezj/searchable/src'), 'Nicolaslopezj\\Searchable\\' => array($vendorDir . '/nicolaslopezj/searchable/src'),
'Namshi\\JOSE\\' => array($vendorDir . '/namshi/jose/src/Namshi/JOSE'), 'Namshi\\JOSE\\' => array($vendorDir . '/namshi/jose/src/Namshi/JOSE'),
'MyCLabs\\Enum\\' => array($vendorDir . '/myclabs/php-enum/src'), 'MyCLabs\\Enum\\' => array($vendorDir . '/myclabs/php-enum/src'),
'Mremi\\UrlShortener\\' => array($vendorDir . '/mremi/url-shortener/src/Mremi/UrlShortener'),
'Monolog\\' => array($vendorDir . '/monolog/monolog/src/Monolog'), 'Monolog\\' => array($vendorDir . '/monolog/monolog/src/Monolog'),
'Matrix\\' => array($vendorDir . '/markbaker/matrix/classes/src'), 'Matrix\\' => array($vendorDir . '/markbaker/matrix/classes/src'),
'Maatwebsite\\Excel\\' => array($vendorDir . '/maatwebsite/excel/src'), 'Maatwebsite\\Excel\\' => array($vendorDir . '/maatwebsite/excel/src'),
@@ -81,18 +82,20 @@ return array(
'Laravel\\Ui\\' => array($vendorDir . '/laravel/ui/src'), 'Laravel\\Ui\\' => array($vendorDir . '/laravel/ui/src'),
'Laravel\\Tinker\\' => array($vendorDir . '/laravel/tinker/src'), 'Laravel\\Tinker\\' => array($vendorDir . '/laravel/tinker/src'),
'Laravel\\Socialite\\' => array($vendorDir . '/laravel/socialite/src'), 'Laravel\\Socialite\\' => array($vendorDir . '/laravel/socialite/src'),
'Laravel\\SerializableClosure\\' => array($vendorDir . '/laravel/serializable-closure/src'),
'Laravel\\Dusk\\' => array($vendorDir . '/laravel/dusk/src'), 'Laravel\\Dusk\\' => array($vendorDir . '/laravel/dusk/src'),
'JmesPath\\' => array($vendorDir . '/mtdowling/jmespath.php/src'), 'JmesPath\\' => array($vendorDir . '/mtdowling/jmespath.php/src'),
'Intervention\\Image\\' => array($vendorDir . '/intervention/image/src/Intervention/Image'), 'Intervention\\Image\\' => array($vendorDir . '/intervention/image/src/Intervention/Image'),
'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'),
'Gitonomy\\Git\\' => array($vendorDir . '/gitonomy/gitlib/src/Gitonomy/Git'), 'Gitonomy\\Git\\' => array($vendorDir . '/gitonomy/gitlib/src/Gitonomy/Git'),
'Giggsey\\Locale\\' => array($vendorDir . '/giggsey/locale/src'), 'Giggsey\\Locale\\' => array($vendorDir . '/giggsey/locale/src'),
'Fruitcake\\Cors\\' => array($vendorDir . '/fruitcake/laravel-cors/src'), 'Fruitcake\\Cors\\' => array($vendorDir . '/fruitcake/laravel-cors/src'),
'Fideloper\\Proxy\\' => array($vendorDir . '/fideloper/proxy/src'),
'Faker\\' => array($vendorDir . '/fakerphp/faker/src/Faker'), 'Faker\\' => array($vendorDir . '/fakerphp/faker/src/Faker'),
'Facebook\\WebDriver\\' => array($vendorDir . '/php-webdriver/webdriver/lib'), 'Facebook\\WebDriver\\' => array($vendorDir . '/php-webdriver/webdriver/lib'),
'Facade\\Ignition\\' => array($vendorDir . '/facade/ignition/src'), 'Facade\\Ignition\\' => array($vendorDir . '/facade/ignition/src'),
@@ -108,7 +111,10 @@ return array(
'Doctrine\\Common\\Cache\\' => array($vendorDir . '/doctrine/cache/lib/Doctrine/Common/Cache'), 'Doctrine\\Common\\Cache\\' => array($vendorDir . '/doctrine/cache/lib/Doctrine/Common/Cache'),
'Doctrine\\Common\\' => array($vendorDir . '/doctrine/event-manager/src'), 'Doctrine\\Common\\' => array($vendorDir . '/doctrine/event-manager/src'),
'DeepCopy\\' => array($vendorDir . '/myclabs/deep-copy/src/DeepCopy'), 'DeepCopy\\' => array($vendorDir . '/myclabs/deep-copy/src/DeepCopy'),
'DebugBar\\' => array($vendorDir . '/maximebf/debugbar/src/DebugBar'),
'DaveJamesMiller\\Breadcrumbs\\' => array($vendorDir . '/davejamesmiller/laravel-breadcrumbs/src'), 'DaveJamesMiller\\Breadcrumbs\\' => array($vendorDir . '/davejamesmiller/laravel-breadcrumbs/src'),
'Database\\Seeders\\' => array($baseDir . '/database/seeders'),
'Database\\Factories\\' => array($baseDir . '/database/factories'),
'Cron\\' => array($vendorDir . '/dragonmantank/cron-expression/src/Cron'), 'Cron\\' => array($vendorDir . '/dragonmantank/cron-expression/src/Cron'),
'Composer\\CaBundle\\' => array($vendorDir . '/composer/ca-bundle/src'), 'Composer\\CaBundle\\' => array($vendorDir . '/composer/ca-bundle/src'),
'Complex\\' => array($vendorDir . '/markbaker/complex/classes/src'), 'Complex\\' => array($vendorDir . '/markbaker/complex/classes/src'),
@@ -118,6 +124,7 @@ return array(
'Bugsnag\\BugsnagLaravel\\' => array($vendorDir . '/bugsnag/bugsnag-laravel/src'), 'Bugsnag\\BugsnagLaravel\\' => array($vendorDir . '/bugsnag/bugsnag-laravel/src'),
'Bugsnag\\' => array($vendorDir . '/bugsnag/bugsnag/src'), 'Bugsnag\\' => array($vendorDir . '/bugsnag/bugsnag/src'),
'Brick\\Math\\' => array($vendorDir . '/brick/math/src'), 'Brick\\Math\\' => array($vendorDir . '/brick/math/src'),
'Barryvdh\\Debugbar\\' => array($vendorDir . '/barryvdh/laravel-debugbar/src'),
'Aws\\' => array($vendorDir . '/aws/aws-sdk-php/src'), 'Aws\\' => array($vendorDir . '/aws/aws-sdk-php/src'),
'Asm89\\Stack\\' => array($vendorDir . '/asm89/stack-cors/src'), 'Asm89\\Stack\\' => array($vendorDir . '/asm89/stack-cors/src'),
'App\\' => array($baseDir . '/app'), 'App\\' => array($baseDir . '/app'),

View File

@@ -2,7 +2,7 @@
// autoload_real.php @generated by Composer // autoload_real.php @generated by Composer
class ComposerAutoloaderInit9da6744efcb5435630815fb416a6752c class ComposerAutoloaderInite3a664ccc4def6142d1c80482606ee61
{ {
private static $loader; private static $loader;
@@ -24,18 +24,18 @@ class ComposerAutoloaderInit9da6744efcb5435630815fb416a6752c
require __DIR__ . '/platform_check.php'; require __DIR__ . '/platform_check.php';
spl_autoload_register(array('ComposerAutoloaderInit9da6744efcb5435630815fb416a6752c', 'loadClassLoader'), true, true); spl_autoload_register(array('ComposerAutoloaderInite3a664ccc4def6142d1c80482606ee61', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__)); self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
spl_autoload_unregister(array('ComposerAutoloaderInit9da6744efcb5435630815fb416a6752c', 'loadClassLoader')); spl_autoload_unregister(array('ComposerAutoloaderInite3a664ccc4def6142d1c80482606ee61', 'loadClassLoader'));
require __DIR__ . '/autoload_static.php'; require __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInit9da6744efcb5435630815fb416a6752c::getInitializer($loader)); call_user_func(\Composer\Autoload\ComposerStaticInite3a664ccc4def6142d1c80482606ee61::getInitializer($loader));
$loader->register(true); $loader->register(true);
$includeFiles = \Composer\Autoload\ComposerStaticInit9da6744efcb5435630815fb416a6752c::$files; $includeFiles = \Composer\Autoload\ComposerStaticInite3a664ccc4def6142d1c80482606ee61::$files;
foreach ($includeFiles as $fileIdentifier => $file) { foreach ($includeFiles as $fileIdentifier => $file) {
composerRequire9da6744efcb5435630815fb416a6752c($fileIdentifier, $file); composerRequiree3a664ccc4def6142d1c80482606ee61($fileIdentifier, $file);
} }
return $loader; return $loader;
@@ -47,7 +47,7 @@ class ComposerAutoloaderInit9da6744efcb5435630815fb416a6752c
* @param string $file * @param string $file
* @return void * @return void
*/ */
function composerRequire9da6744efcb5435630815fb416a6752c($fileIdentifier, $file) function composerRequiree3a664ccc4def6142d1c80482606ee61($fileIdentifier, $file)
{ {
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;

View File

@@ -4,7 +4,7 @@
namespace Composer\Autoload; namespace Composer\Autoload;
class ComposerStaticInit9da6744efcb5435630815fb416a6752c class ComposerStaticInite3a664ccc4def6142d1c80482606ee61
{ {
public static $files = array ( public static $files = array (
'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php', 'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php',
@@ -13,11 +13,11 @@ class ComposerStaticInit9da6744efcb5435630815fb416a6752c
'320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php', '320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php',
'e69f7f6ee287b969198c3c9d6777bd38' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/bootstrap.php', 'e69f7f6ee287b969198c3c9d6777bd38' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/bootstrap.php',
'7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php', '7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php',
'0d59ee240a4cd96ddbb4ff164fccea4d' => __DIR__ . '/..' . '/symfony/polyfill-php73/bootstrap.php',
'667aeda72477189d0494fecd327c3641' => __DIR__ . '/..' . '/symfony/var-dumper/Resources/functions/dump.php', '667aeda72477189d0494fecd327c3641' => __DIR__ . '/..' . '/symfony/var-dumper/Resources/functions/dump.php',
'25072dd6e2470089de65ae7bf11d3109' => __DIR__ . '/..' . '/symfony/polyfill-php72/bootstrap.php', '0d59ee240a4cd96ddbb4ff164fccea4d' => __DIR__ . '/..' . '/symfony/polyfill-php73/bootstrap.php',
'c964ee0ededf28c96ebd9db5099ef910' => __DIR__ . '/..' . '/guzzlehttp/promises/src/functions_include.php', 'c964ee0ededf28c96ebd9db5099ef910' => __DIR__ . '/..' . '/guzzlehttp/promises/src/functions_include.php',
'8825ede83f2f289127722d4e842cf7e8' => __DIR__ . '/..' . '/symfony/polyfill-intl-grapheme/bootstrap.php', '8825ede83f2f289127722d4e842cf7e8' => __DIR__ . '/..' . '/symfony/polyfill-intl-grapheme/bootstrap.php',
'25072dd6e2470089de65ae7bf11d3109' => __DIR__ . '/..' . '/symfony/polyfill-php72/bootstrap.php',
'f598d06aa772fa33d905e87be6398fb1' => __DIR__ . '/..' . '/symfony/polyfill-intl-idn/bootstrap.php', 'f598d06aa772fa33d905e87be6398fb1' => __DIR__ . '/..' . '/symfony/polyfill-intl-idn/bootstrap.php',
'b6b991a57620e2fb6b2f66f03fe9ddc2' => __DIR__ . '/..' . '/symfony/string/Resources/functions.php', 'b6b991a57620e2fb6b2f66f03fe9ddc2' => __DIR__ . '/..' . '/symfony/string/Resources/functions.php',
'37a3dc5111fe8f707ab4c132ef1dbc62' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/functions_include.php', '37a3dc5111fe8f707ab4c132ef1dbc62' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/functions_include.php',
@@ -92,7 +92,10 @@ class ComposerStaticInit9da6744efcb5435630815fb416a6752c
'e39a8b23c42d4e1452234d762b03835a' => __DIR__ . '/..' . '/ramsey/uuid/src/functions.php', 'e39a8b23c42d4e1452234d762b03835a' => __DIR__ . '/..' . '/ramsey/uuid/src/functions.php',
'2c102faa651ef8ea5874edb585946bce' => __DIR__ . '/..' . '/swiftmailer/swiftmailer/lib/swift_required.php', '2c102faa651ef8ea5874edb585946bce' => __DIR__ . '/..' . '/swiftmailer/swiftmailer/lib/swift_required.php',
'8a9dc1de0ca7e01f3e08231539562f61' => __DIR__ . '/..' . '/aws/aws-sdk-php/src/functions.php', '8a9dc1de0ca7e01f3e08231539562f61' => __DIR__ . '/..' . '/aws/aws-sdk-php/src/functions.php',
'4a1f389d6ce373bda9e57857d3b61c84' => __DIR__ . '/..' . '/barryvdh/laravel-debugbar/src/helpers.php',
'ed962a97bd972bc82007176b647d4e36' => __DIR__ . '/..' . '/facade/ignition/src/helpers.php', 'ed962a97bd972bc82007176b647d4e36' => __DIR__ . '/..' . '/facade/ignition/src/helpers.php',
'265b4faa2b3a9766332744949e83bf97' => __DIR__ . '/..' . '/laravel/framework/src/Illuminate/Collections/helpers.php',
'c7a3c339e7e14b60e06a2d7fcce9476b' => __DIR__ . '/..' . '/laravel/framework/src/Illuminate/Events/functions.php',
'f0906e6318348a765ffb6eb24e0d0938' => __DIR__ . '/..' . '/laravel/framework/src/Illuminate/Foundation/helpers.php', 'f0906e6318348a765ffb6eb24e0d0938' => __DIR__ . '/..' . '/laravel/framework/src/Illuminate/Foundation/helpers.php',
'58571171fd5812e6e447dce228f52f4d' => __DIR__ . '/..' . '/laravel/framework/src/Illuminate/Support/helpers.php', '58571171fd5812e6e447dce228f52f4d' => __DIR__ . '/..' . '/laravel/framework/src/Illuminate/Support/helpers.php',
'f18cc91337d49233e5754e93f3ed9ec3' => __DIR__ . '/..' . '/laravelcollective/html/src/helpers.php', 'f18cc91337d49233e5754e93f3ed9ec3' => __DIR__ . '/..' . '/laravelcollective/html/src/helpers.php',
@@ -210,6 +213,7 @@ class ComposerStaticInit9da6744efcb5435630815fb416a6752c
'M' => 'M' =>
array ( array (
'MyCLabs\\Enum\\' => 13, 'MyCLabs\\Enum\\' => 13,
'Mremi\\UrlShortener\\' => 19,
'Monolog\\' => 8, 'Monolog\\' => 8,
'Matrix\\' => 7, 'Matrix\\' => 7,
'Maatwebsite\\Excel\\' => 18, 'Maatwebsite\\Excel\\' => 18,
@@ -225,6 +229,7 @@ class ComposerStaticInit9da6744efcb5435630815fb416a6752c
'Laravel\\Ui\\' => 11, 'Laravel\\Ui\\' => 11,
'Laravel\\Tinker\\' => 15, 'Laravel\\Tinker\\' => 15,
'Laravel\\Socialite\\' => 18, 'Laravel\\Socialite\\' => 18,
'Laravel\\SerializableClosure\\' => 28,
'Laravel\\Dusk\\' => 13, 'Laravel\\Dusk\\' => 13,
), ),
'J' => 'J' =>
@@ -234,6 +239,7 @@ class ComposerStaticInit9da6744efcb5435630815fb416a6752c
'I' => 'I' =>
array ( array (
'Intervention\\Image\\' => 19, 'Intervention\\Image\\' => 19,
'Illuminate\\Support\\' => 19,
'Illuminate\\Foundation\\Auth\\' => 27, 'Illuminate\\Foundation\\Auth\\' => 27,
'Illuminate\\' => 11, 'Illuminate\\' => 11,
), ),
@@ -242,13 +248,13 @@ class ComposerStaticInit9da6744efcb5435630815fb416a6752c
'GuzzleHttp\\Psr7\\' => 16, 'GuzzleHttp\\Psr7\\' => 16,
'GuzzleHttp\\Promise\\' => 19, 'GuzzleHttp\\Promise\\' => 19,
'GuzzleHttp\\' => 11, 'GuzzleHttp\\' => 11,
'GrahamCampbell\\ResultType\\' => 26,
'Gitonomy\\Git\\' => 13, 'Gitonomy\\Git\\' => 13,
'Giggsey\\Locale\\' => 15, 'Giggsey\\Locale\\' => 15,
), ),
'F' => 'F' =>
array ( array (
'Fruitcake\\Cors\\' => 15, 'Fruitcake\\Cors\\' => 15,
'Fideloper\\Proxy\\' => 16,
'Faker\\' => 6, 'Faker\\' => 6,
'Facebook\\WebDriver\\' => 19, 'Facebook\\WebDriver\\' => 19,
'Facade\\Ignition\\' => 16, 'Facade\\Ignition\\' => 16,
@@ -270,7 +276,10 @@ class ComposerStaticInit9da6744efcb5435630815fb416a6752c
'Doctrine\\Common\\Cache\\' => 22, 'Doctrine\\Common\\Cache\\' => 22,
'Doctrine\\Common\\' => 16, 'Doctrine\\Common\\' => 16,
'DeepCopy\\' => 9, 'DeepCopy\\' => 9,
'DebugBar\\' => 9,
'DaveJamesMiller\\Breadcrumbs\\' => 28, 'DaveJamesMiller\\Breadcrumbs\\' => 28,
'Database\\Seeders\\' => 17,
'Database\\Factories\\' => 19,
), ),
'C' => 'C' =>
array ( array (
@@ -286,6 +295,7 @@ class ComposerStaticInit9da6744efcb5435630815fb416a6752c
'Bugsnag\\BugsnagLaravel\\' => 23, 'Bugsnag\\BugsnagLaravel\\' => 23,
'Bugsnag\\' => 8, 'Bugsnag\\' => 8,
'Brick\\Math\\' => 11, 'Brick\\Math\\' => 11,
'Barryvdh\\Debugbar\\' => 18,
), ),
'A' => 'A' =>
array ( array (
@@ -303,8 +313,8 @@ class ComposerStaticInit9da6744efcb5435630815fb416a6752c
'phpDocumentor\\Reflection\\' => 'phpDocumentor\\Reflection\\' =>
array ( array (
0 => __DIR__ . '/..' . '/phpdocumentor/reflection-common/src', 0 => __DIR__ . '/..' . '/phpdocumentor/reflection-common/src',
1 => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src', 1 => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src',
2 => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src', 2 => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src',
), ),
'libphonenumber\\' => 'libphonenumber\\' =>
array ( array (
@@ -492,8 +502,8 @@ class ComposerStaticInit9da6744efcb5435630815fb416a6752c
), ),
'Psr\\Http\\Message\\' => 'Psr\\Http\\Message\\' =>
array ( array (
0 => __DIR__ . '/..' . '/psr/http-factory/src', 0 => __DIR__ . '/..' . '/psr/http-message/src',
1 => __DIR__ . '/..' . '/psr/http-message/src', 1 => __DIR__ . '/..' . '/psr/http-factory/src',
), ),
'Psr\\Http\\Client\\' => 'Psr\\Http\\Client\\' =>
array ( array (
@@ -551,6 +561,10 @@ class ComposerStaticInit9da6744efcb5435630815fb416a6752c
array ( array (
0 => __DIR__ . '/..' . '/myclabs/php-enum/src', 0 => __DIR__ . '/..' . '/myclabs/php-enum/src',
), ),
'Mremi\\UrlShortener\\' =>
array (
0 => __DIR__ . '/..' . '/mremi/url-shortener/src/Mremi/UrlShortener',
),
'Monolog\\' => 'Monolog\\' =>
array ( array (
0 => __DIR__ . '/..' . '/monolog/monolog/src/Monolog', 0 => __DIR__ . '/..' . '/monolog/monolog/src/Monolog',
@@ -599,6 +613,10 @@ class ComposerStaticInit9da6744efcb5435630815fb416a6752c
array ( array (
0 => __DIR__ . '/..' . '/laravel/socialite/src', 0 => __DIR__ . '/..' . '/laravel/socialite/src',
), ),
'Laravel\\SerializableClosure\\' =>
array (
0 => __DIR__ . '/..' . '/laravel/serializable-closure/src',
),
'Laravel\\Dusk\\' => 'Laravel\\Dusk\\' =>
array ( array (
0 => __DIR__ . '/..' . '/laravel/dusk/src', 0 => __DIR__ . '/..' . '/laravel/dusk/src',
@@ -611,6 +629,11 @@ class ComposerStaticInit9da6744efcb5435630815fb416a6752c
array ( array (
0 => __DIR__ . '/..' . '/intervention/image/src/Intervention/Image', 0 => __DIR__ . '/..' . '/intervention/image/src/Intervention/Image',
), ),
'Illuminate\\Support\\' =>
array (
0 => __DIR__ . '/..' . '/laravel/framework/src/Illuminate/Macroable',
1 => __DIR__ . '/..' . '/laravel/framework/src/Illuminate/Collections',
),
'Illuminate\\Foundation\\Auth\\' => 'Illuminate\\Foundation\\Auth\\' =>
array ( array (
0 => __DIR__ . '/..' . '/laravel/ui/auth-backend', 0 => __DIR__ . '/..' . '/laravel/ui/auth-backend',
@@ -631,6 +654,10 @@ class ComposerStaticInit9da6744efcb5435630815fb416a6752c
array ( array (
0 => __DIR__ . '/..' . '/guzzlehttp/guzzle/src', 0 => __DIR__ . '/..' . '/guzzlehttp/guzzle/src',
), ),
'GrahamCampbell\\ResultType\\' =>
array (
0 => __DIR__ . '/..' . '/graham-campbell/result-type/src',
),
'Gitonomy\\Git\\' => 'Gitonomy\\Git\\' =>
array ( array (
0 => __DIR__ . '/..' . '/gitonomy/gitlib/src/Gitonomy/Git', 0 => __DIR__ . '/..' . '/gitonomy/gitlib/src/Gitonomy/Git',
@@ -643,10 +670,6 @@ class ComposerStaticInit9da6744efcb5435630815fb416a6752c
array ( array (
0 => __DIR__ . '/..' . '/fruitcake/laravel-cors/src', 0 => __DIR__ . '/..' . '/fruitcake/laravel-cors/src',
), ),
'Fideloper\\Proxy\\' =>
array (
0 => __DIR__ . '/..' . '/fideloper/proxy/src',
),
'Faker\\' => 'Faker\\' =>
array ( array (
0 => __DIR__ . '/..' . '/fakerphp/faker/src/Faker', 0 => __DIR__ . '/..' . '/fakerphp/faker/src/Faker',
@@ -707,10 +730,22 @@ class ComposerStaticInit9da6744efcb5435630815fb416a6752c
array ( array (
0 => __DIR__ . '/..' . '/myclabs/deep-copy/src/DeepCopy', 0 => __DIR__ . '/..' . '/myclabs/deep-copy/src/DeepCopy',
), ),
'DebugBar\\' =>
array (
0 => __DIR__ . '/..' . '/maximebf/debugbar/src/DebugBar',
),
'DaveJamesMiller\\Breadcrumbs\\' => 'DaveJamesMiller\\Breadcrumbs\\' =>
array ( array (
0 => __DIR__ . '/..' . '/davejamesmiller/laravel-breadcrumbs/src', 0 => __DIR__ . '/..' . '/davejamesmiller/laravel-breadcrumbs/src',
), ),
'Database\\Seeders\\' =>
array (
0 => __DIR__ . '/../..' . '/database/seeders',
),
'Database\\Factories\\' =>
array (
0 => __DIR__ . '/../..' . '/database/factories',
),
'Cron\\' => 'Cron\\' =>
array ( array (
0 => __DIR__ . '/..' . '/dragonmantank/cron-expression/src/Cron', 0 => __DIR__ . '/..' . '/dragonmantank/cron-expression/src/Cron',
@@ -747,6 +782,10 @@ class ComposerStaticInit9da6744efcb5435630815fb416a6752c
array ( array (
0 => __DIR__ . '/..' . '/brick/math/src', 0 => __DIR__ . '/..' . '/brick/math/src',
), ),
'Barryvdh\\Debugbar\\' =>
array (
0 => __DIR__ . '/..' . '/barryvdh/laravel-debugbar/src',
),
'Aws\\' => 'Aws\\' =>
array ( array (
0 => __DIR__ . '/..' . '/aws/aws-sdk-php/src', 0 => __DIR__ . '/..' . '/aws/aws-sdk-php/src',
@@ -778,10 +817,6 @@ class ComposerStaticInit9da6744efcb5435630815fb416a6752c
), ),
'M' => 'M' =>
array ( array (
'Mremi\\UrlShortener' =>
array (
0 => __DIR__ . '/..' . '/mremi/url-shortener/src',
),
'Mockery' => 'Mockery' =>
array ( array (
0 => __DIR__ . '/..' . '/mockery/mockery/library', 0 => __DIR__ . '/..' . '/mockery/mockery/library',
@@ -794,17 +829,6 @@ class ComposerStaticInit9da6744efcb5435630815fb416a6752c
0 => __DIR__ . '/..' . '/ezyang/htmlpurifier/library', 0 => __DIR__ . '/..' . '/ezyang/htmlpurifier/library',
), ),
), ),
'G' =>
array (
'Guzzle\\Tests' =>
array (
0 => __DIR__ . '/..' . '/guzzle/guzzle/tests',
),
'Guzzle' =>
array (
0 => __DIR__ . '/..' . '/guzzle/guzzle/src',
),
),
'F' => 'F' =>
array ( array (
'ForceUTF8\\' => 'ForceUTF8\\' =>
@@ -873,6 +897,7 @@ class ComposerStaticInit9da6744efcb5435630815fb416a6752c
'AddForeignKeysToTicketsTable' => __DIR__ . '/../..' . '/database/migrations/2016_02_16_140454_add_foreign_keys_to_tickets_table.php', 'AddForeignKeysToTicketsTable' => __DIR__ . '/../..' . '/database/migrations/2016_02_16_140454_add_foreign_keys_to_tickets_table.php',
'AddForeignKeysToUserAssignOrganizationTable' => __DIR__ . '/../..' . '/database/migrations/2016_02_16_140454_add_foreign_keys_to_user_assign_organization_table.php', 'AddForeignKeysToUserAssignOrganizationTable' => __DIR__ . '/../..' . '/database/migrations/2016_02_16_140454_add_foreign_keys_to_user_assign_organization_table.php',
'AddForeignKeysToUsersTable' => __DIR__ . '/../..' . '/database/migrations/2016_02_16_140454_add_foreign_keys_to_users_table.php', 'AddForeignKeysToUsersTable' => __DIR__ . '/../..' . '/database/migrations/2016_02_16_140454_add_foreign_keys_to_users_table.php',
'AddUuidToFailedJobsTable' => __DIR__ . '/../..' . '/database/migrations/2023_01_07_000000_add_uuid_to_failed_jobs_table.php',
'Adobe_Font_Metrics' => __DIR__ . '/..' . '/phenx/php-font-lib/classes/Adobe_Font_Metrics.php', 'Adobe_Font_Metrics' => __DIR__ . '/..' . '/phenx/php-font-lib/classes/Adobe_Font_Metrics.php',
'AlterEmailsTableMakeUsernameColumnNullable' => __DIR__ . '/../..' . '/database/migrations/2018_08_13_075015_alter_emails_table_make_username_column_nullable.php', 'AlterEmailsTableMakeUsernameColumnNullable' => __DIR__ . '/../..' . '/database/migrations/2018_08_13_075015_alter_emails_table_make_username_column_nullable.php',
'AlterTicketSourceTable' => __DIR__ . '/../..' . '/database/migrations/2016_08_16_104539_alter_ticket_source_table.php', 'AlterTicketSourceTable' => __DIR__ . '/../..' . '/database/migrations/2016_08_16_104539_alter_ticket_source_table.php',
@@ -982,7 +1007,10 @@ class ComposerStaticInit9da6744efcb5435630815fb416a6752c
'DOMPDF' => __DIR__ . '/..' . '/dompdf/dompdf/include/dompdf.cls.php', 'DOMPDF' => __DIR__ . '/..' . '/dompdf/dompdf/include/dompdf.cls.php',
'DOMPDF_Exception' => __DIR__ . '/..' . '/dompdf/dompdf/include/dompdf_exception.cls.php', 'DOMPDF_Exception' => __DIR__ . '/..' . '/dompdf/dompdf/include/dompdf_exception.cls.php',
'DOMPDF_Image_Exception' => __DIR__ . '/..' . '/dompdf/dompdf/include/dompdf_image_exception.cls.php', 'DOMPDF_Image_Exception' => __DIR__ . '/..' . '/dompdf/dompdf/include/dompdf_image_exception.cls.php',
'DatabaseSeeder' => __DIR__ . '/../..' . '/database/seeds/DatabaseSeeder.php', 'Database\\Seeders\\DatabaseSeeder' => __DIR__ . '/../..' . '/database/seeders/DatabaseSeeder.php',
'Database\\Seeders\\OutboundMailSeeder' => __DIR__ . '/../..' . '/database/seeders/OutboundMailSeeder.php',
'Database\\Seeders\\TicketSourceSeeder' => __DIR__ . '/../..' . '/database/seeders/TicketSourceSeeder.php',
'Database\\Seeders\\UserSeeder' => __DIR__ . '/../..' . '/database/seeders/UserSeeder.php',
'Encoding_Map' => __DIR__ . '/..' . '/phenx/php-font-lib/classes/Encoding_Map.php', 'Encoding_Map' => __DIR__ . '/..' . '/phenx/php-font-lib/classes/Encoding_Map.php',
'Fixed_Positioner' => __DIR__ . '/..' . '/dompdf/dompdf/include/fixed_positioner.cls.php', 'Fixed_Positioner' => __DIR__ . '/..' . '/dompdf/dompdf/include/fixed_positioner.cls.php',
'Font' => __DIR__ . '/..' . '/phenx/php-font-lib/classes/Font.php', 'Font' => __DIR__ . '/..' . '/phenx/php-font-lib/classes/Font.php',
@@ -1116,7 +1144,6 @@ class ComposerStaticInit9da6744efcb5435630815fb416a6752c
'Null_Frame_Decorator' => __DIR__ . '/..' . '/dompdf/dompdf/include/null_frame_decorator.cls.php', 'Null_Frame_Decorator' => __DIR__ . '/..' . '/dompdf/dompdf/include/null_frame_decorator.cls.php',
'Null_Frame_Reflower' => __DIR__ . '/..' . '/dompdf/dompdf/include/null_frame_reflower.cls.php', 'Null_Frame_Reflower' => __DIR__ . '/..' . '/dompdf/dompdf/include/null_frame_reflower.cls.php',
'Null_Positioner' => __DIR__ . '/..' . '/dompdf/dompdf/include/null_positioner.cls.php', 'Null_Positioner' => __DIR__ . '/..' . '/dompdf/dompdf/include/null_positioner.cls.php',
'OutboundMailSeeder' => __DIR__ . '/../..' . '/database/seeds/OutboundMailSeeder.php',
'PDFLib_Adapter' => __DIR__ . '/..' . '/dompdf/dompdf/include/pdflib_adapter.cls.php', 'PDFLib_Adapter' => __DIR__ . '/..' . '/dompdf/dompdf/include/pdflib_adapter.cls.php',
'PHPUnit\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/Exception.php', 'PHPUnit\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/Exception.php',
'PHPUnit\\Framework\\ActualValueIsNotAnObjectException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/ActualValueIsNotAnObjectException.php', 'PHPUnit\\Framework\\ActualValueIsNotAnObjectException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/ActualValueIsNotAnObjectException.php',
@@ -1773,9 +1800,7 @@ class ComposerStaticInit9da6744efcb5435630815fb416a6752c
'TheSeer\\Tokenizer\\TokenCollectionException' => __DIR__ . '/..' . '/theseer/tokenizer/src/TokenCollectionException.php', 'TheSeer\\Tokenizer\\TokenCollectionException' => __DIR__ . '/..' . '/theseer/tokenizer/src/TokenCollectionException.php',
'TheSeer\\Tokenizer\\Tokenizer' => __DIR__ . '/..' . '/theseer/tokenizer/src/Tokenizer.php', 'TheSeer\\Tokenizer\\Tokenizer' => __DIR__ . '/..' . '/theseer/tokenizer/src/Tokenizer.php',
'TheSeer\\Tokenizer\\XMLSerializer' => __DIR__ . '/..' . '/theseer/tokenizer/src/XMLSerializer.php', 'TheSeer\\Tokenizer\\XMLSerializer' => __DIR__ . '/..' . '/theseer/tokenizer/src/XMLSerializer.php',
'TicketSourceSeeder' => __DIR__ . '/../..' . '/database/seeds/TicketSourceSeeder.php',
'UnhandledMatchError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php', 'UnhandledMatchError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php',
'UserSeeder' => __DIR__ . '/../..' . '/database/seeds/UserSeeder.php',
'ValueError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/ValueError.php', 'ValueError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/ValueError.php',
'Version1079table' => __DIR__ . '/../..' . '/database/migrations/2016_06_28_141613_version1079table.php', 'Version1079table' => __DIR__ . '/../..' . '/database/migrations/2016_06_28_141613_version1079table.php',
); );
@@ -1783,10 +1808,10 @@ class ComposerStaticInit9da6744efcb5435630815fb416a6752c
public static function getInitializer(ClassLoader $loader) public static function getInitializer(ClassLoader $loader)
{ {
return \Closure::bind(function () use ($loader) { return \Closure::bind(function () use ($loader) {
$loader->prefixLengthsPsr4 = ComposerStaticInit9da6744efcb5435630815fb416a6752c::$prefixLengthsPsr4; $loader->prefixLengthsPsr4 = ComposerStaticInite3a664ccc4def6142d1c80482606ee61::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInit9da6744efcb5435630815fb416a6752c::$prefixDirsPsr4; $loader->prefixDirsPsr4 = ComposerStaticInite3a664ccc4def6142d1c80482606ee61::$prefixDirsPsr4;
$loader->prefixesPsr0 = ComposerStaticInit9da6744efcb5435630815fb416a6752c::$prefixesPsr0; $loader->prefixesPsr0 = ComposerStaticInite3a664ccc4def6142d1c80482606ee61::$prefixesPsr0;
$loader->classMap = ComposerStaticInit9da6744efcb5435630815fb416a6752c::$classMap; $loader->classMap = ComposerStaticInite3a664ccc4def6142d1c80482606ee61::$classMap;
}, null, ClassLoader::class); }, null, ClassLoader::class);
} }

File diff suppressed because it is too large Load Diff

View File

@@ -5,7 +5,7 @@
'type' => 'project', 'type' => 'project',
'install_path' => __DIR__ . '/../../', 'install_path' => __DIR__ . '/../../',
'aliases' => array(), 'aliases' => array(),
'reference' => '51056e3aad4cde6c2b824c9965f9ea08610c29ff', 'reference' => '043364042600557fd5dadbe5882735f1c4b29029',
'name' => 'laravel/laravel', 'name' => 'laravel/laravel',
'dev' => true, 'dev' => true,
), ),
@@ -37,6 +37,15 @@
'reference' => 'e851af4d7d2d95b131db344430384ae7cc04758e', 'reference' => 'e851af4d7d2d95b131db344430384ae7cc04758e',
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'barryvdh/laravel-debugbar' => array(
'pretty_version' => 'v3.7.0',
'version' => '3.7.0.0',
'type' => 'library',
'install_path' => __DIR__ . '/../barryvdh/laravel-debugbar',
'aliases' => array(),
'reference' => '3372ed65e6d2039d663ed19aa699956f9d346271',
'dev_requirement' => true,
),
'brick/math' => array( 'brick/math' => array(
'pretty_version' => '0.9.3', 'pretty_version' => '0.9.3',
'version' => '0.9.3.0', 'version' => '0.9.3.0',
@@ -185,12 +194,12 @@
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'dragonmantank/cron-expression' => array( 'dragonmantank/cron-expression' => array(
'pretty_version' => 'v2.3.1', 'pretty_version' => 'v3.3.2',
'version' => '2.3.1.0', 'version' => '3.3.2.0',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../dragonmantank/cron-expression', 'install_path' => __DIR__ . '/../dragonmantank/cron-expression',
'aliases' => array(), 'aliases' => array(),
'reference' => '65b2d8ee1f10915efb3b55597da3404f096acba2', 'reference' => '782ca5968ab8b954773518e9e49a6f892a34b2a8',
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'egulias/email-validator' => array( 'egulias/email-validator' => array(
@@ -253,15 +262,6 @@
'reference' => '37f751c67a5372d4e26353bd9384bc03744ec77b', 'reference' => '37f751c67a5372d4e26353bd9384bc03744ec77b',
'dev_requirement' => true, 'dev_requirement' => true,
), ),
'fideloper/proxy' => array(
'pretty_version' => '4.4.2',
'version' => '4.4.2.0',
'type' => 'library',
'install_path' => __DIR__ . '/../fideloper/proxy',
'aliases' => array(),
'reference' => 'a751f2bc86dd8e6cfef12dc0cbdada82f5a18750',
'dev_requirement' => false,
),
'filp/whoops' => array( 'filp/whoops' => array(
'pretty_version' => '2.14.6', 'pretty_version' => '2.14.6',
'version' => '2.14.6.0', 'version' => '2.14.6.0',
@@ -316,147 +316,15 @@
'reference' => '00b57b79f02396aa4c7c163f76fe2bc48faebbb7', 'reference' => '00b57b79f02396aa4c7c163f76fe2bc48faebbb7',
'dev_requirement' => true, 'dev_requirement' => true,
), ),
'guzzle/batch' => array( 'graham-campbell/result-type' => array(
'dev_requirement' => false, 'pretty_version' => 'v1.1.0',
'replaced' => array( 'version' => '1.1.0.0',
0 => 'v3.8.1',
),
),
'guzzle/cache' => array(
'dev_requirement' => false,
'replaced' => array(
0 => 'v3.8.1',
),
),
'guzzle/common' => array(
'dev_requirement' => false,
'replaced' => array(
0 => 'v3.8.1',
),
),
'guzzle/guzzle' => array(
'pretty_version' => 'v3.8.1',
'version' => '3.8.1.0',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../guzzle/guzzle', 'install_path' => __DIR__ . '/../graham-campbell/result-type',
'aliases' => array(), 'aliases' => array(),
'reference' => '4de0618a01b34aa1c8c33a3f13f396dcd3882eba', 'reference' => 'a878d45c1914464426dc94da61c9e1d36ae262a8',
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'guzzle/http' => array(
'dev_requirement' => false,
'replaced' => array(
0 => 'v3.8.1',
),
),
'guzzle/inflection' => array(
'dev_requirement' => false,
'replaced' => array(
0 => 'v3.8.1',
),
),
'guzzle/iterator' => array(
'dev_requirement' => false,
'replaced' => array(
0 => 'v3.8.1',
),
),
'guzzle/log' => array(
'dev_requirement' => false,
'replaced' => array(
0 => 'v3.8.1',
),
),
'guzzle/parser' => array(
'dev_requirement' => false,
'replaced' => array(
0 => 'v3.8.1',
),
),
'guzzle/plugin' => array(
'dev_requirement' => false,
'replaced' => array(
0 => 'v3.8.1',
),
),
'guzzle/plugin-async' => array(
'dev_requirement' => false,
'replaced' => array(
0 => 'v3.8.1',
),
),
'guzzle/plugin-backoff' => array(
'dev_requirement' => false,
'replaced' => array(
0 => 'v3.8.1',
),
),
'guzzle/plugin-cache' => array(
'dev_requirement' => false,
'replaced' => array(
0 => 'v3.8.1',
),
),
'guzzle/plugin-cookie' => array(
'dev_requirement' => false,
'replaced' => array(
0 => 'v3.8.1',
),
),
'guzzle/plugin-curlauth' => array(
'dev_requirement' => false,
'replaced' => array(
0 => 'v3.8.1',
),
),
'guzzle/plugin-error-response' => array(
'dev_requirement' => false,
'replaced' => array(
0 => 'v3.8.1',
),
),
'guzzle/plugin-history' => array(
'dev_requirement' => false,
'replaced' => array(
0 => 'v3.8.1',
),
),
'guzzle/plugin-log' => array(
'dev_requirement' => false,
'replaced' => array(
0 => 'v3.8.1',
),
),
'guzzle/plugin-md5' => array(
'dev_requirement' => false,
'replaced' => array(
0 => 'v3.8.1',
),
),
'guzzle/plugin-mock' => array(
'dev_requirement' => false,
'replaced' => array(
0 => 'v3.8.1',
),
),
'guzzle/plugin-oauth' => array(
'dev_requirement' => false,
'replaced' => array(
0 => 'v3.8.1',
),
),
'guzzle/service' => array(
'dev_requirement' => false,
'replaced' => array(
0 => 'v3.8.1',
),
),
'guzzle/stream' => array(
'dev_requirement' => false,
'replaced' => array(
0 => 'v3.8.1',
),
),
'guzzlehttp/guzzle' => array( 'guzzlehttp/guzzle' => array(
'pretty_version' => '7.5.0', 'pretty_version' => '7.5.0',
'version' => '7.5.0.0', 'version' => '7.5.0.0',
@@ -496,175 +364,187 @@
'illuminate/auth' => array( 'illuminate/auth' => array(
'dev_requirement' => false, 'dev_requirement' => false,
'replaced' => array( 'replaced' => array(
0 => 'v7.30.6', 0 => 'v8.83.27',
), ),
), ),
'illuminate/broadcasting' => array( 'illuminate/broadcasting' => array(
'dev_requirement' => false, 'dev_requirement' => false,
'replaced' => array( 'replaced' => array(
0 => 'v7.30.6', 0 => 'v8.83.27',
), ),
), ),
'illuminate/bus' => array( 'illuminate/bus' => array(
'dev_requirement' => false, 'dev_requirement' => false,
'replaced' => array( 'replaced' => array(
0 => 'v7.30.6', 0 => 'v8.83.27',
), ),
), ),
'illuminate/cache' => array( 'illuminate/cache' => array(
'dev_requirement' => false, 'dev_requirement' => false,
'replaced' => array( 'replaced' => array(
0 => 'v7.30.6', 0 => 'v8.83.27',
),
),
'illuminate/collections' => array(
'dev_requirement' => false,
'replaced' => array(
0 => 'v8.83.27',
), ),
), ),
'illuminate/config' => array( 'illuminate/config' => array(
'dev_requirement' => false, 'dev_requirement' => false,
'replaced' => array( 'replaced' => array(
0 => 'v7.30.6', 0 => 'v8.83.27',
), ),
), ),
'illuminate/console' => array( 'illuminate/console' => array(
'dev_requirement' => false, 'dev_requirement' => false,
'replaced' => array( 'replaced' => array(
0 => 'v7.30.6', 0 => 'v8.83.27',
), ),
), ),
'illuminate/container' => array( 'illuminate/container' => array(
'dev_requirement' => false, 'dev_requirement' => false,
'replaced' => array( 'replaced' => array(
0 => 'v7.30.6', 0 => 'v8.83.27',
), ),
), ),
'illuminate/contracts' => array( 'illuminate/contracts' => array(
'dev_requirement' => false, 'dev_requirement' => false,
'replaced' => array( 'replaced' => array(
0 => 'v7.30.6', 0 => 'v8.83.27',
), ),
), ),
'illuminate/cookie' => array( 'illuminate/cookie' => array(
'dev_requirement' => false, 'dev_requirement' => false,
'replaced' => array( 'replaced' => array(
0 => 'v7.30.6', 0 => 'v8.83.27',
), ),
), ),
'illuminate/database' => array( 'illuminate/database' => array(
'dev_requirement' => false, 'dev_requirement' => false,
'replaced' => array( 'replaced' => array(
0 => 'v7.30.6', 0 => 'v8.83.27',
), ),
), ),
'illuminate/encryption' => array( 'illuminate/encryption' => array(
'dev_requirement' => false, 'dev_requirement' => false,
'replaced' => array( 'replaced' => array(
0 => 'v7.30.6', 0 => 'v8.83.27',
), ),
), ),
'illuminate/events' => array( 'illuminate/events' => array(
'dev_requirement' => false, 'dev_requirement' => false,
'replaced' => array( 'replaced' => array(
0 => 'v7.30.6', 0 => 'v8.83.27',
), ),
), ),
'illuminate/filesystem' => array( 'illuminate/filesystem' => array(
'dev_requirement' => false, 'dev_requirement' => false,
'replaced' => array( 'replaced' => array(
0 => 'v7.30.6', 0 => 'v8.83.27',
), ),
), ),
'illuminate/hashing' => array( 'illuminate/hashing' => array(
'dev_requirement' => false, 'dev_requirement' => false,
'replaced' => array( 'replaced' => array(
0 => 'v7.30.6', 0 => 'v8.83.27',
), ),
), ),
'illuminate/http' => array( 'illuminate/http' => array(
'dev_requirement' => false, 'dev_requirement' => false,
'replaced' => array( 'replaced' => array(
0 => 'v7.30.6', 0 => 'v8.83.27',
), ),
), ),
'illuminate/log' => array( 'illuminate/log' => array(
'dev_requirement' => false, 'dev_requirement' => false,
'replaced' => array( 'replaced' => array(
0 => 'v7.30.6', 0 => 'v8.83.27',
),
),
'illuminate/macroable' => array(
'dev_requirement' => false,
'replaced' => array(
0 => 'v8.83.27',
), ),
), ),
'illuminate/mail' => array( 'illuminate/mail' => array(
'dev_requirement' => false, 'dev_requirement' => false,
'replaced' => array( 'replaced' => array(
0 => 'v7.30.6', 0 => 'v8.83.27',
), ),
), ),
'illuminate/notifications' => array( 'illuminate/notifications' => array(
'dev_requirement' => false, 'dev_requirement' => false,
'replaced' => array( 'replaced' => array(
0 => 'v7.30.6', 0 => 'v8.83.27',
), ),
), ),
'illuminate/pagination' => array( 'illuminate/pagination' => array(
'dev_requirement' => false, 'dev_requirement' => false,
'replaced' => array( 'replaced' => array(
0 => 'v7.30.6', 0 => 'v8.83.27',
), ),
), ),
'illuminate/pipeline' => array( 'illuminate/pipeline' => array(
'dev_requirement' => false, 'dev_requirement' => false,
'replaced' => array( 'replaced' => array(
0 => 'v7.30.6', 0 => 'v8.83.27',
), ),
), ),
'illuminate/queue' => array( 'illuminate/queue' => array(
'dev_requirement' => false, 'dev_requirement' => false,
'replaced' => array( 'replaced' => array(
0 => 'v7.30.6', 0 => 'v8.83.27',
), ),
), ),
'illuminate/redis' => array( 'illuminate/redis' => array(
'dev_requirement' => false, 'dev_requirement' => false,
'replaced' => array( 'replaced' => array(
0 => 'v7.30.6', 0 => 'v8.83.27',
), ),
), ),
'illuminate/routing' => array( 'illuminate/routing' => array(
'dev_requirement' => false, 'dev_requirement' => false,
'replaced' => array( 'replaced' => array(
0 => 'v7.30.6', 0 => 'v8.83.27',
), ),
), ),
'illuminate/session' => array( 'illuminate/session' => array(
'dev_requirement' => false, 'dev_requirement' => false,
'replaced' => array( 'replaced' => array(
0 => 'v7.30.6', 0 => 'v8.83.27',
), ),
), ),
'illuminate/support' => array( 'illuminate/support' => array(
'dev_requirement' => false, 'dev_requirement' => false,
'replaced' => array( 'replaced' => array(
0 => 'v7.30.6', 0 => 'v8.83.27',
), ),
), ),
'illuminate/testing' => array( 'illuminate/testing' => array(
'dev_requirement' => false, 'dev_requirement' => false,
'replaced' => array( 'replaced' => array(
0 => 'v7.30.6', 0 => 'v8.83.27',
), ),
), ),
'illuminate/translation' => array( 'illuminate/translation' => array(
'dev_requirement' => false, 'dev_requirement' => false,
'replaced' => array( 'replaced' => array(
0 => 'v7.30.6', 0 => 'v8.83.27',
), ),
), ),
'illuminate/validation' => array( 'illuminate/validation' => array(
'dev_requirement' => false, 'dev_requirement' => false,
'replaced' => array( 'replaced' => array(
0 => 'v7.30.6', 0 => 'v8.83.27',
), ),
), ),
'illuminate/view' => array( 'illuminate/view' => array(
'dev_requirement' => false, 'dev_requirement' => false,
'replaced' => array( 'replaced' => array(
0 => 'v7.30.6', 0 => 'v8.83.27',
), ),
), ),
'intervention/image' => array( 'intervention/image' => array(
@@ -683,21 +563,21 @@
), ),
), ),
'laravel/dusk' => array( 'laravel/dusk' => array(
'pretty_version' => 'v5.11.0', 'pretty_version' => 'v6.25.2',
'version' => '5.11.0.0', 'version' => '6.25.2.0',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../laravel/dusk', 'install_path' => __DIR__ . '/../laravel/dusk',
'aliases' => array(), 'aliases' => array(),
'reference' => 'e07cc46a1e39767739e8197189780b4c2639806d', 'reference' => '25a595ac3dc82089a91af10dd23b0d58fd3f6d0b',
'dev_requirement' => true, 'dev_requirement' => true,
), ),
'laravel/framework' => array( 'laravel/framework' => array(
'pretty_version' => 'v7.30.6', 'pretty_version' => 'v8.83.27',
'version' => '7.30.6.0', 'version' => '8.83.27.0',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../laravel/framework', 'install_path' => __DIR__ . '/../laravel/framework',
'aliases' => array(), 'aliases' => array(),
'reference' => 'ecdafad1dda3c790af186a6d18479ea4757ef9ee', 'reference' => 'e1afe088b4ca613fb96dc57e6d8dbcb8cc2c6b49',
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'laravel/laravel' => array( 'laravel/laravel' => array(
@@ -706,16 +586,25 @@
'type' => 'project', 'type' => 'project',
'install_path' => __DIR__ . '/../../', 'install_path' => __DIR__ . '/../../',
'aliases' => array(), 'aliases' => array(),
'reference' => '51056e3aad4cde6c2b824c9965f9ea08610c29ff', 'reference' => '043364042600557fd5dadbe5882735f1c4b29029',
'dev_requirement' => false,
),
'laravel/serializable-closure' => array(
'pretty_version' => 'v1.2.2',
'version' => '1.2.2.0',
'type' => 'library',
'install_path' => __DIR__ . '/../laravel/serializable-closure',
'aliases' => array(),
'reference' => '47afb7fae28ed29057fdca37e16a84f90cc62fae',
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'laravel/socialite' => array( 'laravel/socialite' => array(
'pretty_version' => 'v4.4.1', 'pretty_version' => 'v5.5.7',
'version' => '4.4.1.0', 'version' => '5.5.7.0',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../laravel/socialite', 'install_path' => __DIR__ . '/../laravel/socialite',
'aliases' => array(), 'aliases' => array(),
'reference' => '80951df0d93435b773aa00efe1fad6d5015fac75', 'reference' => 'ee6201f539ac47c3a55132449f9d20ee928f0ee2',
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'laravel/tinker' => array( 'laravel/tinker' => array(
@@ -728,12 +617,12 @@
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'laravel/ui' => array( 'laravel/ui' => array(
'pretty_version' => 'v2.5.0', 'pretty_version' => 'v3.4.6',
'version' => '2.5.0.0', 'version' => '3.4.6.0',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../laravel/ui', 'install_path' => __DIR__ . '/../laravel/ui',
'aliases' => array(), 'aliases' => array(),
'reference' => 'd01a705763c243b07be795e9d1bb47f89260f73d', 'reference' => '65ec5c03f7fee2c8ecae785795b829a15be48c2c',
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'laravelcollective/html' => array( 'laravelcollective/html' => array(
@@ -773,12 +662,12 @@
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'league/iso3166' => array( 'league/iso3166' => array(
'pretty_version' => '3.0.0', 'pretty_version' => '4.1.0',
'version' => '3.0.0.0', 'version' => '4.1.0.0',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../league/iso3166', 'install_path' => __DIR__ . '/../league/iso3166',
'aliases' => array(), 'aliases' => array(),
'reference' => '9976d382f270ad3f3df8a68719beb7a7179ffa1e', 'reference' => 'a0dd2a1d956f85811f9c667a1744d822fb2c63d8',
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'league/mime-type-detection' => array( 'league/mime-type-detection' => array(
@@ -835,6 +724,15 @@
'reference' => '469e937dc91aa087e43b21a5266cb7567f482f3e', 'reference' => '469e937dc91aa087e43b21a5266cb7567f482f3e',
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'maximebf/debugbar' => array(
'pretty_version' => 'v1.18.1',
'version' => '1.18.1.0',
'type' => 'library',
'install_path' => __DIR__ . '/../maximebf/debugbar',
'aliases' => array(),
'reference' => 'ba0af68dd4316834701ecb30a00ce9604ced3ee9',
'dev_requirement' => true,
),
'mockery/mockery' => array( 'mockery/mockery' => array(
'pretty_version' => '1.5.1', 'pretty_version' => '1.5.1',
'version' => '1.5.1.0', 'version' => '1.5.1.0',
@@ -854,14 +752,20 @@
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'mremi/url-shortener' => array( 'mremi/url-shortener' => array(
'pretty_version' => 'v1.0.3', 'pretty_version' => 'v2.4.0',
'version' => '1.0.3.0', 'version' => '2.4.0.0',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../mremi/url-shortener', 'install_path' => __DIR__ . '/../mremi/url-shortener',
'aliases' => array(), 'aliases' => array(),
'reference' => 'ed3b482c2a2f0ff83e07e8a96ade13d9b84eb773', 'reference' => '346dcc25f491f962cd380813631da9f2e939b092',
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'mtdowling/cron-expression' => array(
'dev_requirement' => false,
'replaced' => array(
0 => '^1.0',
),
),
'mtdowling/jmespath.php' => array( 'mtdowling/jmespath.php' => array(
'pretty_version' => '2.6.1', 'pretty_version' => '2.6.1',
'version' => '2.6.1.0', 'version' => '2.6.1.0',
@@ -937,12 +841,12 @@
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'nunomaduro/collision' => array( 'nunomaduro/collision' => array(
'pretty_version' => 'v4.3.0', 'pretty_version' => 'v5.11.0',
'version' => '4.3.0.0', 'version' => '5.11.0.0',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../nunomaduro/collision', 'install_path' => __DIR__ . '/../nunomaduro/collision',
'aliases' => array(), 'aliases' => array(),
'reference' => '7c125dc2463f3e144ddc7e05e63077109508c94e', 'reference' => '8b610eef8582ccdc05d8f2ab23305e2d37049461',
'dev_requirement' => true, 'dev_requirement' => true,
), ),
'opis/closure' => array( 'opis/closure' => array(
@@ -1126,12 +1030,12 @@
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'propaganistas/laravel-phone' => array( 'propaganistas/laravel-phone' => array(
'pretty_version' => '4.2.7', 'pretty_version' => '4.4.0',
'version' => '4.2.7.0', 'version' => '4.4.0.0',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../propaganistas/laravel-phone', 'install_path' => __DIR__ . '/../propaganistas/laravel-phone',
'aliases' => array(), 'aliases' => array(),
'reference' => 'f2765e308977511c7ee42a48d635dca7026fa427', 'reference' => 'ba5aa49226793faf4bd37b38bd627d49269611d9',
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'psr/container' => array( 'psr/container' => array(
@@ -1221,8 +1125,8 @@
'psr/log-implementation' => array( 'psr/log-implementation' => array(
'dev_requirement' => false, 'dev_requirement' => false,
'provided' => array( 'provided' => array(
0 => '1.0.0 || 2.0.0 || 3.0.0', 0 => '1.0|2.0',
1 => '1.0|2.0', 1 => '1.0.0 || 2.0.0 || 3.0.0',
), ),
), ),
'psr/simple-cache' => array( 'psr/simple-cache' => array(
@@ -1234,6 +1138,12 @@
'reference' => '408d5eafb83c57f6365a3ca330ff23aa4a5fa39b', 'reference' => '408d5eafb83c57f6365a3ca330ff23aa4a5fa39b',
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'psr/simple-cache-implementation' => array(
'dev_requirement' => false,
'provided' => array(
0 => '1.0',
),
),
'psy/psysh' => array( 'psy/psysh' => array(
'pretty_version' => 'v0.11.10', 'pretty_version' => 'v0.11.10',
'version' => '0.11.10.0', 'version' => '0.11.10.0',
@@ -1757,12 +1667,12 @@
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'torann/geoip' => array( 'torann/geoip' => array(
'pretty_version' => '1.2.1', 'pretty_version' => '3.0.2',
'version' => '1.2.1.0', 'version' => '3.0.2.0',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../torann/geoip', 'install_path' => __DIR__ . '/../torann/geoip',
'aliases' => array(), 'aliases' => array(),
'reference' => '15c7cb3d2edcfbfd7e8cd6f435defc2352df40d2', 'reference' => 'f16d5df66ecb6ba4ffaef52abef519fbc19596d3',
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'tymon/jwt-auth' => array( 'tymon/jwt-auth' => array(
@@ -1784,12 +1694,12 @@
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'vlucas/phpdotenv' => array( 'vlucas/phpdotenv' => array(
'pretty_version' => 'v4.3.0', 'pretty_version' => 'v5.5.0',
'version' => '4.3.0.0', 'version' => '5.5.0.0',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../vlucas/phpdotenv', 'install_path' => __DIR__ . '/../vlucas/phpdotenv',
'aliases' => array(), 'aliases' => array(),
'reference' => '67a491df68208bef8c37092db11fa3885008efcf', 'reference' => '1a7ea2afc49c3ee6d87061f5a233e3a035d0eae7',
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'voku/portable-ascii' => array( 'voku/portable-ascii' => array(
@@ -1817,15 +1727,15 @@
'install_path' => __DIR__ . '/../webmozart/assert', 'install_path' => __DIR__ . '/../webmozart/assert',
'aliases' => array(), 'aliases' => array(),
'reference' => '11cb2199493b2f8a3b53e7f19068fc6aac760991', 'reference' => '11cb2199493b2f8a3b53e7f19068fc6aac760991',
'dev_requirement' => true, 'dev_requirement' => false,
), ),
'yajra/laravel-datatables-oracle' => array( 'yajra/laravel-datatables-oracle' => array(
'pretty_version' => 'v9.10.0', 'pretty_version' => 'v9.21.2',
'version' => '9.10.0.0', 'version' => '9.21.2.0',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../yajra/laravel-datatables-oracle', 'install_path' => __DIR__ . '/../yajra/laravel-datatables-oracle',
'aliases' => array(), 'aliases' => array(),
'reference' => 'b0b9e2c37b5a17ca35bb2c6d3927bf6176393229', 'reference' => 'a7fd01f06282923e9c63fa27fe6b391e21dc321a',
'dev_requirement' => false, 'dev_requirement' => false,
), ),
), ),

View File

@@ -1,16 +0,0 @@
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
indent_style = space
indent_size = 4
trim_trailing_whitespace = true
[*.md]
trim_trailing_whitespace = false
[*.yml]
indent_style = space
indent_size = 2

View File

@@ -1,5 +1,149 @@
# Change Log # Change Log
## [3.3.2] - 2022-09-19
### Added
- N/A
### Changed
- Skip some daylight savings time tests for PHP 8.1 daylight savings time weirdness (#146)
### Fixed
- Changed string interpolations to work better with PHP 8.2 (#142)
## [3.3.1] - 2022-01-18
### Added
- N/A
### Changed
- N/A
### Fixed
- Fixed issue when timezones had no transition, which can occur over very short timespans (#134)
## [3.3.0] - 2022-01-13
### Added
- Added ability to register your own expression aliases (#132)
### Changed
- Changed how Day of Week and Day of Month resolve when one or the other is `*` or `?`
### Fixed
- PHPStan should no longer error out
## [3.2.4] - 2022-01-12
### Added
- N/A
### Changed
- Changed how Day of Week increment/decrement to help with DST changes (#131)
### Fixed
- N/A
## [3.2.3] - 2022-01-05
### Added
- N/A
### Changed
- Changed how minutes and hours increment/decrement to help with DST changes (#131)
### Fixed
- N/A
## [3.2.2] - 2022-01-05
### Added
- N/A
### Changed
- Marked some methods `@internal` (#124)
### Fixed
- Fixed issue with small ranges and large steps that caused an error with `range()` (#88)
- Fixed issue where wraparound logic incorrectly considered high bound on range (#89)
## [3.2.1] - 2022-01-04
### Added
- N/A
### Changed
- Added PHP 8.1 to testing (#125)
### Fixed
- Allow better mixture of ranges, steps, and lists (#122)
- Fixed return order when multiple dates are requested and inverted (#121)
- Better handling over DST (#115)
- Fixed PHPStan tests (#130)
## [3.2.0] - 2022-01-04
### Added
- Added alias for `@midnight` (#117)
### Changed
- Improved testing for instance of field in tests (#105)
- Optimization for determining multiple run dates (#75)
- `CronExpression` properties changed from private to protected (#106)
### Fixed
- N/A
## [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`, `@midnight` - Run once a day, midnight - `0 0 * * *`
* `@hourly` - Run once an hour, first minute - `0 * * * *`
Requirements Requirements
============ ============
- PHP 7.0+ - PHP 7.2+
- 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.0"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "^6.4|^7.0|^8.0|^9.0" "phpstan/phpstan": "^1.0",
"phpunit/phpunit": "^7.0|^8.0|^9.0",
"phpstan/phpstan-webmozart-assert": "^1.0",
"phpstan/extension-installer": "^1.0"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {
@@ -29,12 +28,20 @@
}, },
"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 analyze",
"test": "phpunit"
},
"config": {
"allow-plugins": {
"ocramius/package-versions": true,
"phpstan/extension-installer": true
} }
} }
} }

View File

@@ -0,0 +1,15 @@
parameters:
checkMissingIterableValueType: false
ignoreErrors:
- '#Call to an undefined method DateTimeInterface::add\(\)#'
- '#Call to an undefined method DateTimeInterface::modify\(\)#'
- '#Call to an undefined method DateTimeInterface::setDate\(\)#'
- '#Call to an undefined method DateTimeInterface::setTime\(\)#'
- '#Call to an undefined method DateTimeInterface::setTimezone\(\)#'
- '#Call to an undefined method DateTimeInterface::sub\(\)#'
level: max
paths:
- src/

View File

@@ -1,33 +1,41 @@
<?php <?php
declare(strict_types=1);
namespace Cron; namespace Cron;
use DateTimeInterface;
/** /**
* 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 +48,107 @@ 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 * @internal
* @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.
* *
* @internal
* @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.
* *
* @internal
* @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 * @internal
* @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 * @internal
* @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 = (int) $rangeChunks[0];
$rangeEnd = isset($rangeChunks[1]) ? $rangeChunks[1] : $rangeStart; $rangeEnd = $rangeChunks[1] ?? $rangeStart;
$rangeEnd = (int) $rangeEnd;
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');
@@ -141,82 +158,93 @@ abstract class AbstractField implements FieldInterface
throw new \OutOfRangeException('Invalid range end requested'); throw new \OutOfRangeException('Invalid range end requested');
} }
// 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
if ($step >= $this->rangeEnd) { // slightly differently than smaller steps
$thisRange = [$this->fullRange[$step % count($this->fullRange)]];
// UPDATE - This is actually false. The C implementation will allow a
// larger step as valid syntax, it never wraps around. It will stop
// once it hits the end. Unfortunately this means in future versions
// we will not wrap around. However, because the logic exists today
// per the above documentation, fixing the bug from #89
if ($step > $this->rangeEnd) {
$thisRange = [$this->fullRange[$step % \count($this->fullRange)]];
} else { } else {
$thisRange = range($rangeStart, $rangeEnd, $step); if ($step > ($rangeEnd - $rangeStart)) {
$thisRange[$rangeStart] = (int) $rangeStart;
} else {
$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 +253,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 +268,29 @@ abstract class AbstractField implements FieldInterface
return true; return true;
} }
if (strpos($value, '/') !== false) {
list($range, $step) = explode('/', $value);
return $this->validate($range) && filter_var($step, FILTER_VALIDATE_INT);
}
// Validate each chunk of a list individually // 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, '/')) {
[$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);
}
if (false !== strpos($value, '-')) {
if (substr_count($value, '-') > 1) { if (substr_count($value, '-') > 1) {
return false; return false;
} }
@@ -263,7 +299,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 +310,37 @@ 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);
}
protected function timezoneSafeModify(DateTimeInterface $dt, string $modification): DateTimeInterface
{
$timezone = $dt->getTimezone();
$dt = $dt->setTimezone(new \DateTimeZone("UTC"));
$dt = $dt->modify($modification);
$dt = $dt->setTimezone($timezone);
return $dt;
}
protected function setTimeHour(DateTimeInterface $date, bool $invert, int $originalTimestamp): DateTimeInterface
{
$date = $date->setTime((int)$date->format('H'), ($invert ? 59 : 0));
// setTime caused the offset to change, moving time in the wrong direction
$actualTimestamp = $date->format('U');
if ((! $invert) && ($actualTimestamp <= $originalTimestamp)) {
$date = $this->timezoneSafeModify($date, "+1 hour");
} elseif ($invert && ($actualTimestamp >= $originalTimestamp)) {
$date = $this->timezoneSafeModify($date, "-1 hour");
}
return $date;
} }
} }

View File

@@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace Cron; namespace Cron;
use DateTime; use DateTime;
@@ -8,7 +10,9 @@ use DateTimeInterface;
use DateTimeZone; use DateTimeZone;
use Exception; use Exception;
use InvalidArgumentException; use InvalidArgumentException;
use LogicException;
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,83 +24,147 @@ 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 */
* @var array CRON expression parts public const YEAR = 5;
*/
private $cronParts;
/** public const MAPPINGS = [
* @var FieldFactory CRON field factory
*/
private $fieldFactory;
/**
* @var int Max iteration count when searching for next run date
*/
private $maxIterationCount = 1000;
/**
* @var array Order in which to test of cron parts
*/
private static $order = array(self::YEAR, self::MONTH, self::DAY, self::WEEKDAY, self::HOUR, self::MINUTE);
/**
* Factory method to create a new CronExpression.
*
* @param string $expression The CRON expression to create. There are
* several special predefined values which can be used to substitute the
* CRON expression:
*
* `@yearly`, `@annually` - Run once a year, midnight, Jan. 1 - 0 0 1 1 *
* `@monthly` - Run once a month, midnight, first of month - 0 0 1 * *
* `@weekly` - Run once a week, midnight on Sun - 0 0 * * 0
* `@daily` - Run once a day, midnight - 0 0 * * *
* `@hourly` - Run once an hour, first minute - 0 * * * *
* @param FieldFactory|null $fieldFactory Field factory to use
*
* @return CronExpression
*/
public static function factory($expression, FieldFactory $fieldFactory = null)
{
$mappings = array(
'@yearly' => '0 0 1 1 *', '@yearly' => '0 0 1 1 *',
'@annually' => '0 0 1 1 *', '@annually' => '0 0 1 1 *',
'@monthly' => '0 0 1 * *', '@monthly' => '0 0 1 * *',
'@weekly' => '0 0 * * 0', '@weekly' => '0 0 * * 0',
'@daily' => '0 0 * * *', '@daily' => '0 0 * * *',
'@hourly' => '0 * * * *' '@midnight' => '0 0 * * *',
); '@hourly' => '0 * * * *',
];
if (isset($mappings[$expression])) { /**
$expression = $mappings[$expression]; * @var array CRON expression parts
*/
protected $cronParts;
/**
* @var FieldFactoryInterface CRON field factory
*/
protected $fieldFactory;
/**
* @var int Max iteration count when searching for next run date
*/
protected $maxIterationCount = 1000;
/**
* @var array Order in which to test of cron parts
*/
protected static $order = [
self::YEAR,
self::MONTH,
self::DAY,
self::WEEKDAY,
self::HOUR,
self::MINUTE,
];
/**
* @var array<string, string>
*/
private static $registeredAliases = self::MAPPINGS;
/**
* Registered a user defined CRON Expression Alias.
*
* @throws LogicException If the expression or the alias name are invalid
* or if the alias is already registered.
*/
public static function registerAlias(string $alias, string $expression): void
{
try {
new self($expression);
} catch (InvalidArgumentException $exception) {
throw new LogicException("The expression `$expression` is invalid", 0, $exception);
} }
return new static($expression, $fieldFactory ?: new FieldFactory()); $shortcut = strtolower($alias);
if (1 !== preg_match('/^@\w+$/', $shortcut)) {
throw new LogicException("The alias `$alias` is invalid. It must start with an `@` character and contain alphanumeric (letters, numbers, regardless of case) plus underscore (_).");
}
if (isset(self::$registeredAliases[$shortcut])) {
throw new LogicException("The alias `$alias` is already registered.");
}
self::$registeredAliases[$shortcut] = $expression;
}
/**
* Unregistered a user defined CRON Expression Alias.
*
* @throws LogicException If the user tries to unregister a built-in alias
*/
public static function unregisterAlias(string $alias): bool
{
$shortcut = strtolower($alias);
if (isset(self::MAPPINGS[$shortcut])) {
throw new LogicException("The alias `$alias` is a built-in alias; it can not be unregistered.");
}
if (!isset(self::$registeredAliases[$shortcut])) {
return false;
}
unset(self::$registeredAliases[$shortcut]);
return true;
}
/**
* Tells whether a CRON Expression alias is registered.
*/
public static function supportsAlias(string $alias): bool
{
return isset(self::$registeredAliases[strtolower($alias)]);
}
/**
* Returns all registered aliases as an associated array where the aliases are the key
* and their associated expressions are the values.
*
* @return array<string, string>
*/
public static function getAliases(): array
{
return self::$registeredAliases;
}
/**
* @deprecated since version 3.0.2, use __construct instead.
*/
public static function factory(string $expression, FieldFactoryInterface $fieldFactory = null): CronExpression
{
/** @phpstan-ignore-next-line */
return new static($expression, $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 +173,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::$registeredAliases[$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 +216,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 +239,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 +267,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 +286,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,48 +310,80 @@ 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(); $timeZone = $this->determineTimeZone($currentTime, $timeZone);
for ($i = 0; $i < max(0, $total); $i++) {
if ('now' === $currentTime) {
$currentTime = new DateTime();
} elseif ($currentTime instanceof DateTime) {
$currentTime = clone $currentTime;
} elseif ($currentTime instanceof DateTimeImmutable) {
$currentTime = DateTime::createFromFormat('U', $currentTime->format('U'));
} elseif (\is_string($currentTime)) {
$currentTime = new DateTime($currentTime);
}
Assert::isInstanceOf($currentTime, DateTime::class);
$currentTime->setTimezone(new DateTimeZone($timeZone));
$matches = [];
for ($i = 0; $i < $total; ++$i) {
try { try {
$matches[] = $this->getRunDate($currentTime, $i, $invert, $allowCurrentDate, $timeZone); $result = $this->getRunDate($currentTime, 0, $invert, $allowCurrentDate, $timeZone);
} catch (RuntimeException $e) { } catch (RuntimeException $e) {
break; break;
} }
$allowCurrentDate = false;
$currentTime = clone $result;
$matches[] = $result;
} }
return $matches; return $matches;
} }
/** /**
* 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 +396,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 +424,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 +446,26 @@ 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));
// Workaround for setTime causing an offset change: https://bugs.php.net/bug.php?id=81074
$currentDate = DateTime::createFromFormat("!Y-m-d H:iO", $currentDate->format("Y-m-d H:iP"), $currentDate->getTimezone());
if ($currentDate === false) {
throw new \RuntimeException('Unable to create date from format');
}
$currentDate->setTimezone(new DateTimeZone($timeZone));
$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 +475,49 @@ 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[self::DAY]) && isset($parts[self::WEEKDAY])) {
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);
if ($parts[self::DAY] === '?' || $parts[self::DAY] === '*') {
$domRunDates = [];
}
if ($parts[self::WEEKDAY] === '?' || $parts[self::WEEKDAY] === '*') {
$dowRunDates = [];
}
$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');
});
if ($invert) {
$combined = array_reverse($combined);
}
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, $invert);
} 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, $invert)) {
$satisfied = true; $satisfied = true;
break; break;
} }
} }
@@ -372,13 +526,14 @@ 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(self::MINUTE)->increment($nextRun, $invert, $parts[self::MINUTE] ?? null);
continue; continue;
} }
@@ -393,19 +548,19 @@ 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();
} }
return date_default_timezone_get(); return date_default_timezone_get();

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,81 +62,93 @@ 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 $invert): 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 ($wPosition = strpos($value, 'W')) {
// Parse the target day // Parse the target day
$targetDay = substr($value, 0, strpos($value, 'W')); $targetDay = (int) substr($value, 0, $wPosition);
// 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( $nearest = self::getNearestWeekday(
$date->format('Y'), (int) $date->format('Y'),
$date->format('m'), (int) $date->format('m'),
$targetDay $targetDay
)->format('j'); );
if ($nearest) {
return $date->format('j') === $nearest->format('j');
} }
return $this->isSatisfied($date->format('d'), $value); throw new \RuntimeException('Unable to return nearest weekday');
}
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->add(new \DateInterval('P1D'));
$date = $date->setTime(0, 0);
} else { } else {
$date = $date->modify('next day')->setTime(0, 0); $date = $date->sub(new \DateInterval('P1D'));
$date = $date->setTime(23, 59);
} }
return $this; return $this;
} }
/** /**
* @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,13 +1,14 @@
<?php <?php
declare(strict_types=1);
namespace Cron; namespace Cron;
use DateTime;
use DateTimeInterface; 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 +23,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 +38,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'];
@@ -52,42 +53,33 @@ class DayOfWeekField extends AbstractField
/** /**
* @inheritDoc * @inheritDoc
*
* @param \DateTime|\DateTimeImmutable $date
*/ */
public function isSatisfiedBy(DateTimeInterface $date, $value) public function isSatisfiedBy(DateTimeInterface $date, $value, bool $invert): 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 ($lPosition = strpos($value, 'L')) {
$weekday = (int) $this->convertLiterals(substr($value, 0, strpos($value, 'L'))); $weekday = $this->convertLiterals(substr($value, 0, $lPosition));
$weekday %= 7; $weekday %= 7;
$tdate = clone $date; $daysInMonth = (int) $date->format('t');
$tdate = $tdate->setDate($currentYear, $currentMonth, $lastDayOfMonth); $remainingDaysInMonth = $daysInMonth - (int) $date->format('d');
while ($tdate->format('w') != $weekday) { return (($weekday === (int) $date->format('w')) && ($remainingDaysInMonth < 7));
$tdateClone = new DateTime();
$tdate = $tdateClone
->setTimezone($tdate->getTimezone())
->setDate($currentYear, $currentMonth, --$lastDayOfMonth);
}
return $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 +88,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 +113,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,57 +121,63 @@ 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);
} }
/** /**
* @inheritDoc * @inheritDoc
*
* @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->add(new \DateInterval('P1D'));
$date = $date->setTime(0, 0);
} else { } else {
$date = $date->modify('+1 day')->setTime(0, 0, 0); $date = $date->sub(new \DateInterval('P1D'));
$date = $date->setTime(23, 59);
} }
return $this; return $this;
} }
/** /**
* @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,46 @@
<?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.
* *
* @internal
* @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 $invert): 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 * @internal
* @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,83 +1,210 @@
<?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 * @var array|null Transitions returned by DateTimeZone::getTransitions()
*/ */
public function isSatisfiedBy(DateTimeInterface $date, $value) protected $transitions = [];
/**
* @var int|null Timestamp of the start of the transitions range
*/
protected $transitionsStart = null;
/**
* @var int|null Timestamp of the end of the transitions range
*/
protected $transitionsEnd = null;
/**
* {@inheritdoc}
*/
public function isSatisfiedBy(DateTimeInterface $date, $value, bool $invert): bool
{ {
if ($value == '?') { $checkValue = (int) $date->format('H');
return true; $retval = $this->isSatisfied($checkValue, $value);
if ($retval) {
return $retval;
} }
return $this->isSatisfied($date->format('H'), $value); // Are we on the edge of a transition
$lastTransition = $this->getPastTransition($date);
if (($lastTransition !== null) && ($lastTransition["ts"] > ((int) $date->format('U') - 3600))) {
$dtLastOffset = clone $date;
$this->timezoneSafeModify($dtLastOffset, "-1 hour");
$lastOffset = $dtLastOffset->getOffset();
$dtNextOffset = clone $date;
$this->timezoneSafeModify($dtNextOffset, "+1 hour");
$nextOffset = $dtNextOffset->getOffset();
$offsetChange = $nextOffset - $lastOffset;
if ($offsetChange >= 3600) {
$checkValue -= 1;
return $this->isSatisfied($checkValue, $value);
}
if ((! $invert) && ($offsetChange <= -3600)) {
$checkValue += 1;
return $this->isSatisfied($checkValue, $value);
}
}
return $retval;
}
public function getPastTransition(DateTimeInterface $date): ?array
{
$currentTimestamp = (int) $date->format('U');
if (
($this->transitions === null)
|| ($this->transitionsStart < ($currentTimestamp + 86400))
|| ($this->transitionsEnd > ($currentTimestamp - 86400))
) {
// We start a day before current time so we can differentiate between the first transition entry
// and a change that happens now
$dtLimitStart = clone $date;
$dtLimitStart = $dtLimitStart->modify("-12 months");
$dtLimitEnd = clone $date;
$dtLimitEnd = $dtLimitEnd->modify('+12 months');
$this->transitions = $date->getTimezone()->getTransitions(
$dtLimitStart->getTimestamp(),
$dtLimitEnd->getTimestamp()
);
if (empty($this->transitions)) {
return null;
}
$this->transitionsStart = $dtLimitStart->getTimestamp();
$this->transitionsEnd = $dtLimitEnd->getTimestamp();
}
$nextTransition = null;
foreach ($this->transitions as $transition) {
if ($transition["ts"] > $currentTimestamp) {
continue;
}
if (($nextTransition !== null) && ($transition["ts"] < $nextTransition["ts"])) {
continue;
}
$nextTransition = $transition;
}
return ($nextTransition ?? null);
} }
/** /**
* {@inheritDoc} * {@inheritdoc}
* *
* @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
{ {
$originalTimestamp = (int) $date->format('U');
// 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(); if ($invert) {
$date = $date->setTimezone(new DateTimeZone('UTC')); $date = $date->sub(new \DateInterval('PT1H'));
$date = $date->modify(($invert ? '-' : '+') . '1 hour'); } else {
$date = $date->setTimezone($timezone); $date = $date->add(new \DateInterval('PT1H'));
}
$date = $date->setTime($date->format('H'), $invert ? 59 : 0); $date = $this->setTimeHour($date, $invert, $originalTimestamp);
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 = (int) $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]; $target = (int) $hours[$position];
if ((!$invert && $date->format('H') >= $hour) || ($invert && $date->format('H') <= $hour)) { $originalHour = (int)$date->format('H');
$date = $date->modify(($invert ? '-' : '+') . '1 day');
$date = $date->setTime($invert ? 23 : 0, $invert ? 59 : 0); $originalDay = (int)$date->format('d');
$previousOffset = $date->getOffset();
if (! $invert) {
if ($originalHour >= $target) {
$distance = 24 - $originalHour;
$date = $this->timezoneSafeModify($date, "+{$distance} hours");
$actualDay = (int)$date->format('d');
$actualHour = (int)$date->format('H');
if (($actualDay !== ($originalDay + 1)) && ($actualHour !== 0)) {
$offsetChange = ($previousOffset - $date->getOffset());
$date = $this->timezoneSafeModify($date, "+{$offsetChange} seconds");
} }
else {
$date = $date->setTime($hour, $invert ? 59 : 0); $originalHour = (int)$date->format('H');
}
$distance = $target - $originalHour;
$date = $this->timezoneSafeModify($date, "+{$distance} hours");
} else {
if ($originalHour <= $target) {
$distance = ($originalHour + 1);
$date = $this->timezoneSafeModify($date, "-" . $distance . " hours");
$actualDay = (int)$date->format('d');
$actualHour = (int)$date->format('H');
if (($actualDay !== ($originalDay - 1)) && ($actualHour !== 23)) {
$offsetChange = ($previousOffset - $date->getOffset());
$date = $this->timezoneSafeModify($date, "+{$offsetChange} seconds");
}
$originalHour = (int)$date->format('H');
}
$distance = $originalHour - $target;
$date = $this->timezoneSafeModify($date, "-{$distance} hours");
}
$date = $this->setTimeHour($date, $invert, $originalTimestamp);
$actualHour = (int)$date->format('H');
if ($invert && ($actualHour === ($target - 1) || (($actualHour === 23) && ($target === 0)))) {
$date = $this->timezoneSafeModify($date, "+1 hour");
} }
return $this; return $this;

View File

@@ -1,73 +1,94 @@
<?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 $invert):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 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 = $this->timezoneSafeModify($date, ($invert ? "-" : "+") ."1 minute");
return $this; return $this;
} }
$parts = strpos($parts, ',') !== false ? explode(',', $parts) : array($parts); $current_minute = (int) $date->format('i');
$minutes = array();
$parts = false !== strpos($parts, ',') ? explode(',', $parts) : [$parts];
$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'); $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;
} }
} }
} }
if ((!$invert && $current_minute >= $minutes[$position]) || ($invert && $current_minute <= $minutes[$position])) { $target = (int) $minutes[$position];
$date = $date->modify(($invert ? '-' : '+') . '1 hour'); $originalMinute = (int) $date->format("i");
$date = $date->setTime($date->format('H'), $invert ? 59 : 0);
if (! $invert) {
if ($originalMinute >= $target) {
$distance = 60 - $originalMinute;
$date = $this->timezoneSafeModify($date, "+{$distance} minutes");
$originalMinute = (int) $date->format("i");
} }
else {
$date = $date->setTime($date->format('H'), $minutes[$position]); $distance = $target - $originalMinute;
$date = $this->timezoneSafeModify($date, "+{$distance} minutes");
} else {
if ($originalMinute <= $target) {
$distance = ($originalMinute + 1);
$date = $this->timezoneSafeModify($date, "-{$distance} minutes");
$originalMinute = (int) $date->format("i");
}
$distance = $originalMinute - $target;
$date = $this->timezoneSafeModify($date, "-{$distance} minutes");
} }
return $this; return $this;

View File

@@ -1,59 +1,61 @@
<?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 $invert): bool
{ {
if ($value == '?') { if ($value === '?') {
return true; return true;
} }
$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('first day of next month');
$date = $date->setTime(0, 0);
} else { } else {
$date = $date->modify('first day of next month')->setTime(0, 0); $date = $date->modify('last day of previous month');
$date = $date->setTime(23, 59);
} }
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

@@ -1,14 +0,0 @@
---
name: Laravel 9 Updates
about: Inform about Laravel 9 changes
title: ''
labels: ''
assignees: ''
---
<!--
NOTE: Laravel has incorporated this package into the core of Laravel as of Laravel 9.
Do not use this package in Laravel 9. Details here: https://github.com/fideloper/TrustedProxy/issues/152
-->

View File

@@ -1,51 +0,0 @@
# This is a basic workflow to help you get started with Actions
name: Tests
# Controls when the action will run.
on:
push:
pull_request:
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "build"
run_tests:
# The type of runner that the job will run on
runs-on: ubuntu-latest
strategy:
fail-fast: true
matrix:
php: [7.2, 7.3, 7.4, 8.0, 8.1]
name: PHP ${{ matrix.php }}
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v2
- name: Checkout code
uses: actions/checkout@v2
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite
tools: composer:v2
coverage: none
- name: Install dependencies
uses: nick-invision/retry@v1
with:
timeout_minutes: 5
max_attempts: 5
command: composer update --prefer-dist --no-interaction --no-progress
- name: Execute tests
run: vendor/bin/phpunit --verbose

View File

@@ -1,35 +0,0 @@
{
"name": "fideloper/proxy",
"description": "Set trusted proxies for Laravel",
"keywords": ["proxy", "trusted proxy", "load balancing"],
"license": "MIT",
"authors": [
{
"name": "Chris Fidao",
"email": "fideloper@gmail.com"
}
],
"require": {
"php": ">=5.4.0",
"illuminate/contracts": "^5.0|^6.0|^7.0|^8.0|^9.0"
},
"require-dev": {
"illuminate/http": "^5.0|^6.0|^7.0|^8.0|^9.0",
"mockery/mockery": "^1.0",
"phpunit/phpunit": "^8.5.8|^9.3.3"
},
"autoload": {
"psr-4": {
"Fideloper\\Proxy\\": "src/"
}
},
"extra": {
"laravel": {
"providers": [
"Fideloper\\Proxy\\TrustedProxyServiceProvider"
]
}
},
"minimum-stability": "dev",
"prefer-stable": true
}

View File

@@ -1,46 +0,0 @@
<?php
return [
/*
* Set trusted proxy IP addresses.
*
* Both IPv4 and IPv6 addresses are
* supported, along with CIDR notation.
*
* The "*" character is syntactic sugar
* within TrustedProxy to trust any proxy
* that connects directly to your server,
* a requirement when you cannot know the address
* of your proxy (e.g. if using ELB or similar).
*
*/
'proxies' => null, // [<ip addresses>,], '*', '<ip addresses>,'
/*
* To trust one or more specific proxies that connect
* directly to your server, use an array or a string separated by comma of IP addresses:
*/
// 'proxies' => ['192.168.1.1'],
// 'proxies' => '192.168.1.1, 192.168.1.2',
/*
* Or, to trust all proxies that connect
* directly to your server, use a "*"
*/
// 'proxies' => '*',
/*
* Which headers to use to detect proxy related data (For, Host, Proto, Port)
*
* Options include:
*
* - All headers (see below) - Trust all x-forwarded-* headers
* - Illuminate\Http\Request::HEADER_FORWARDED - Use the FORWARDED header to establish trust
* - Illuminate\Http\Request::HEADER_X_FORWARDED_AWS_ELB - If you are using AWS Elastic Load Balancer
*
* @link https://symfony.com/doc/current/deployment/proxies.html
*/
'headers' => Illuminate\Http\Request::HEADER_X_FORWARDED_FOR | Illuminate\Http\Request::HEADER_X_FORWARDED_HOST | Illuminate\Http\Request::HEADER_X_FORWARDED_PORT | Illuminate\Http\Request::HEADER_X_FORWARDED_PROTO | Illuminate\Http\Request::HEADER_X_FORWARDED_AWS_ELB,
];

View File

@@ -1,41 +0,0 @@
<?php
namespace Fideloper\Proxy;
use Illuminate\Foundation\Application as LaravelApplication;
use Illuminate\Support\ServiceProvider;
use Laravel\Lumen\Application as LumenApplication;
class TrustedProxyServiceProvider extends ServiceProvider
{
/**
* Boot the service provider.
*
* @return void
*/
public function boot()
{
$source = realpath($raw = __DIR__.'/../config/trustedproxy.php') ?: $raw;
if ($this->app instanceof LaravelApplication && $this->app->runningInConsole()) {
$this->publishes([$source => config_path('trustedproxy.php')]);
} elseif ($this->app instanceof LumenApplication) {
$this->app->configure('trustedproxy');
}
if ($this->app instanceof LaravelApplication && ! $this->app->configurationIsCached()) {
$this->mergeConfigFrom($source, 'trustedproxy');
}
}
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
//
}
}

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