Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
921ba6811d | ||
|
|
906dd241b4 | ||
|
|
3f0cd2ad64 | ||
|
|
41420d1954 | ||
|
|
6e5a72b170 | ||
|
|
4b19e6aec8 | ||
|
|
58572cbc36 | ||
|
|
096d5766bf |
@@ -2,7 +2,11 @@
|
||||
|
||||
namespace sammo;
|
||||
|
||||
include "lib.php";
|
||||
include "func.php";
|
||||
require(__DIR__ . '/vendor/autoload.php');
|
||||
|
||||
|
||||
if (!class_exists('\\sammo\\RootDB')) {
|
||||
Json::dieWithReason('No DB');
|
||||
}
|
||||
|
||||
APIHelper::launch(dirname(__FILE__));
|
||||
+3
-1
@@ -28,7 +28,9 @@
|
||||
"catfan/medoo": "^1.5",
|
||||
"phan/phan": "*",
|
||||
"erusev/parsedown-extra": "^0.8.1",
|
||||
"nette/caching": "^3.0"
|
||||
"nette/caching": "^3.0",
|
||||
"illuminate/database": "^8.61",
|
||||
"illuminate/events": "^8.61"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
||||
Generated
+980
-2
@@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "2aeb036fc53a6fdc343bd2707d4697ee",
|
||||
"content-hash": "317938cff7b30806f4e385a70f4943fc",
|
||||
"packages": [
|
||||
{
|
||||
"name": "brandonwamboldt/utilphp",
|
||||
@@ -265,6 +265,101 @@
|
||||
],
|
||||
"time": "2021-07-31T17:03:58+00:00"
|
||||
},
|
||||
{
|
||||
"name": "doctrine/inflector",
|
||||
"version": "2.0.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/doctrine/inflector.git",
|
||||
"reference": "9cf661f4eb38f7c881cac67c75ea9b00bf97b210"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/doctrine/inflector/zipball/9cf661f4eb38f7c881cac67c75ea9b00bf97b210",
|
||||
"reference": "9cf661f4eb38f7c881cac67c75ea9b00bf97b210",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.2 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/coding-standard": "^7.0",
|
||||
"phpstan/phpstan": "^0.11",
|
||||
"phpstan/phpstan-phpunit": "^0.11",
|
||||
"phpstan/phpstan-strict-rules": "^0.11",
|
||||
"phpunit/phpunit": "^7.0 || ^8.0 || ^9.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Doctrine\\Inflector\\": "lib/Doctrine/Inflector"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Guilherme Blanco",
|
||||
"email": "guilhermeblanco@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Roman Borschel",
|
||||
"email": "roman@code-factory.org"
|
||||
},
|
||||
{
|
||||
"name": "Benjamin Eberlei",
|
||||
"email": "kontakt@beberlei.de"
|
||||
},
|
||||
{
|
||||
"name": "Jonathan Wage",
|
||||
"email": "jonwage@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Johannes Schmitt",
|
||||
"email": "schmittjoh@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "PHP Doctrine Inflector is a small library that can perform string manipulations with regard to upper/lowercase and singular/plural forms of words.",
|
||||
"homepage": "https://www.doctrine-project.org/projects/inflector.html",
|
||||
"keywords": [
|
||||
"inflection",
|
||||
"inflector",
|
||||
"lowercase",
|
||||
"manipulation",
|
||||
"php",
|
||||
"plural",
|
||||
"singular",
|
||||
"strings",
|
||||
"uppercase",
|
||||
"words"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/doctrine/inflector/issues",
|
||||
"source": "https://github.com/doctrine/inflector/tree/2.0.x"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://www.doctrine-project.org/sponsorship.html",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://www.patreon.com/phpdoctrine",
|
||||
"type": "patreon"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/doctrine%2Finflector",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2020-05-29T15:13:26+00:00"
|
||||
},
|
||||
{
|
||||
"name": "erusev/parsedown",
|
||||
"version": "1.7.4",
|
||||
@@ -707,6 +802,497 @@
|
||||
},
|
||||
"time": "2021-04-26T09:17:50+00:00"
|
||||
},
|
||||
{
|
||||
"name": "illuminate/bus",
|
||||
"version": "v8.61.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/illuminate/bus.git",
|
||||
"reference": "808097c0dfd893309bd77b00139586c516b965c9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/illuminate/bus/zipball/808097c0dfd893309bd77b00139586c516b965c9",
|
||||
"reference": "808097c0dfd893309bd77b00139586c516b965c9",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"illuminate/collections": "^8.0",
|
||||
"illuminate/contracts": "^8.0",
|
||||
"illuminate/pipeline": "^8.0",
|
||||
"illuminate/support": "^8.0",
|
||||
"php": "^7.3|^8.0"
|
||||
},
|
||||
"suggest": {
|
||||
"illuminate/queue": "Required to use closures when chaining jobs (^7.0)."
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "8.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Illuminate\\Bus\\": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Taylor Otwell",
|
||||
"email": "taylor@laravel.com"
|
||||
}
|
||||
],
|
||||
"description": "The Illuminate Bus package.",
|
||||
"homepage": "https://laravel.com",
|
||||
"support": {
|
||||
"issues": "https://github.com/laravel/framework/issues",
|
||||
"source": "https://github.com/laravel/framework"
|
||||
},
|
||||
"time": "2021-08-10T16:49:48+00:00"
|
||||
},
|
||||
{
|
||||
"name": "illuminate/collections",
|
||||
"version": "v8.61.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/illuminate/collections.git",
|
||||
"reference": "18fa841df912ec56849351dd6ca8928e8a98b69d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/illuminate/collections/zipball/18fa841df912ec56849351dd6ca8928e8a98b69d",
|
||||
"reference": "18fa841df912ec56849351dd6ca8928e8a98b69d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"illuminate/contracts": "^8.0",
|
||||
"illuminate/macroable": "^8.0",
|
||||
"php": "^7.3|^8.0"
|
||||
},
|
||||
"suggest": {
|
||||
"symfony/var-dumper": "Required to use the dump method (^5.1.4)."
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "8.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Illuminate\\Support\\": ""
|
||||
},
|
||||
"files": [
|
||||
"helpers.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Taylor Otwell",
|
||||
"email": "taylor@laravel.com"
|
||||
}
|
||||
],
|
||||
"description": "The Illuminate Collections package.",
|
||||
"homepage": "https://laravel.com",
|
||||
"support": {
|
||||
"issues": "https://github.com/laravel/framework/issues",
|
||||
"source": "https://github.com/laravel/framework"
|
||||
},
|
||||
"time": "2021-09-08T12:48:16+00:00"
|
||||
},
|
||||
{
|
||||
"name": "illuminate/container",
|
||||
"version": "v8.61.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/illuminate/container.git",
|
||||
"reference": "862b64ea4ab56e307a1676104a1b93295d347ad0"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/illuminate/container/zipball/862b64ea4ab56e307a1676104a1b93295d347ad0",
|
||||
"reference": "862b64ea4ab56e307a1676104a1b93295d347ad0",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"illuminate/contracts": "^8.0",
|
||||
"php": "^7.3|^8.0",
|
||||
"psr/container": "^1.0"
|
||||
},
|
||||
"provide": {
|
||||
"psr/container-implementation": "1.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "8.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Illuminate\\Container\\": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Taylor Otwell",
|
||||
"email": "taylor@laravel.com"
|
||||
}
|
||||
],
|
||||
"description": "The Illuminate Container package.",
|
||||
"homepage": "https://laravel.com",
|
||||
"support": {
|
||||
"issues": "https://github.com/laravel/framework/issues",
|
||||
"source": "https://github.com/laravel/framework"
|
||||
},
|
||||
"time": "2021-09-09T13:55:23+00:00"
|
||||
},
|
||||
{
|
||||
"name": "illuminate/contracts",
|
||||
"version": "v8.61.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/illuminate/contracts.git",
|
||||
"reference": "ab4bb4ec3b36905ccf972c84f9aaa2bdd1153913"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/illuminate/contracts/zipball/ab4bb4ec3b36905ccf972c84f9aaa2bdd1153913",
|
||||
"reference": "ab4bb4ec3b36905ccf972c84f9aaa2bdd1153913",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.3|^8.0",
|
||||
"psr/container": "^1.0",
|
||||
"psr/simple-cache": "^1.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "8.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Illuminate\\Contracts\\": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Taylor Otwell",
|
||||
"email": "taylor@laravel.com"
|
||||
}
|
||||
],
|
||||
"description": "The Illuminate Contracts package.",
|
||||
"homepage": "https://laravel.com",
|
||||
"support": {
|
||||
"issues": "https://github.com/laravel/framework/issues",
|
||||
"source": "https://github.com/laravel/framework"
|
||||
},
|
||||
"time": "2021-09-08T12:09:40+00:00"
|
||||
},
|
||||
{
|
||||
"name": "illuminate/database",
|
||||
"version": "v8.61.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/illuminate/database.git",
|
||||
"reference": "acc11d6839ddb3b694bc6585177fa5141b70c693"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/illuminate/database/zipball/acc11d6839ddb3b694bc6585177fa5141b70c693",
|
||||
"reference": "acc11d6839ddb3b694bc6585177fa5141b70c693",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-json": "*",
|
||||
"illuminate/collections": "^8.0",
|
||||
"illuminate/container": "^8.0",
|
||||
"illuminate/contracts": "^8.0",
|
||||
"illuminate/macroable": "^8.0",
|
||||
"illuminate/support": "^8.0",
|
||||
"php": "^7.3|^8.0",
|
||||
"symfony/console": "^5.1.4"
|
||||
},
|
||||
"suggest": {
|
||||
"doctrine/dbal": "Required to rename columns and drop SQLite columns (^2.6|^3.0).",
|
||||
"fakerphp/faker": "Required to use the eloquent factory builder (^1.9.1).",
|
||||
"illuminate/console": "Required to use the database commands (^8.0).",
|
||||
"illuminate/events": "Required to use the observers with Eloquent (^8.0).",
|
||||
"illuminate/filesystem": "Required to use the migrations (^8.0).",
|
||||
"illuminate/pagination": "Required to paginate the result set (^8.0).",
|
||||
"symfony/finder": "Required to use Eloquent model factories (^5.1.4)."
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "8.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Illuminate\\Database\\": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Taylor Otwell",
|
||||
"email": "taylor@laravel.com"
|
||||
}
|
||||
],
|
||||
"description": "The Illuminate Database package.",
|
||||
"homepage": "https://laravel.com",
|
||||
"keywords": [
|
||||
"database",
|
||||
"laravel",
|
||||
"orm",
|
||||
"sql"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/laravel/framework/issues",
|
||||
"source": "https://github.com/laravel/framework"
|
||||
},
|
||||
"time": "2021-09-13T18:43:43+00:00"
|
||||
},
|
||||
{
|
||||
"name": "illuminate/events",
|
||||
"version": "v8.61.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/illuminate/events.git",
|
||||
"reference": "7def78033f29cd0c0383513b27c291d233a7f90e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/illuminate/events/zipball/7def78033f29cd0c0383513b27c291d233a7f90e",
|
||||
"reference": "7def78033f29cd0c0383513b27c291d233a7f90e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"illuminate/bus": "^8.0",
|
||||
"illuminate/collections": "^8.0",
|
||||
"illuminate/container": "^8.0",
|
||||
"illuminate/contracts": "^8.0",
|
||||
"illuminate/macroable": "^8.0",
|
||||
"illuminate/support": "^8.0",
|
||||
"php": "^7.3|^8.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "8.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Illuminate\\Events\\": ""
|
||||
},
|
||||
"files": [
|
||||
"functions.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Taylor Otwell",
|
||||
"email": "taylor@laravel.com"
|
||||
}
|
||||
],
|
||||
"description": "The Illuminate Events package.",
|
||||
"homepage": "https://laravel.com",
|
||||
"support": {
|
||||
"issues": "https://github.com/laravel/framework/issues",
|
||||
"source": "https://github.com/laravel/framework"
|
||||
},
|
||||
"time": "2021-08-16T21:45:47+00:00"
|
||||
},
|
||||
{
|
||||
"name": "illuminate/macroable",
|
||||
"version": "v8.61.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/illuminate/macroable.git",
|
||||
"reference": "300aa13c086f25116b5f3cde3ca54ff5c822fb05"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/illuminate/macroable/zipball/300aa13c086f25116b5f3cde3ca54ff5c822fb05",
|
||||
"reference": "300aa13c086f25116b5f3cde3ca54ff5c822fb05",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.3|^8.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "8.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Illuminate\\Support\\": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Taylor Otwell",
|
||||
"email": "taylor@laravel.com"
|
||||
}
|
||||
],
|
||||
"description": "The Illuminate Macroable package.",
|
||||
"homepage": "https://laravel.com",
|
||||
"support": {
|
||||
"issues": "https://github.com/laravel/framework/issues",
|
||||
"source": "https://github.com/laravel/framework"
|
||||
},
|
||||
"time": "2020-10-27T15:20:30+00:00"
|
||||
},
|
||||
{
|
||||
"name": "illuminate/pipeline",
|
||||
"version": "v8.61.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/illuminate/pipeline.git",
|
||||
"reference": "23aeff5b26ae4aee3f370835c76bd0f4e93f71d2"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/illuminate/pipeline/zipball/23aeff5b26ae4aee3f370835c76bd0f4e93f71d2",
|
||||
"reference": "23aeff5b26ae4aee3f370835c76bd0f4e93f71d2",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"illuminate/contracts": "^8.0",
|
||||
"illuminate/support": "^8.0",
|
||||
"php": "^7.3|^8.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "8.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Illuminate\\Pipeline\\": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Taylor Otwell",
|
||||
"email": "taylor@laravel.com"
|
||||
}
|
||||
],
|
||||
"description": "The Illuminate Pipeline package.",
|
||||
"homepage": "https://laravel.com",
|
||||
"support": {
|
||||
"issues": "https://github.com/laravel/framework/issues",
|
||||
"source": "https://github.com/laravel/framework"
|
||||
},
|
||||
"time": "2021-03-26T18:39:16+00:00"
|
||||
},
|
||||
{
|
||||
"name": "illuminate/support",
|
||||
"version": "v8.61.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/illuminate/support.git",
|
||||
"reference": "b0a21c41163381dd9a5abbd68fe85ed7b4247d30"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/illuminate/support/zipball/b0a21c41163381dd9a5abbd68fe85ed7b4247d30",
|
||||
"reference": "b0a21c41163381dd9a5abbd68fe85ed7b4247d30",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"doctrine/inflector": "^1.4|^2.0",
|
||||
"ext-json": "*",
|
||||
"ext-mbstring": "*",
|
||||
"illuminate/collections": "^8.0",
|
||||
"illuminate/contracts": "^8.0",
|
||||
"illuminate/macroable": "^8.0",
|
||||
"nesbot/carbon": "^2.31",
|
||||
"php": "^7.3|^8.0",
|
||||
"voku/portable-ascii": "^1.4.8"
|
||||
},
|
||||
"conflict": {
|
||||
"tightenco/collect": "<5.5.33"
|
||||
},
|
||||
"suggest": {
|
||||
"illuminate/filesystem": "Required to use the composer class (^8.0).",
|
||||
"league/commonmark": "Required to use Str::markdown() and Stringable::markdown() (^1.3|^2.0).",
|
||||
"ramsey/uuid": "Required to use Str::uuid() (^4.0).",
|
||||
"symfony/process": "Required to use the composer class (^5.1.4).",
|
||||
"symfony/var-dumper": "Required to use the dd function (^5.1.4).",
|
||||
"vlucas/phpdotenv": "Required to use the Env class and env helper (^5.2)."
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "8.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Illuminate\\Support\\": ""
|
||||
},
|
||||
"files": [
|
||||
"helpers.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Taylor Otwell",
|
||||
"email": "taylor@laravel.com"
|
||||
}
|
||||
],
|
||||
"description": "The Illuminate Support package.",
|
||||
"homepage": "https://laravel.com",
|
||||
"support": {
|
||||
"issues": "https://github.com/laravel/framework/issues",
|
||||
"source": "https://github.com/laravel/framework"
|
||||
},
|
||||
"time": "2021-09-13T18:43:43+00:00"
|
||||
},
|
||||
{
|
||||
"name": "league/plates",
|
||||
"version": "v3.4.0",
|
||||
@@ -902,6 +1488,100 @@
|
||||
],
|
||||
"time": "2021-05-28T08:32:12+00:00"
|
||||
},
|
||||
{
|
||||
"name": "nesbot/carbon",
|
||||
"version": "2.53.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/briannesbitt/Carbon.git",
|
||||
"reference": "f4655858a784988f880c1b8c7feabbf02dfdf045"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/f4655858a784988f880c1b8c7feabbf02dfdf045",
|
||||
"reference": "f4655858a784988f880c1b8c7feabbf02dfdf045",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-json": "*",
|
||||
"php": "^7.1.8 || ^8.0",
|
||||
"symfony/polyfill-mbstring": "^1.0",
|
||||
"symfony/polyfill-php80": "^1.16",
|
||||
"symfony/translation": "^3.4 || ^4.0 || ^5.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/orm": "^2.7",
|
||||
"friendsofphp/php-cs-fixer": "^3.0",
|
||||
"kylekatarnls/multi-tester": "^2.0",
|
||||
"phpmd/phpmd": "^2.9",
|
||||
"phpstan/extension-installer": "^1.0",
|
||||
"phpstan/phpstan": "^0.12.54",
|
||||
"phpunit/phpunit": "^7.5.20 || ^8.5.14",
|
||||
"squizlabs/php_codesniffer": "^3.4"
|
||||
},
|
||||
"bin": [
|
||||
"bin/carbon"
|
||||
],
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-3.x": "3.x-dev",
|
||||
"dev-master": "2.x-dev"
|
||||
},
|
||||
"laravel": {
|
||||
"providers": [
|
||||
"Carbon\\Laravel\\ServiceProvider"
|
||||
]
|
||||
},
|
||||
"phpstan": {
|
||||
"includes": [
|
||||
"extension.neon"
|
||||
]
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Carbon\\": "src/Carbon/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Brian Nesbitt",
|
||||
"email": "brian@nesbot.com",
|
||||
"homepage": "https://markido.com"
|
||||
},
|
||||
{
|
||||
"name": "kylekatarnls",
|
||||
"homepage": "https://github.com/kylekatarnls"
|
||||
}
|
||||
],
|
||||
"description": "An API extension for DateTime that supports 281 different languages.",
|
||||
"homepage": "https://carbon.nesbot.com",
|
||||
"keywords": [
|
||||
"date",
|
||||
"datetime",
|
||||
"time"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/briannesbitt/Carbon/issues",
|
||||
"source": "https://github.com/briannesbitt/Carbon"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://opencollective.com/Carbon",
|
||||
"type": "open_collective"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/nesbot/carbon",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-09-06T09:29:23+00:00"
|
||||
},
|
||||
{
|
||||
"name": "netresearch/jsonmapper",
|
||||
"version": "v4.0.0",
|
||||
@@ -1684,6 +2364,57 @@
|
||||
},
|
||||
"time": "2021-05-03T11:20:27+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/simple-cache",
|
||||
"version": "1.0.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/simple-cache.git",
|
||||
"reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b",
|
||||
"reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Psr\\SimpleCache\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "http://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"description": "Common interfaces for simple caching",
|
||||
"keywords": [
|
||||
"cache",
|
||||
"caching",
|
||||
"psr",
|
||||
"psr-16",
|
||||
"simple-cache"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/php-fig/simple-cache/tree/master"
|
||||
},
|
||||
"time": "2017-10-23T01:57:42+00:00"
|
||||
},
|
||||
{
|
||||
"name": "ralouphie/getallheaders",
|
||||
"version": "3.0.3",
|
||||
@@ -2970,6 +3701,179 @@
|
||||
],
|
||||
"time": "2021-06-27T11:44:38+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/translation",
|
||||
"version": "v5.3.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/translation.git",
|
||||
"reference": "4d595a6d15fd3a2c67f6f31d14d15d3b7356d7a6"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/translation/zipball/4d595a6d15fd3a2c67f6f31d14d15d3b7356d7a6",
|
||||
"reference": "4d595a6d15fd3a2c67f6f31d14d15d3b7356d7a6",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.2.5",
|
||||
"symfony/deprecation-contracts": "^2.1",
|
||||
"symfony/polyfill-mbstring": "~1.0",
|
||||
"symfony/polyfill-php80": "^1.16",
|
||||
"symfony/translation-contracts": "^2.3"
|
||||
},
|
||||
"conflict": {
|
||||
"symfony/config": "<4.4",
|
||||
"symfony/dependency-injection": "<5.0",
|
||||
"symfony/http-kernel": "<5.0",
|
||||
"symfony/twig-bundle": "<5.0",
|
||||
"symfony/yaml": "<4.4"
|
||||
},
|
||||
"provide": {
|
||||
"symfony/translation-implementation": "2.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"psr/log": "^1|^2|^3",
|
||||
"symfony/config": "^4.4|^5.0",
|
||||
"symfony/console": "^4.4|^5.0",
|
||||
"symfony/dependency-injection": "^5.0",
|
||||
"symfony/finder": "^4.4|^5.0",
|
||||
"symfony/http-kernel": "^5.0",
|
||||
"symfony/intl": "^4.4|^5.0",
|
||||
"symfony/polyfill-intl-icu": "^1.21",
|
||||
"symfony/service-contracts": "^1.1.2|^2",
|
||||
"symfony/yaml": "^4.4|^5.0"
|
||||
},
|
||||
"suggest": {
|
||||
"psr/log-implementation": "To use logging capability in translator",
|
||||
"symfony/config": "",
|
||||
"symfony/yaml": ""
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"files": [
|
||||
"Resources/functions.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\Translation\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Provides tools to internationalize your application",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/translation/tree/v5.3.7"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-08-26T08:22:53+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/translation-contracts",
|
||||
"version": "v2.4.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/translation-contracts.git",
|
||||
"reference": "95c812666f3e91db75385749fe219c5e494c7f95"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/translation-contracts/zipball/95c812666f3e91db75385749fe219c5e494c7f95",
|
||||
"reference": "95c812666f3e91db75385749fe219c5e494c7f95",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.2.5"
|
||||
},
|
||||
"suggest": {
|
||||
"symfony/translation-implementation": ""
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "2.4-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/contracts",
|
||||
"url": "https://github.com/symfony/contracts"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Contracts\\Translation\\": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Nicolas Grekas",
|
||||
"email": "p@tchwork.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Generic abstractions related to translation",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"abstractions",
|
||||
"contracts",
|
||||
"decoupling",
|
||||
"interfaces",
|
||||
"interoperability",
|
||||
"standards"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/translation-contracts/tree/v2.4.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-03-23T23:28:01+00:00"
|
||||
},
|
||||
{
|
||||
"name": "tysonandre/var_representation_polyfill",
|
||||
"version": "0.0.2",
|
||||
@@ -3080,6 +3984,80 @@
|
||||
],
|
||||
"time": "2021-07-08T16:18:03+00:00"
|
||||
},
|
||||
{
|
||||
"name": "voku/portable-ascii",
|
||||
"version": "1.5.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/voku/portable-ascii.git",
|
||||
"reference": "80953678b19901e5165c56752d087fc11526017c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/voku/portable-ascii/zipball/80953678b19901e5165c56752d087fc11526017c",
|
||||
"reference": "80953678b19901e5165c56752d087fc11526017c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.0.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~6.0 || ~7.0 || ~9.0"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-intl": "Use Intl for transliterator_transliterate() support"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"voku\\": "src/voku/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Lars Moelleken",
|
||||
"homepage": "http://www.moelleken.org/"
|
||||
}
|
||||
],
|
||||
"description": "Portable ASCII library - performance optimized (ascii) string functions for php.",
|
||||
"homepage": "https://github.com/voku/portable-ascii",
|
||||
"keywords": [
|
||||
"ascii",
|
||||
"clean",
|
||||
"php"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/voku/portable-ascii/issues",
|
||||
"source": "https://github.com/voku/portable-ascii/tree/1.5.6"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://www.paypal.me/moelleken",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/voku",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://opencollective.com/portable-ascii",
|
||||
"type": "open_collective"
|
||||
},
|
||||
{
|
||||
"url": "https://www.patreon.com/voku",
|
||||
"type": "patreon"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/voku/portable-ascii",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2020-11-12T00:07:28+00:00"
|
||||
},
|
||||
{
|
||||
"name": "webmozart/assert",
|
||||
"version": "1.10.0",
|
||||
@@ -3203,7 +4181,7 @@
|
||||
"platform": [],
|
||||
"platform-dev": [],
|
||||
"platform-overrides": {
|
||||
"php": "7.3"
|
||||
"php": "7.4"
|
||||
},
|
||||
"plugin-api-version": "2.0.0"
|
||||
}
|
||||
|
||||
@@ -2,9 +2,15 @@
|
||||
|
||||
namespace sammo;
|
||||
|
||||
//https://hub.packtpub.com/eloquent-without-laravel/
|
||||
use Illuminate\Database\Capsule\Manager as Capsule;
|
||||
use Illuminate\Events\Dispatcher;
|
||||
use Illuminate\Container\Container;
|
||||
|
||||
class RootDB
|
||||
{
|
||||
private static $uDB = null;
|
||||
private static ?Capsule $uIlluminate = null;
|
||||
|
||||
private static $host = '_tK_host_';
|
||||
private static $user = '_tK_user_';
|
||||
@@ -12,6 +18,8 @@ class RootDB
|
||||
private static $dbName = '_tK_dbName_';
|
||||
private static $port = _tK_port_;
|
||||
private static $encoding = 'utf8mb4';
|
||||
private static $collation = 'utf8mb4_general_ci';
|
||||
|
||||
|
||||
private static $globalSalt = '_tK_globalSalt_';
|
||||
|
||||
@@ -19,6 +27,29 @@ class RootDB
|
||||
{
|
||||
}
|
||||
|
||||
public static function illuminate(): Capsule
|
||||
{
|
||||
if(self::$uIlluminate !== null){
|
||||
return self::$uIlluminate;
|
||||
}
|
||||
$capsule = new Capsule;
|
||||
|
||||
$capsule->addConnection([
|
||||
'driver' => 'mysql',
|
||||
'host' => self::$host,
|
||||
'database' => self::$dbName,
|
||||
'username' => self::$user,
|
||||
'password' => self::$password,
|
||||
'charset' => self::$encoding,
|
||||
'collation' => self::$collation,
|
||||
], 'root');
|
||||
|
||||
$capsule->setEventDispatcher(new Dispatcher(new Container));
|
||||
$capsule->bootEloquent();
|
||||
self::$uIlluminate = $capsule;
|
||||
return $capsule;
|
||||
}
|
||||
|
||||
/**
|
||||
* DB 객체 생성
|
||||
*
|
||||
|
||||
@@ -28,7 +28,7 @@ $scenarioList = (function(){
|
||||
|
||||
|
||||
|
||||
if($scenarioIdx !== null && key_exists($scenarioIdx, $scenarioList)){
|
||||
if($scenarioIdx && key_exists($scenarioIdx, $scenarioList[$seasonIdx]??[])){
|
||||
$searchScenarioName = $scenarioList[$seasonIdx][$scenarioIdx]['name'];
|
||||
$searchFilter = $db->sqleval('season = %i AND scenario = %i', $seasonIdx, $scenarioIdx);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace sammo;
|
||||
|
||||
class DB{
|
||||
//https://hub.packtpub.com/eloquent-without-laravel/
|
||||
use Illuminate\Database\Capsule\Manager as Capsule;
|
||||
use Illuminate\Events\Dispatcher;
|
||||
use Illuminate\Container\Container;
|
||||
|
||||
class DB
|
||||
{
|
||||
private static $uDB = null;
|
||||
private static ?Capsule $uIlluminate = null;
|
||||
|
||||
private static $host = '_tK_host_';
|
||||
private static $user = '_tK_user_';
|
||||
@@ -10,11 +18,36 @@ class DB{
|
||||
private static $dbName = '_tK_dbName_';
|
||||
private static $port = _tK_port_;
|
||||
private static $encoding = 'utf8mb4';
|
||||
private static $collation = 'utf8mb4_general_ci';
|
||||
|
||||
private static $prefix = '_tK_prefix_';
|
||||
|
||||
private function __construct(){
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
public static function illuminate(): Capsule
|
||||
{
|
||||
if(self::$uIlluminate !== null){
|
||||
return self::$uIlluminate;
|
||||
}
|
||||
$capsule = new Capsule;
|
||||
|
||||
$capsule->addConnection([
|
||||
'driver' => 'mysql',
|
||||
'host' => self::$host,
|
||||
'database' => self::$dbName,
|
||||
'username' => self::$user,
|
||||
'password' => self::$password,
|
||||
'charset' => self::$encoding,
|
||||
'collation' => self::$collation,
|
||||
]);
|
||||
|
||||
$capsule->setEventDispatcher(new Dispatcher(new Container));
|
||||
$capsule->setAsGlobal();
|
||||
$capsule->bootEloquent();
|
||||
self::$uIlluminate = $capsule;
|
||||
return $capsule;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -23,12 +56,14 @@ class DB{
|
||||
* @return \MeekroDB
|
||||
* @suppress PhanTypeMismatchProperty
|
||||
*/
|
||||
public static function db(){
|
||||
if(self::$uDB === null){
|
||||
self::$uDB = new \MeekroDB(self::$host,self::$user,self::$password,self::$dbName,self::$port,self::$encoding);
|
||||
public static function db()
|
||||
{
|
||||
if (self::$uDB === null) {
|
||||
self::$uDB = new \MeekroDB(self::$host, self::$user, self::$password, self::$dbName, self::$port, self::$encoding);
|
||||
self::$uDB->connect_options[MYSQLI_OPT_INT_AND_FLOAT_NATIVE] = true;
|
||||
|
||||
self::$uDB->error_handler= function(){};
|
||||
self::$uDB->error_handler = function () {
|
||||
};
|
||||
self::$uDB->throw_exception_on_error = true;
|
||||
self::$uDB->throw_exception_on_nonsql_error = true;
|
||||
}
|
||||
@@ -39,4 +74,4 @@ class DB{
|
||||
{
|
||||
return self::$prefix;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ $db = DB::db();
|
||||
$me = General::createGeneralObjFromDB($generalID);
|
||||
|
||||
|
||||
if($defence_train != $me->getVar('defence_train')){
|
||||
if($defence_train !== $me->getVar('defence_train')){
|
||||
if($defence_train == 999){
|
||||
$me->increaseVar('myset', -1);
|
||||
$me->setVar('defence_train', $defence_train);
|
||||
@@ -53,14 +53,8 @@ if($defence_train != $me->getVar('defence_train')){
|
||||
}
|
||||
|
||||
$me->setAuxVar('use_treatment', Util::valueFit($use_treatment, 10, 100));
|
||||
|
||||
if($use_auto_nation_turn != $me->getAuxVar('use_auto_nation_turn')){
|
||||
$me->setAuxVar('use_auto_nation_turn', $use_auto_nation_turn);
|
||||
}
|
||||
|
||||
if($me->getVar('tnmt') != $tnmt){
|
||||
$me->setVar('tnmt', $tnmt);
|
||||
}
|
||||
$me->setAuxVar('use_auto_nation_turn', $use_auto_nation_turn);
|
||||
$me->setVar('tnmt', $tnmt);
|
||||
|
||||
if($me->getNPCType() == 1 && $detachNPC){
|
||||
$turnterm = $gameStor->turnterm;
|
||||
|
||||
+69
-57
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
namespace sammo;
|
||||
|
||||
include "lib.php";
|
||||
@@ -21,18 +22,18 @@ $availableTypes = [
|
||||
'nationPolicy',
|
||||
];
|
||||
|
||||
if(!in_array($type, $availableTypes)){
|
||||
if (!in_array($type, $availableTypes)) {
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'올바른 타입이 아닙니다.',
|
||||
'result' => false,
|
||||
'reason' => '올바른 타입이 아닙니다.',
|
||||
]);
|
||||
}
|
||||
|
||||
$data = Json::decode($data);
|
||||
if(!$data || !is_array($data)){
|
||||
if (!$data || !is_array($data)) {
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'올바른 입력이 아닙니다.',
|
||||
'result' => false,
|
||||
'reason' => '올바른 입력이 아닙니다.',
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -44,94 +45,95 @@ $me = $db->queryFirstRow('SELECT no, name, npc, nation, city, officer_level, con
|
||||
$nationID = $me['nation'];
|
||||
if (!$nationID) {
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'국가에 소속되어있지 않습니다.',
|
||||
'result' => false,
|
||||
'reason' => '국가에 소속되어있지 않습니다.',
|
||||
]);
|
||||
}
|
||||
|
||||
$permission = checkSecretPermission($me);
|
||||
if ($permission < 3) {
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'권한이 부족합니다. 군주, 외교권자, 조언자가 아닙니다.'
|
||||
'result' => false,
|
||||
'reason' => '권한이 부족합니다. 군주, 외교권자, 조언자가 아닙니다.'
|
||||
]);
|
||||
}
|
||||
|
||||
function applyNationPolicy($policy, $nationID, $generalName):?string{
|
||||
function applyNationPolicy($policy, $nationID, $generalName): ?string
|
||||
{
|
||||
$db = DB::db();
|
||||
$nationStor = KVStorage::getStorage($db, $nationID, 'nation_env');
|
||||
|
||||
$defaultPolicy = AutorunNationPolicy::$defaultPolicy;
|
||||
$troopCache = null;
|
||||
foreach($db->queryFirstColumn('SELECT troop_leader FROM troop WHERE nation=%i',$nationID) as $troopID){
|
||||
foreach ($db->queryFirstColumn('SELECT troop_leader FROM troop WHERE nation=%i', $nationID) as $troopID) {
|
||||
$troopCache[$troopID] = 'Neutral';
|
||||
}
|
||||
$cityList = CityConst::all();
|
||||
$nationPolicyRoot = $nationStor->npc_nation_policy;
|
||||
$nationPolicy = $nationPolicyRoot['values']??[];
|
||||
foreach($policy as $key=>$val){
|
||||
$nationPolicy = $nationPolicyRoot['values'] ?? [];
|
||||
foreach ($policy as $key => $val) {
|
||||
|
||||
if($key === 'CombatForce'){
|
||||
if(!is_array($val)){
|
||||
return "{$key}는 올바른 정책값이 아닙니다.";
|
||||
if ($key === 'CombatForce') {
|
||||
if (!is_array($val)) {
|
||||
return "{$key}는 올바른 정책값이 아닙니다.";
|
||||
}
|
||||
foreach($val as $troopID=>$troopTarget){
|
||||
if(!key_exists($troopID, $troopCache)){
|
||||
foreach ($val as $troopID => $troopTarget) {
|
||||
if (!key_exists($troopID, $troopCache)) {
|
||||
return "{$troopID}는 국가의 부대가 아닙니다.";
|
||||
}
|
||||
if($troopCache[$troopID] != 'Neutral'){
|
||||
if ($troopCache[$troopID] != 'Neutral') {
|
||||
return "부대({$troopID}는 하나의 역할만 지정할 수 있습니다.";
|
||||
}
|
||||
if(!is_array($troopTarget) || count($troopTarget)!=2){
|
||||
if (!is_array($troopTarget) || count($troopTarget) != 2) {
|
||||
return "{$troopID}의 입력양식이 올바르지 않습니다.";
|
||||
}
|
||||
[$fromCity, $toCity] = $troopCache;
|
||||
if(!key_exists($fromCity, $cityList) || !key_exists($toCity, $cityList)){
|
||||
if (!key_exists($fromCity, $cityList) || !key_exists($toCity, $cityList)) {
|
||||
return "{$troopID}의 도시 {$fromCity}, {$toCity}가 올바른 도시 번호가 아닙니다.";
|
||||
}
|
||||
$troopCache[$troopID]=$key;
|
||||
$troopCache[$troopID] = $key;
|
||||
}
|
||||
$nationPolicy[$key]=$val;
|
||||
$nationPolicy[$key] = $val;
|
||||
continue;
|
||||
}
|
||||
if(in_array($key, ['SupportForce', 'DevelopForce'])){
|
||||
if(!is_array($val)){
|
||||
return "{$key}는 올바른 정책값이 아닙니다.";
|
||||
if (in_array($key, ['SupportForce', 'DevelopForce'])) {
|
||||
if (!is_array($val)) {
|
||||
return "{$key}는 올바른 정책값이 아닙니다.";
|
||||
}
|
||||
foreach($val as $troopID){
|
||||
if(!key_exists($troopID, $troopCache)){
|
||||
foreach ($val as $troopID) {
|
||||
if (!key_exists($troopID, $troopCache)) {
|
||||
return "{$troopID}는 국가의 부대가 아닙니다.";
|
||||
}
|
||||
if($troopCache[$troopID] != 'Neutral'){
|
||||
if ($troopCache[$troopID] != 'Neutral') {
|
||||
return "부대({$troopID}는 하나의 역할만 지정할 수 있습니다.";
|
||||
}
|
||||
$troopCache[$troopID]=$key;
|
||||
$troopCache[$troopID] = $key;
|
||||
}
|
||||
|
||||
$nationPolicy[$key]=array_values($val);
|
||||
$nationPolicy[$key] = array_values($val);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if(!key_exists($key, $defaultPolicy)){
|
||||
if (!key_exists($key, $defaultPolicy)) {
|
||||
return "{$key}는 올바른 정책값이 아닙니다.";
|
||||
}
|
||||
$defaultValue = $defaultPolicy[$key];
|
||||
if(is_numeric($defaultValue) != is_numeric($val)){
|
||||
if (is_numeric($defaultValue) != is_numeric($val)) {
|
||||
return "{$key}는 올바른 값이 아닙니다.";
|
||||
}
|
||||
if(is_integer($defaultValue) != is_integer($val)){
|
||||
if (is_integer($defaultValue) != is_integer($val)) {
|
||||
return "{$key}는 올바른 값이 아닙니다.";
|
||||
}
|
||||
if(is_array($defaultValue) != is_array($val)){
|
||||
if (is_array($defaultValue) != is_array($val)) {
|
||||
return "{$key}는 올바른 값이 아닙니다.";
|
||||
}
|
||||
if(is_integer($val) && $val < 0){
|
||||
if (is_integer($val) && $val < 0) {
|
||||
$val = 0;
|
||||
}
|
||||
$nationPolicy[$key] = $val;
|
||||
}
|
||||
|
||||
|
||||
$nationPolicyRoot['values'] = $nationPolicy;
|
||||
$nationPolicyRoot['valueSetter'] = $generalName;
|
||||
$nationPolicyRoot['valueSetTime'] = TimeUtil::now();
|
||||
@@ -139,14 +141,15 @@ function applyNationPolicy($policy, $nationID, $generalName):?string{
|
||||
return null;
|
||||
}
|
||||
|
||||
function applyNationPriority($priority, $nationID, $generalName):?string{
|
||||
function applyNationPriority($priority, $nationID, $generalName): ?string
|
||||
{
|
||||
$db = DB::db();
|
||||
$nationStor = KVStorage::getStorage($db, $nationID, 'nation_env');
|
||||
$nationPolicyRoot = $nationStor->npc_nation_policy;
|
||||
|
||||
$defaultPriority = AutorunNationPolicy::$defaultPriority;
|
||||
foreach($priority as $item){
|
||||
if(!in_array($item, $defaultPriority)){
|
||||
foreach ($priority as $item) {
|
||||
if (!in_array($item, $defaultPriority)) {
|
||||
return "{$item}은 올바른 명령이 아닙니다.";
|
||||
}
|
||||
}
|
||||
@@ -157,17 +160,29 @@ function applyNationPriority($priority, $nationID, $generalName):?string{
|
||||
return null;
|
||||
}
|
||||
|
||||
function applyGeneralPriority($priority, $nationID, $generalName):?string{
|
||||
function applyGeneralPriority($priority, $nationID, $generalName): ?string
|
||||
{
|
||||
$db = DB::db();
|
||||
$nationStor = KVStorage::getStorage($db, $nationID, 'nation_env');
|
||||
$generalPolicyRoot = $nationStor->npc_general_policy;
|
||||
|
||||
$defaultPriority = AutorunGeneralPolicy::$default_priority;
|
||||
foreach($priority as $item){
|
||||
if(!in_array($item, $defaultPriority)){
|
||||
$mustHaveActions = ['출병' => 1];
|
||||
foreach ($priority as $item) {
|
||||
if (key_exists($item, $mustHaveActions)) {
|
||||
$mustHaveActions[$item] = 0;
|
||||
}
|
||||
if (!in_array($item, $defaultPriority)) {
|
||||
return "{$item}은 올바른 명령이 아닙니다.";
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($mustHaveActions as $actionKey => $unset) {
|
||||
if ($unset) {
|
||||
return "{$actionKey}은 항상 사용해야 합니다.";
|
||||
}
|
||||
}
|
||||
|
||||
$generalPolicyRoot['priority'] = $priority;
|
||||
$generalPolicyRoot['prioritySetter'] = $generalName;
|
||||
$generalPolicyRoot['prioritySetTime'] = TimeUtil::now();
|
||||
@@ -175,26 +190,23 @@ function applyGeneralPriority($priority, $nationID, $generalName):?string{
|
||||
return null;
|
||||
}
|
||||
|
||||
if($type == 'nationPolicy'){
|
||||
if ($type == 'nationPolicy') {
|
||||
$result = applyNationPolicy($data, $nationID, $me['name']);
|
||||
}
|
||||
else if($type == 'generalPriority'){
|
||||
} else if ($type == 'generalPriority') {
|
||||
$result = applyGeneralPriority($data, $nationID, $me['name']);
|
||||
}
|
||||
else if($type == 'nationPriority'){
|
||||
} else if ($type == 'nationPriority') {
|
||||
$result = applyNationPriority($data, $nationID, $me['name']);
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
throw new MustNotBeReachedException();
|
||||
}
|
||||
|
||||
if($result!==null){
|
||||
if ($result !== null) {
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>$result,
|
||||
'result' => false,
|
||||
'reason' => $result,
|
||||
]);
|
||||
}
|
||||
Json::die([
|
||||
'result'=>true,
|
||||
'reason'=>'success',
|
||||
]);
|
||||
'result' => true,
|
||||
'reason' => 'success',
|
||||
]);
|
||||
|
||||
@@ -11,7 +11,7 @@ class event_전투특기_무쌍 extends \sammo\BaseItem{
|
||||
protected $id = 61;
|
||||
protected $rawName = '비급';
|
||||
protected $name = '비급(무쌍)';
|
||||
protected $info = '[전투] 대미지 +10%, 피해 -5%, 공격 시 필살 확률 +10%p, <br>승리 수만큼 대미지 0.20%씩 추가 상승(최대40%)<br>승리 수만큼 피해 0.05%씩 감소(최대30%)';
|
||||
protected $info = '[전투] 대미지 +10%, 피해 -5%, 공격 시 필살 확률 +10%p, <br>승리 수만큼 대미지 0.20%씩 추가 상승(최대50%)<br>승리 수만큼 피해 0.05%씩 감소(최대20%)';
|
||||
protected $cost = 100;
|
||||
protected $buyable = true;
|
||||
protected $consumable = false;
|
||||
@@ -28,8 +28,8 @@ class event_전투특기_무쌍 extends \sammo\BaseItem{
|
||||
$attackMultiplier = 1.1;
|
||||
$defenceMultiplier = 0.95;
|
||||
$killnum = $unit->getGeneral()->getRankVar('killnum');
|
||||
$attackMultiplier += Util::valueFit($killnum * 0.01 * 0.2, null, 0.4);
|
||||
$defenceMultiplier -= Util::valueFit($killnum * 0.01 * 0.05, null, 0.3);
|
||||
$attackMultiplier += Util::valueFit($killnum * 0.01 * 0.2, null, 0.5);
|
||||
$defenceMultiplier -= Util::valueFit($killnum * 0.01 * 0.05, null, 0.2);
|
||||
return [$attackMultiplier, $defenceMultiplier];
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@ class che_무쌍 extends \sammo\BaseSpecial{
|
||||
|
||||
protected $id = 61;
|
||||
protected $name = '무쌍';
|
||||
protected $info = '[전투] 대미지 +10%, 피해 -5%, 공격 시 필살 확률 +10%p, <br>승리 수만큼 대미지 0.20%씩 추가 상승(최대40%)<br>승리 수만큼 피해 0.05%씩 감소(최대30%)';
|
||||
protected $info = '[전투] 대미지 +10%, 피해 -5%, 공격 시 필살 확률 +10%p, <br>승리 수만큼 대미지 0.20%씩 추가 상승(최대50%)<br>승리 수만큼 피해 0.05%씩 감소(최대20%)';
|
||||
|
||||
static $selectWeightType = SpecialityHelper::WEIGHT_NORM;
|
||||
static $selectWeight = 1;
|
||||
@@ -29,8 +29,8 @@ class che_무쌍 extends \sammo\BaseSpecial{
|
||||
$attackMultiplier = 1.1;
|
||||
$defenceMultiplier = 0.95;
|
||||
$killnum = $unit->getGeneral()->getRankVar('killnum');
|
||||
$attackMultiplier += Util::valueFit($killnum * 0.01 * 0.2, null, 0.4);
|
||||
$defenceMultiplier -= Util::valueFit($killnum * 0.01 * 0.05, null, 0.3);
|
||||
$attackMultiplier += Util::valueFit($killnum * 0.01 * 0.2, null, 0.5);
|
||||
$defenceMultiplier -= Util::valueFit($killnum * 0.01 * 0.05, null, 0.2);
|
||||
return [$attackMultiplier, $defenceMultiplier];
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
"title": "【가상모드19b】 진유저무쌍! (대형 지도)",
|
||||
"startYear": 180,
|
||||
"history": [
|
||||
"<C>●</>180년 1월:<L><b>【가상모드19ㅠ】</b>진유저무쌍! (대형 지도)</>",
|
||||
"<C>●</>180년 1월:<L><b>【가상모드19】</b>진유저무쌍! (대형 지도)</>",
|
||||
"<C>●</>180년 1월:<L><b>【이벤트】</b></>고대장수 다 덤벼라! 유저가 최강이다!"
|
||||
],
|
||||
"stat": {
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
{
|
||||
"title": "【가상모드23】 CookieRun : Kingdom",
|
||||
"startYear": 180,
|
||||
"history": [
|
||||
"<C>●</>180년 1월:<L><b>【가상모드23】</b>CookieRun : Kingdom</>",
|
||||
"<C>●</>180년 1월:<L><b>【이벤트】</b></>쿠키들과 함께하는 삼모전"
|
||||
],
|
||||
"stat": {
|
||||
"total": 200,
|
||||
"min": 10,
|
||||
"max": 90,
|
||||
"npcTotal":180,
|
||||
"npcMax":70,
|
||||
"npcMin":10,
|
||||
"chiefMin": 60
|
||||
},
|
||||
"iconPath": "쿠키런킹덤",
|
||||
"fiction": 1,
|
||||
"nation":[
|
||||
|
||||
],
|
||||
"map":{
|
||||
"mapName":"miniche",
|
||||
"unitSet":"che"
|
||||
},
|
||||
"diplomacy":[],
|
||||
"general":[
|
||||
[30, "커스터드3세", null, 0, null, 60, 60, 60, 0, 160, 300, null, null, "새로운 백성이로구나. 반가워!"],
|
||||
[30, "클로버", null, 0, null, 71, 49, 71, 0, 160, 300, null, null, "여러분의 모험에 행운이 깃들길..."],
|
||||
[50, "마들렌", null, 0, null, 73, 57, 73, 0, 160, 300, null, null, "빛의 신께 세상을 구하라는 명을 받은 쿠키가 바로 나다!"],
|
||||
[50, "호밀", null, 0, null, 73, 65, 65, 0, 160, 300, null, null, "애송이들! 그렇게 부드러워서야 되겠어?"],
|
||||
[50, "에스프레소", null, 0, null, 75, 55, 75, 0, 160, 300, null, null, "커피마법이라고 다를 것 없습니다?"],
|
||||
[50, "라떼", null, 0, null, 72, 58, 72, 0, 160, 300, null, null, "쓰디 쓴 실패라도 부드러운 우유 몇 방울이면 달콤해질거야"],
|
||||
[50, "아몬드", null, 0, null, 69, 30, 100, 0, 160, 300, null, null, "당신을 마법 행정 규약 위반으로 체포합니다"],
|
||||
[50, "블랙레이즌", null, 0, null, 65, 70, 60, 0, 160, 300, null, null, "깜깜한 어둠 속도 상관 없어. 난 전부 보이니까!"],
|
||||
[60, "감초", null, 0, null, 70, 10, 120, 0, 160, 300, null, null, "나도 할 땐 하는 쿠키야!"],
|
||||
[60, "독버섯", null, 0, null, 70, 60, 70, 0, 160, 300, null, null, "버서엇...?"],
|
||||
[60, "딸기크레페", null, 0, null, 70, 60, 70, 0, 160, 300, null, null],
|
||||
[70, "퓨어바닐라", null, 0, null, 90, 45, 90, 0, 160, 300, null, null, "힘들 땐 힘들다고 말해도 괜찮아요."],
|
||||
[60, "다크초코", null, 0, null, 70, 60, 70, 0, 160, 300, null, null, "그저… 영웅이 되고 싶었을 뿐…"],
|
||||
[60, "석류", null, 0, null, 75, 55, 75, 0, 160, 300, null, null, "영원히 그분만을 섬기리…"],
|
||||
[999, "설탕노움", null, 0, null, 60, 60, 60, 0, 160, 300, null, null],
|
||||
[10, "The브레이브", null, 0, null, 69, 51, 69, 0, 160, 300, null, null, "모험은 이제부터 시작이야!"],
|
||||
[10, "스트로베리", null, 0, null, 70, 50, 70, 0, 160, 300, null, null, "쿠키생은 혼자야…"],
|
||||
[10, "매지션", null, 0, null, 66, 54, 66, 0, 160, 300, null, null, "가슴은 뜨겁게 머리는 앗 차거!"],
|
||||
[10, "에인절", null, 0, null, 63, 57, 63, 0, 160, 300, null, null, "새처럼 날아가 볼까요…"],
|
||||
[10, "비트", null, 0, null, 64, 56, 64, 0, 160, 300, null, null, "벌써 이곳에서 1000일을 버텼지!"],
|
||||
[10, "The머슬", null, 0, null, 70, 50, 70, 0, 160, 300, null, null, "이번엔 스쿼트다! 하나! 둘!"],
|
||||
[10, "닌자", null, 0, null, 63, 57, 63, 0, 160, 300, null, null, "허공을 가르고 바람을 밟는다!"],
|
||||
[30, "용사", null, 0, null, 67, 58, 67, 0, 160, 300, null, null, "더 강해져야 해!"],
|
||||
[30, "알케미스트", null, 0, null, 61, 64, 61, 0, 160, 300, null, null, "내가 어떤 걸 만들어 내는지 잘 보라구~!"],
|
||||
[30, "체리", null, 0, null, 66, 59, 66, 0, 160, 300, null, null, "어랏? 터져버렸네~? 미안...일부러 그랬어~ 헤헷!"],
|
||||
[30, "버블껌", null, 0, null, 65, 60, 65, 0, 160, 300, null, null, "껌은 씹는 것 보다 쏘는 게 더 재밌어!"],
|
||||
[30, "블랙베리", null, 0, null, 65, 60, 65, 0, 160, 300, null, null, "맡기실 일이 있다면 뭐든 말씀하세요."],
|
||||
[30, "팬케이크", null, 0, null, 52, 73, 52, 0, 160, 300, null, null, "나 도토리젤리 안 줄 거야?"],
|
||||
[30, "The프린세스", null, 0, null, 60, 65, 60, 0, 160, 300, null, null, "나들이하기 좋은 날이네~!"],
|
||||
[30, "아보카도", null, 0, null, 67, 58, 67, 0, 160, 300, null, null, "가장 맛있는 싸움은? 보쌈! 와하하!"],
|
||||
[30, "어니언", null, 0, null, 72, 53, 72, 0, 160, 300, null, null, "으아아아아앙~"],
|
||||
[30, "익스플로러", null, 0, null, 65, 60, 65, 0, 160, 300, null, null, "가보고 싶은 곳이 너무 많아!"],
|
||||
[30, "캐롯", null, 0, null, 71, 54, 71, 0, 160, 300, null, null, "밭일하러 나갈 시간이야!"],
|
||||
[60, "뱀파이어", null, 0, null, 58, 72, 58, 0, 160, 300, null, null, "나랑 포도주스 한 잔 어때?"],
|
||||
[50, "스파클링", null, 0, null, 70, 60, 70, 0, 160, 300, null, null, "승리를 위한 한 잔이 필요하겠군요!"],
|
||||
[50, "칠리", null, 0, null, 65, 65, 65, 0, 160, 300, null, null, "어이! 주머니 조심하라구!"],
|
||||
[50, "자색고구마", null, 0, null, 65, 65, 65, 0, 160, 300, null, null, "나랑 싸울 쿠키 다 나와!"],
|
||||
[50, "눈설탕", null, 0, null, 79, 51, 79, 0, 160, 300, null, null, "안녕? 반가워~ 나랑... 눈싸움할래?"],
|
||||
[50, "정글전사", null, 0, null, 80, 50, 80, 0, 160, 300, null, null, "친구…들을… 지켜야… 해…"],
|
||||
[50, "민트초코", null, 0, null, 76, 54, 76, 0, 160, 300, null, null, "어떤 음악을 들려드릴까요?"],
|
||||
[50, "허브", null, 0, null, 71, 59, 71, 0, 160, 300, null, null, "무럭무럭 자라렴~"],
|
||||
[50, "우유", null, 0, null, 72, 58, 72, 0, 160, 300, null, null, "평화를 위해 어둠과 맞서 싸우리라!"],
|
||||
[50, "웨어울프", null, 0, null, 72, 58, 72, 0, 160, 300, null, null, "다가오지 마… 다쳐…"],
|
||||
[50, "구미호", null, 0, null, 72, 58, 72, 0, 160, 300, null, null, "나한테 반하면 어떻게 되는지 궁금해?"],
|
||||
[50, "슈크림", null, 0, null, 71, 59, 71, 0, 160, 300, null, null, "저도 이제 어엿한 마법사라구요!"],
|
||||
[150, "케이크들개", null, 0, null, 40, 80, 40, 0, 160, 300, null, null],
|
||||
[999, "곰젤리", null, 0, null, 40, 80, 40, 0, 160, 300, null, null],
|
||||
[999, "곰젤리역장", null, 0, null, 60, 60, 60, 0, 160, 300, null, null],
|
||||
[999, "후르츠칸앵무", null, 0, null, 60, 60, 60, 0, 160, 300, null, null],
|
||||
[999, "순례자", null, 0, null, 60, 60, 60, 0, 160, 300, null, null],
|
||||
[999, "은행강도", null, 0, null, 60, 60, 60, 0, 160, 300, null, null],
|
||||
[999, "무녀", null, 0, null, 60, 60, 60, 0, 160, 300, null, null],
|
||||
[150, "역사선생님", null, 0, null, 85, 45, 85, 0, 160, 300, null, null, "오늘 확실히 가르쳐 주겠습니다! 도서관의 규칙을!"],
|
||||
[150, "화학선생님", null, 0, null, 85, 45, 85, 0, 160, 300, null, null, "화학실에 멋대로 침입한 벌을 내리겠다!!"],
|
||||
[150, "전술선생님", null, 0, null, 85, 45, 85, 0, 160, 300, null, null, "으하하하!! 그럼 어디 한 번 시험해 볼까! 너의 전술을!"],
|
||||
[150, "꿈꾸는 바할로모트", null, 0, null, 90, 40, 90, 0, 160, 300, null, "환술", "난 이 학교의 교장이니까 말일세!"],
|
||||
[999, "치료사", null, 0, null, 65, 55, 65, 0, 160, 300, null, null],
|
||||
[999, "커스터드총리", null, 0, null, 63, 63, 63, 0, 160, 300, null, null],
|
||||
[150, "3단케이크마녀", null, 0, null, 70, 70, 70, 0, 160, 300, null, null]
|
||||
],
|
||||
"general_ex":[
|
||||
[999, "바람궁수", null, 0, null, 60, 60, 60, 0, 160, 300, null, null],
|
||||
[999, "달빛술사", null, 0, null, 60, 60, 60, 0, 160, 300, null, null],
|
||||
[999, "바다요정", null, 0, null, 60, 60, 60, 0, 160, 300, null, null],
|
||||
[999, "불꽃정령", null, 0, null, 60, 60, 60, 0, 160, 300, null, null],
|
||||
[150, "어둠마녀", null, 0, null, 60, 60, 60, 0, 160, 300, null, null],
|
||||
[999, "천년나무", null, 0, null, 60, 60, 60, 0, 160, 300, null, null],
|
||||
[999, "다크카카오", null, 0, null, 60, 60, 60, 0, 160, 300, null, null],
|
||||
[999, "세인트릴리", null, 0, null, 60, 60, 60, 0, 160, 300, null, null],
|
||||
[999, "홀리베리", null, 0, null, 60, 60, 60, 0, 160, 300, null, null],
|
||||
[999, "골드치즈", null, 0, null, 60, 60, 60, 0, 160, 300, null, null]
|
||||
],
|
||||
"events":[
|
||||
[
|
||||
["or", ["Date", "==", null, 12], ["Date", "==", null, 6]],
|
||||
["CreateManyNPC", 30],
|
||||
["DeleteEvent"]
|
||||
],
|
||||
[
|
||||
["Date", "==", 181, 1],
|
||||
["RaiseNPCNation"],
|
||||
["DeleteEvent"]
|
||||
]
|
||||
]
|
||||
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
../nesbot/carbon/bin/carbon
|
||||
+151
-2
@@ -29,7 +29,7 @@ private static $installed = array (
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '5310c2e7f6f872cbb923ed71b72ef01b8df4aaaf',
|
||||
'reference' => '40a20a55d3aa08f0ab58a50b0572b17dce33de80',
|
||||
'name' => 'sammo-hid/sammo',
|
||||
),
|
||||
'versions' =>
|
||||
@@ -70,6 +70,15 @@ private static $installed = array (
|
||||
),
|
||||
'reference' => '84674dd3a7575ba617f5a76d7e9e29a7d3891339',
|
||||
),
|
||||
'doctrine/inflector' =>
|
||||
array (
|
||||
'pretty_version' => '2.0.3',
|
||||
'version' => '2.0.3.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '9cf661f4eb38f7c881cac67c75ea9b00bf97b210',
|
||||
),
|
||||
'erusev/parsedown' =>
|
||||
array (
|
||||
'pretty_version' => '1.7.4',
|
||||
@@ -142,6 +151,87 @@ private static $installed = array (
|
||||
),
|
||||
'reference' => 'dc960a912984efb74d0a90222870c72c87f10c91',
|
||||
),
|
||||
'illuminate/bus' =>
|
||||
array (
|
||||
'pretty_version' => 'v8.61.0',
|
||||
'version' => '8.61.0.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '808097c0dfd893309bd77b00139586c516b965c9',
|
||||
),
|
||||
'illuminate/collections' =>
|
||||
array (
|
||||
'pretty_version' => 'v8.61.0',
|
||||
'version' => '8.61.0.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '18fa841df912ec56849351dd6ca8928e8a98b69d',
|
||||
),
|
||||
'illuminate/container' =>
|
||||
array (
|
||||
'pretty_version' => 'v8.61.0',
|
||||
'version' => '8.61.0.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '862b64ea4ab56e307a1676104a1b93295d347ad0',
|
||||
),
|
||||
'illuminate/contracts' =>
|
||||
array (
|
||||
'pretty_version' => 'v8.61.0',
|
||||
'version' => '8.61.0.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'ab4bb4ec3b36905ccf972c84f9aaa2bdd1153913',
|
||||
),
|
||||
'illuminate/database' =>
|
||||
array (
|
||||
'pretty_version' => 'v8.61.0',
|
||||
'version' => '8.61.0.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'acc11d6839ddb3b694bc6585177fa5141b70c693',
|
||||
),
|
||||
'illuminate/events' =>
|
||||
array (
|
||||
'pretty_version' => 'v8.61.0',
|
||||
'version' => '8.61.0.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '7def78033f29cd0c0383513b27c291d233a7f90e',
|
||||
),
|
||||
'illuminate/macroable' =>
|
||||
array (
|
||||
'pretty_version' => 'v8.61.0',
|
||||
'version' => '8.61.0.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '300aa13c086f25116b5f3cde3ca54ff5c822fb05',
|
||||
),
|
||||
'illuminate/pipeline' =>
|
||||
array (
|
||||
'pretty_version' => 'v8.61.0',
|
||||
'version' => '8.61.0.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '23aeff5b26ae4aee3f370835c76bd0f4e93f71d2',
|
||||
),
|
||||
'illuminate/support' =>
|
||||
array (
|
||||
'pretty_version' => 'v8.61.0',
|
||||
'version' => '8.61.0.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'b0a21c41163381dd9a5abbd68fe85ed7b4247d30',
|
||||
),
|
||||
'league/plates' =>
|
||||
array (
|
||||
'pretty_version' => 'v3.4.0',
|
||||
@@ -169,6 +259,15 @@ private static $installed = array (
|
||||
),
|
||||
'reference' => 'c6b00f05152ae2c9b04a448f99c7590beb6042f5',
|
||||
),
|
||||
'nesbot/carbon' =>
|
||||
array (
|
||||
'pretty_version' => '2.53.1',
|
||||
'version' => '2.53.1.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'f4655858a784988f880c1b8c7feabbf02dfdf045',
|
||||
),
|
||||
'netresearch/jsonmapper' =>
|
||||
array (
|
||||
'pretty_version' => 'v4.0.0',
|
||||
@@ -277,6 +376,13 @@ private static $installed = array (
|
||||
),
|
||||
'reference' => '8622567409010282b7aeebe4bb841fe98b58dcaf',
|
||||
),
|
||||
'psr/container-implementation' =>
|
||||
array (
|
||||
'provided' =>
|
||||
array (
|
||||
0 => '1.0',
|
||||
),
|
||||
),
|
||||
'psr/http-message' =>
|
||||
array (
|
||||
'pretty_version' => '1.0.1',
|
||||
@@ -310,6 +416,15 @@ private static $installed = array (
|
||||
1 => '1.0|2.0',
|
||||
),
|
||||
),
|
||||
'psr/simple-cache' =>
|
||||
array (
|
||||
'pretty_version' => '1.0.1',
|
||||
'version' => '1.0.1.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '408d5eafb83c57f6365a3ca330ff23aa4a5fa39b',
|
||||
),
|
||||
'ralouphie/getallheaders' =>
|
||||
array (
|
||||
'pretty_version' => '3.0.3',
|
||||
@@ -335,7 +450,7 @@ private static $installed = array (
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '5310c2e7f6f872cbb923ed71b72ef01b8df4aaaf',
|
||||
'reference' => '40a20a55d3aa08f0ab58a50b0572b17dce33de80',
|
||||
),
|
||||
'scssphp/scssphp' =>
|
||||
array (
|
||||
@@ -472,6 +587,31 @@ private static $installed = array (
|
||||
),
|
||||
'reference' => 'bd53358e3eccec6a670b5f33ab680d8dbe1d4ae1',
|
||||
),
|
||||
'symfony/translation' =>
|
||||
array (
|
||||
'pretty_version' => 'v5.3.7',
|
||||
'version' => '5.3.7.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '4d595a6d15fd3a2c67f6f31d14d15d3b7356d7a6',
|
||||
),
|
||||
'symfony/translation-contracts' =>
|
||||
array (
|
||||
'pretty_version' => 'v2.4.0',
|
||||
'version' => '2.4.0.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '95c812666f3e91db75385749fe219c5e494c7f95',
|
||||
),
|
||||
'symfony/translation-implementation' =>
|
||||
array (
|
||||
'provided' =>
|
||||
array (
|
||||
0 => '2.3',
|
||||
),
|
||||
),
|
||||
'tysonandre/var_representation_polyfill' =>
|
||||
array (
|
||||
'pretty_version' => '0.0.2',
|
||||
@@ -490,6 +630,15 @@ private static $installed = array (
|
||||
),
|
||||
'reference' => '5ebd5d7af82cc0a9d798e816a2ecad63f1b59ceb',
|
||||
),
|
||||
'voku/portable-ascii' =>
|
||||
array (
|
||||
'pretty_version' => '1.5.6',
|
||||
'version' => '1.5.6.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '80953678b19901e5165c56752d087fc11526017c',
|
||||
),
|
||||
'webmozart/assert' =>
|
||||
array (
|
||||
'pretty_version' => '1.10.0',
|
||||
|
||||
Vendored
+5
-1
@@ -8,12 +8,15 @@ $baseDir = dirname($vendorDir);
|
||||
return array(
|
||||
'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php',
|
||||
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
|
||||
'6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php',
|
||||
'320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php',
|
||||
'e69f7f6ee287b969198c3c9d6777bd38' => $vendorDir . '/symfony/polyfill-intl-normalizer/bootstrap.php',
|
||||
'8825ede83f2f289127722d4e842cf7e8' => $vendorDir . '/symfony/polyfill-intl-grapheme/bootstrap.php',
|
||||
'6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php',
|
||||
'0d59ee240a4cd96ddbb4ff164fccea4d' => $vendorDir . '/symfony/polyfill-php73/bootstrap.php',
|
||||
'b6b991a57620e2fb6b2f66f03fe9ddc2' => $vendorDir . '/symfony/string/Resources/functions.php',
|
||||
'60799491728b879e74601d83e38b2cad' => $vendorDir . '/illuminate/collections/helpers.php',
|
||||
'a1105708a18b76903365ca1c4aa61b02' => $vendorDir . '/symfony/translation/Resources/functions.php',
|
||||
'72579e7bd17821bb1321b87411366eae' => $vendorDir . '/illuminate/support/helpers.php',
|
||||
'2b9d0f43f9552984cfa82fee95491826' => $vendorDir . '/sabre/event/lib/coroutine.php',
|
||||
'd81bab31d3feb45bfe2f283ea3c8fdf7' => $vendorDir . '/sabre/event/lib/Loop/functions.php',
|
||||
'a1cce3d26cc15c00fcd0b3354bd72c88' => $vendorDir . '/sabre/event/lib/Promise/functions.php',
|
||||
@@ -26,5 +29,6 @@ return array(
|
||||
'6714be961f4a45ae8b9a99d5d55c5d07' => $vendorDir . '/tysonandre/var_representation_polyfill/src/var_representation.php',
|
||||
'37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php',
|
||||
'5b154887902198b16314243c6e0e3e19' => $vendorDir . '/pguardiario/phpuri/phpuri.php',
|
||||
'ef65a1626449d89d0811cf9befce46f0' => $vendorDir . '/illuminate/events/functions.php',
|
||||
'870dc64919afa8b0f700701bb2c6a783' => $baseDir . '/f_config/config.php',
|
||||
);
|
||||
|
||||
Vendored
+13
@@ -6,6 +6,7 @@ $vendorDir = dirname(dirname(__FILE__));
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'voku\\' => array($vendorDir . '/voku/portable-ascii/src/voku'),
|
||||
'sammo\\' => array($baseDir . '/src/sammo'),
|
||||
'phpDocumentor\\Reflection\\' => array($vendorDir . '/phpdocumentor/reflection-common/src', $vendorDir . '/phpdocumentor/reflection-docblock/src', $vendorDir . '/phpdocumentor/type-resolver/src'),
|
||||
'kakao\\' => array($baseDir . '/src/kakao'),
|
||||
@@ -20,12 +21,15 @@ return array(
|
||||
'Symfony\\Polyfill\\Intl\\Idn\\' => array($vendorDir . '/symfony/polyfill-intl-idn'),
|
||||
'Symfony\\Polyfill\\Intl\\Grapheme\\' => array($vendorDir . '/symfony/polyfill-intl-grapheme'),
|
||||
'Symfony\\Polyfill\\Ctype\\' => array($vendorDir . '/symfony/polyfill-ctype'),
|
||||
'Symfony\\Contracts\\Translation\\' => array($vendorDir . '/symfony/translation-contracts'),
|
||||
'Symfony\\Contracts\\Service\\' => array($vendorDir . '/symfony/service-contracts'),
|
||||
'Symfony\\Component\\Translation\\' => array($vendorDir . '/symfony/translation'),
|
||||
'Symfony\\Component\\String\\' => array($vendorDir . '/symfony/string'),
|
||||
'Symfony\\Component\\Lock\\' => array($vendorDir . '/symfony/lock'),
|
||||
'Symfony\\Component\\Console\\' => array($vendorDir . '/symfony/console'),
|
||||
'ScssPhp\\ScssPhp\\' => array($vendorDir . '/scssphp/scssphp/src'),
|
||||
'Sabre\\Event\\' => array($vendorDir . '/sabre/event/lib'),
|
||||
'Psr\\SimpleCache\\' => array($vendorDir . '/psr/simple-cache/src'),
|
||||
'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
|
||||
'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-message/src'),
|
||||
'Psr\\Container\\' => array($vendorDir . '/psr/container/src'),
|
||||
@@ -36,10 +40,19 @@ return array(
|
||||
'Microsoft\\PhpParser\\' => array($vendorDir . '/microsoft/tolerant-php-parser/src'),
|
||||
'Medoo\\' => array($vendorDir . '/catfan/medoo/src'),
|
||||
'League\\Plates\\' => array($vendorDir . '/league/plates/src'),
|
||||
'Illuminate\\Support\\' => array($vendorDir . '/illuminate/collections', $vendorDir . '/illuminate/macroable', $vendorDir . '/illuminate/support'),
|
||||
'Illuminate\\Pipeline\\' => array($vendorDir . '/illuminate/pipeline'),
|
||||
'Illuminate\\Events\\' => array($vendorDir . '/illuminate/events'),
|
||||
'Illuminate\\Database\\' => array($vendorDir . '/illuminate/database'),
|
||||
'Illuminate\\Contracts\\' => array($vendorDir . '/illuminate/contracts'),
|
||||
'Illuminate\\Container\\' => array($vendorDir . '/illuminate/container'),
|
||||
'Illuminate\\Bus\\' => array($vendorDir . '/illuminate/bus'),
|
||||
'GuzzleHttp\\Psr7\\' => array($vendorDir . '/guzzlehttp/psr7/src'),
|
||||
'GuzzleHttp\\Promise\\' => array($vendorDir . '/guzzlehttp/promises/src'),
|
||||
'GuzzleHttp\\' => array($vendorDir . '/guzzlehttp/guzzle/src'),
|
||||
'Doctrine\\Inflector\\' => array($vendorDir . '/doctrine/inflector/lib/Doctrine/Inflector'),
|
||||
'Composer\\XdebugHandler\\' => array($vendorDir . '/composer/xdebug-handler/src'),
|
||||
'Composer\\Semver\\' => array($vendorDir . '/composer/semver/src'),
|
||||
'Carbon\\' => array($vendorDir . '/nesbot/carbon/src/Carbon'),
|
||||
'AdvancedJsonRpc\\' => array($vendorDir . '/felixfbecker/advanced-json-rpc/lib'),
|
||||
);
|
||||
|
||||
Vendored
+81
-1
@@ -9,12 +9,15 @@ class ComposerStaticInit67b09c83b85c3bc0027caefe5bba171a
|
||||
public static $files = array (
|
||||
'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php',
|
||||
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
|
||||
'6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php',
|
||||
'320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php',
|
||||
'e69f7f6ee287b969198c3c9d6777bd38' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/bootstrap.php',
|
||||
'8825ede83f2f289127722d4e842cf7e8' => __DIR__ . '/..' . '/symfony/polyfill-intl-grapheme/bootstrap.php',
|
||||
'6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php',
|
||||
'0d59ee240a4cd96ddbb4ff164fccea4d' => __DIR__ . '/..' . '/symfony/polyfill-php73/bootstrap.php',
|
||||
'b6b991a57620e2fb6b2f66f03fe9ddc2' => __DIR__ . '/..' . '/symfony/string/Resources/functions.php',
|
||||
'60799491728b879e74601d83e38b2cad' => __DIR__ . '/..' . '/illuminate/collections/helpers.php',
|
||||
'a1105708a18b76903365ca1c4aa61b02' => __DIR__ . '/..' . '/symfony/translation/Resources/functions.php',
|
||||
'72579e7bd17821bb1321b87411366eae' => __DIR__ . '/..' . '/illuminate/support/helpers.php',
|
||||
'2b9d0f43f9552984cfa82fee95491826' => __DIR__ . '/..' . '/sabre/event/lib/coroutine.php',
|
||||
'd81bab31d3feb45bfe2f283ea3c8fdf7' => __DIR__ . '/..' . '/sabre/event/lib/Loop/functions.php',
|
||||
'a1cce3d26cc15c00fcd0b3354bd72c88' => __DIR__ . '/..' . '/sabre/event/lib/Promise/functions.php',
|
||||
@@ -27,10 +30,15 @@ class ComposerStaticInit67b09c83b85c3bc0027caefe5bba171a
|
||||
'6714be961f4a45ae8b9a99d5d55c5d07' => __DIR__ . '/..' . '/tysonandre/var_representation_polyfill/src/var_representation.php',
|
||||
'37a3dc5111fe8f707ab4c132ef1dbc62' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/functions_include.php',
|
||||
'5b154887902198b16314243c6e0e3e19' => __DIR__ . '/..' . '/pguardiario/phpuri/phpuri.php',
|
||||
'ef65a1626449d89d0811cf9befce46f0' => __DIR__ . '/..' . '/illuminate/events/functions.php',
|
||||
'870dc64919afa8b0f700701bb2c6a783' => __DIR__ . '/../..' . '/f_config/config.php',
|
||||
);
|
||||
|
||||
public static $prefixLengthsPsr4 = array (
|
||||
'v' =>
|
||||
array (
|
||||
'voku\\' => 5,
|
||||
),
|
||||
's' =>
|
||||
array (
|
||||
'sammo\\' => 6,
|
||||
@@ -62,7 +70,9 @@ class ComposerStaticInit67b09c83b85c3bc0027caefe5bba171a
|
||||
'Symfony\\Polyfill\\Intl\\Idn\\' => 26,
|
||||
'Symfony\\Polyfill\\Intl\\Grapheme\\' => 31,
|
||||
'Symfony\\Polyfill\\Ctype\\' => 23,
|
||||
'Symfony\\Contracts\\Translation\\' => 30,
|
||||
'Symfony\\Contracts\\Service\\' => 26,
|
||||
'Symfony\\Component\\Translation\\' => 30,
|
||||
'Symfony\\Component\\String\\' => 25,
|
||||
'Symfony\\Component\\Lock\\' => 23,
|
||||
'Symfony\\Component\\Console\\' => 26,
|
||||
@@ -71,6 +81,7 @@ class ComposerStaticInit67b09c83b85c3bc0027caefe5bba171a
|
||||
),
|
||||
'P' =>
|
||||
array (
|
||||
'Psr\\SimpleCache\\' => 16,
|
||||
'Psr\\Log\\' => 8,
|
||||
'Psr\\Http\\Message\\' => 17,
|
||||
'Psr\\Container\\' => 14,
|
||||
@@ -88,16 +99,31 @@ class ComposerStaticInit67b09c83b85c3bc0027caefe5bba171a
|
||||
array (
|
||||
'League\\Plates\\' => 14,
|
||||
),
|
||||
'I' =>
|
||||
array (
|
||||
'Illuminate\\Support\\' => 19,
|
||||
'Illuminate\\Pipeline\\' => 20,
|
||||
'Illuminate\\Events\\' => 18,
|
||||
'Illuminate\\Database\\' => 20,
|
||||
'Illuminate\\Contracts\\' => 21,
|
||||
'Illuminate\\Container\\' => 21,
|
||||
'Illuminate\\Bus\\' => 15,
|
||||
),
|
||||
'G' =>
|
||||
array (
|
||||
'GuzzleHttp\\Psr7\\' => 16,
|
||||
'GuzzleHttp\\Promise\\' => 19,
|
||||
'GuzzleHttp\\' => 11,
|
||||
),
|
||||
'D' =>
|
||||
array (
|
||||
'Doctrine\\Inflector\\' => 19,
|
||||
),
|
||||
'C' =>
|
||||
array (
|
||||
'Composer\\XdebugHandler\\' => 23,
|
||||
'Composer\\Semver\\' => 16,
|
||||
'Carbon\\' => 7,
|
||||
),
|
||||
'A' =>
|
||||
array (
|
||||
@@ -106,6 +132,10 @@ class ComposerStaticInit67b09c83b85c3bc0027caefe5bba171a
|
||||
);
|
||||
|
||||
public static $prefixDirsPsr4 = array (
|
||||
'voku\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/voku/portable-ascii/src/voku',
|
||||
),
|
||||
'sammo\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/../..' . '/src/sammo',
|
||||
@@ -164,10 +194,18 @@ class ComposerStaticInit67b09c83b85c3bc0027caefe5bba171a
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/symfony/polyfill-ctype',
|
||||
),
|
||||
'Symfony\\Contracts\\Translation\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/symfony/translation-contracts',
|
||||
),
|
||||
'Symfony\\Contracts\\Service\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/symfony/service-contracts',
|
||||
),
|
||||
'Symfony\\Component\\Translation\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/symfony/translation',
|
||||
),
|
||||
'Symfony\\Component\\String\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/symfony/string',
|
||||
@@ -188,6 +226,10 @@ class ComposerStaticInit67b09c83b85c3bc0027caefe5bba171a
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/sabre/event/lib',
|
||||
),
|
||||
'Psr\\SimpleCache\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/psr/simple-cache/src',
|
||||
),
|
||||
'Psr\\Log\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/psr/log/Psr/Log',
|
||||
@@ -228,6 +270,36 @@ class ComposerStaticInit67b09c83b85c3bc0027caefe5bba171a
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/league/plates/src',
|
||||
),
|
||||
'Illuminate\\Support\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/illuminate/collections',
|
||||
1 => __DIR__ . '/..' . '/illuminate/macroable',
|
||||
2 => __DIR__ . '/..' . '/illuminate/support',
|
||||
),
|
||||
'Illuminate\\Pipeline\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/illuminate/pipeline',
|
||||
),
|
||||
'Illuminate\\Events\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/illuminate/events',
|
||||
),
|
||||
'Illuminate\\Database\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/illuminate/database',
|
||||
),
|
||||
'Illuminate\\Contracts\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/illuminate/contracts',
|
||||
),
|
||||
'Illuminate\\Container\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/illuminate/container',
|
||||
),
|
||||
'Illuminate\\Bus\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/illuminate/bus',
|
||||
),
|
||||
'GuzzleHttp\\Psr7\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/guzzlehttp/psr7/src',
|
||||
@@ -240,6 +312,10 @@ class ComposerStaticInit67b09c83b85c3bc0027caefe5bba171a
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/guzzlehttp/guzzle/src',
|
||||
),
|
||||
'Doctrine\\Inflector\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/doctrine/inflector/lib/Doctrine/Inflector',
|
||||
),
|
||||
'Composer\\XdebugHandler\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/composer/xdebug-handler/src',
|
||||
@@ -248,6 +324,10 @@ class ComposerStaticInit67b09c83b85c3bc0027caefe5bba171a
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/composer/semver/src',
|
||||
),
|
||||
'Carbon\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon',
|
||||
),
|
||||
'AdvancedJsonRpc\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/felixfbecker/advanced-json-rpc/lib',
|
||||
|
||||
Vendored
+1023
@@ -267,6 +267,104 @@
|
||||
],
|
||||
"install-path": "./xdebug-handler"
|
||||
},
|
||||
{
|
||||
"name": "doctrine/inflector",
|
||||
"version": "2.0.3",
|
||||
"version_normalized": "2.0.3.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/doctrine/inflector.git",
|
||||
"reference": "9cf661f4eb38f7c881cac67c75ea9b00bf97b210"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/doctrine/inflector/zipball/9cf661f4eb38f7c881cac67c75ea9b00bf97b210",
|
||||
"reference": "9cf661f4eb38f7c881cac67c75ea9b00bf97b210",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.2 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/coding-standard": "^7.0",
|
||||
"phpstan/phpstan": "^0.11",
|
||||
"phpstan/phpstan-phpunit": "^0.11",
|
||||
"phpstan/phpstan-strict-rules": "^0.11",
|
||||
"phpunit/phpunit": "^7.0 || ^8.0 || ^9.0"
|
||||
},
|
||||
"time": "2020-05-29T15:13:26+00:00",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.0.x-dev"
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Doctrine\\Inflector\\": "lib/Doctrine/Inflector"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Guilherme Blanco",
|
||||
"email": "guilhermeblanco@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Roman Borschel",
|
||||
"email": "roman@code-factory.org"
|
||||
},
|
||||
{
|
||||
"name": "Benjamin Eberlei",
|
||||
"email": "kontakt@beberlei.de"
|
||||
},
|
||||
{
|
||||
"name": "Jonathan Wage",
|
||||
"email": "jonwage@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Johannes Schmitt",
|
||||
"email": "schmittjoh@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "PHP Doctrine Inflector is a small library that can perform string manipulations with regard to upper/lowercase and singular/plural forms of words.",
|
||||
"homepage": "https://www.doctrine-project.org/projects/inflector.html",
|
||||
"keywords": [
|
||||
"inflection",
|
||||
"inflector",
|
||||
"lowercase",
|
||||
"manipulation",
|
||||
"php",
|
||||
"plural",
|
||||
"singular",
|
||||
"strings",
|
||||
"uppercase",
|
||||
"words"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/doctrine/inflector/issues",
|
||||
"source": "https://github.com/doctrine/inflector/tree/2.0.x"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://www.doctrine-project.org/sponsorship.html",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://www.patreon.com/phpdoctrine",
|
||||
"type": "patreon"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/doctrine%2Finflector",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"install-path": "../doctrine/inflector"
|
||||
},
|
||||
{
|
||||
"name": "erusev/parsedown",
|
||||
"version": "1.7.4",
|
||||
@@ -720,6 +818,524 @@
|
||||
},
|
||||
"install-path": "../guzzlehttp/psr7"
|
||||
},
|
||||
{
|
||||
"name": "illuminate/bus",
|
||||
"version": "v8.61.0",
|
||||
"version_normalized": "8.61.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/illuminate/bus.git",
|
||||
"reference": "808097c0dfd893309bd77b00139586c516b965c9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/illuminate/bus/zipball/808097c0dfd893309bd77b00139586c516b965c9",
|
||||
"reference": "808097c0dfd893309bd77b00139586c516b965c9",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"illuminate/collections": "^8.0",
|
||||
"illuminate/contracts": "^8.0",
|
||||
"illuminate/pipeline": "^8.0",
|
||||
"illuminate/support": "^8.0",
|
||||
"php": "^7.3|^8.0"
|
||||
},
|
||||
"suggest": {
|
||||
"illuminate/queue": "Required to use closures when chaining jobs (^7.0)."
|
||||
},
|
||||
"time": "2021-08-10T16:49:48+00:00",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "8.x-dev"
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Illuminate\\Bus\\": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Taylor Otwell",
|
||||
"email": "taylor@laravel.com"
|
||||
}
|
||||
],
|
||||
"description": "The Illuminate Bus package.",
|
||||
"homepage": "https://laravel.com",
|
||||
"support": {
|
||||
"issues": "https://github.com/laravel/framework/issues",
|
||||
"source": "https://github.com/laravel/framework"
|
||||
},
|
||||
"install-path": "../illuminate/bus"
|
||||
},
|
||||
{
|
||||
"name": "illuminate/collections",
|
||||
"version": "v8.61.0",
|
||||
"version_normalized": "8.61.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/illuminate/collections.git",
|
||||
"reference": "18fa841df912ec56849351dd6ca8928e8a98b69d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/illuminate/collections/zipball/18fa841df912ec56849351dd6ca8928e8a98b69d",
|
||||
"reference": "18fa841df912ec56849351dd6ca8928e8a98b69d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"illuminate/contracts": "^8.0",
|
||||
"illuminate/macroable": "^8.0",
|
||||
"php": "^7.3|^8.0"
|
||||
},
|
||||
"suggest": {
|
||||
"symfony/var-dumper": "Required to use the dump method (^5.1.4)."
|
||||
},
|
||||
"time": "2021-09-08T12:48:16+00:00",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "8.x-dev"
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Illuminate\\Support\\": ""
|
||||
},
|
||||
"files": [
|
||||
"helpers.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Taylor Otwell",
|
||||
"email": "taylor@laravel.com"
|
||||
}
|
||||
],
|
||||
"description": "The Illuminate Collections package.",
|
||||
"homepage": "https://laravel.com",
|
||||
"support": {
|
||||
"issues": "https://github.com/laravel/framework/issues",
|
||||
"source": "https://github.com/laravel/framework"
|
||||
},
|
||||
"install-path": "../illuminate/collections"
|
||||
},
|
||||
{
|
||||
"name": "illuminate/container",
|
||||
"version": "v8.61.0",
|
||||
"version_normalized": "8.61.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/illuminate/container.git",
|
||||
"reference": "862b64ea4ab56e307a1676104a1b93295d347ad0"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/illuminate/container/zipball/862b64ea4ab56e307a1676104a1b93295d347ad0",
|
||||
"reference": "862b64ea4ab56e307a1676104a1b93295d347ad0",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"illuminate/contracts": "^8.0",
|
||||
"php": "^7.3|^8.0",
|
||||
"psr/container": "^1.0"
|
||||
},
|
||||
"provide": {
|
||||
"psr/container-implementation": "1.0"
|
||||
},
|
||||
"time": "2021-09-09T13:55:23+00:00",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "8.x-dev"
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Illuminate\\Container\\": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Taylor Otwell",
|
||||
"email": "taylor@laravel.com"
|
||||
}
|
||||
],
|
||||
"description": "The Illuminate Container package.",
|
||||
"homepage": "https://laravel.com",
|
||||
"support": {
|
||||
"issues": "https://github.com/laravel/framework/issues",
|
||||
"source": "https://github.com/laravel/framework"
|
||||
},
|
||||
"install-path": "../illuminate/container"
|
||||
},
|
||||
{
|
||||
"name": "illuminate/contracts",
|
||||
"version": "v8.61.0",
|
||||
"version_normalized": "8.61.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/illuminate/contracts.git",
|
||||
"reference": "ab4bb4ec3b36905ccf972c84f9aaa2bdd1153913"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/illuminate/contracts/zipball/ab4bb4ec3b36905ccf972c84f9aaa2bdd1153913",
|
||||
"reference": "ab4bb4ec3b36905ccf972c84f9aaa2bdd1153913",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.3|^8.0",
|
||||
"psr/container": "^1.0",
|
||||
"psr/simple-cache": "^1.0"
|
||||
},
|
||||
"time": "2021-09-08T12:09:40+00:00",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "8.x-dev"
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Illuminate\\Contracts\\": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Taylor Otwell",
|
||||
"email": "taylor@laravel.com"
|
||||
}
|
||||
],
|
||||
"description": "The Illuminate Contracts package.",
|
||||
"homepage": "https://laravel.com",
|
||||
"support": {
|
||||
"issues": "https://github.com/laravel/framework/issues",
|
||||
"source": "https://github.com/laravel/framework"
|
||||
},
|
||||
"install-path": "../illuminate/contracts"
|
||||
},
|
||||
{
|
||||
"name": "illuminate/database",
|
||||
"version": "v8.61.0",
|
||||
"version_normalized": "8.61.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/illuminate/database.git",
|
||||
"reference": "acc11d6839ddb3b694bc6585177fa5141b70c693"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/illuminate/database/zipball/acc11d6839ddb3b694bc6585177fa5141b70c693",
|
||||
"reference": "acc11d6839ddb3b694bc6585177fa5141b70c693",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-json": "*",
|
||||
"illuminate/collections": "^8.0",
|
||||
"illuminate/container": "^8.0",
|
||||
"illuminate/contracts": "^8.0",
|
||||
"illuminate/macroable": "^8.0",
|
||||
"illuminate/support": "^8.0",
|
||||
"php": "^7.3|^8.0",
|
||||
"symfony/console": "^5.1.4"
|
||||
},
|
||||
"suggest": {
|
||||
"doctrine/dbal": "Required to rename columns and drop SQLite columns (^2.6|^3.0).",
|
||||
"fakerphp/faker": "Required to use the eloquent factory builder (^1.9.1).",
|
||||
"illuminate/console": "Required to use the database commands (^8.0).",
|
||||
"illuminate/events": "Required to use the observers with Eloquent (^8.0).",
|
||||
"illuminate/filesystem": "Required to use the migrations (^8.0).",
|
||||
"illuminate/pagination": "Required to paginate the result set (^8.0).",
|
||||
"symfony/finder": "Required to use Eloquent model factories (^5.1.4)."
|
||||
},
|
||||
"time": "2021-09-13T18:43:43+00:00",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "8.x-dev"
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Illuminate\\Database\\": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Taylor Otwell",
|
||||
"email": "taylor@laravel.com"
|
||||
}
|
||||
],
|
||||
"description": "The Illuminate Database package.",
|
||||
"homepage": "https://laravel.com",
|
||||
"keywords": [
|
||||
"database",
|
||||
"laravel",
|
||||
"orm",
|
||||
"sql"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/laravel/framework/issues",
|
||||
"source": "https://github.com/laravel/framework"
|
||||
},
|
||||
"install-path": "../illuminate/database"
|
||||
},
|
||||
{
|
||||
"name": "illuminate/events",
|
||||
"version": "v8.61.0",
|
||||
"version_normalized": "8.61.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/illuminate/events.git",
|
||||
"reference": "7def78033f29cd0c0383513b27c291d233a7f90e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/illuminate/events/zipball/7def78033f29cd0c0383513b27c291d233a7f90e",
|
||||
"reference": "7def78033f29cd0c0383513b27c291d233a7f90e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"illuminate/bus": "^8.0",
|
||||
"illuminate/collections": "^8.0",
|
||||
"illuminate/container": "^8.0",
|
||||
"illuminate/contracts": "^8.0",
|
||||
"illuminate/macroable": "^8.0",
|
||||
"illuminate/support": "^8.0",
|
||||
"php": "^7.3|^8.0"
|
||||
},
|
||||
"time": "2021-08-16T21:45:47+00:00",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "8.x-dev"
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Illuminate\\Events\\": ""
|
||||
},
|
||||
"files": [
|
||||
"functions.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Taylor Otwell",
|
||||
"email": "taylor@laravel.com"
|
||||
}
|
||||
],
|
||||
"description": "The Illuminate Events package.",
|
||||
"homepage": "https://laravel.com",
|
||||
"support": {
|
||||
"issues": "https://github.com/laravel/framework/issues",
|
||||
"source": "https://github.com/laravel/framework"
|
||||
},
|
||||
"install-path": "../illuminate/events"
|
||||
},
|
||||
{
|
||||
"name": "illuminate/macroable",
|
||||
"version": "v8.61.0",
|
||||
"version_normalized": "8.61.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/illuminate/macroable.git",
|
||||
"reference": "300aa13c086f25116b5f3cde3ca54ff5c822fb05"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/illuminate/macroable/zipball/300aa13c086f25116b5f3cde3ca54ff5c822fb05",
|
||||
"reference": "300aa13c086f25116b5f3cde3ca54ff5c822fb05",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.3|^8.0"
|
||||
},
|
||||
"time": "2020-10-27T15:20:30+00:00",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "8.x-dev"
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Illuminate\\Support\\": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Taylor Otwell",
|
||||
"email": "taylor@laravel.com"
|
||||
}
|
||||
],
|
||||
"description": "The Illuminate Macroable package.",
|
||||
"homepage": "https://laravel.com",
|
||||
"support": {
|
||||
"issues": "https://github.com/laravel/framework/issues",
|
||||
"source": "https://github.com/laravel/framework"
|
||||
},
|
||||
"install-path": "../illuminate/macroable"
|
||||
},
|
||||
{
|
||||
"name": "illuminate/pipeline",
|
||||
"version": "v8.61.0",
|
||||
"version_normalized": "8.61.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/illuminate/pipeline.git",
|
||||
"reference": "23aeff5b26ae4aee3f370835c76bd0f4e93f71d2"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/illuminate/pipeline/zipball/23aeff5b26ae4aee3f370835c76bd0f4e93f71d2",
|
||||
"reference": "23aeff5b26ae4aee3f370835c76bd0f4e93f71d2",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"illuminate/contracts": "^8.0",
|
||||
"illuminate/support": "^8.0",
|
||||
"php": "^7.3|^8.0"
|
||||
},
|
||||
"time": "2021-03-26T18:39:16+00:00",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "8.x-dev"
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Illuminate\\Pipeline\\": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Taylor Otwell",
|
||||
"email": "taylor@laravel.com"
|
||||
}
|
||||
],
|
||||
"description": "The Illuminate Pipeline package.",
|
||||
"homepage": "https://laravel.com",
|
||||
"support": {
|
||||
"issues": "https://github.com/laravel/framework/issues",
|
||||
"source": "https://github.com/laravel/framework"
|
||||
},
|
||||
"install-path": "../illuminate/pipeline"
|
||||
},
|
||||
{
|
||||
"name": "illuminate/support",
|
||||
"version": "v8.61.0",
|
||||
"version_normalized": "8.61.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/illuminate/support.git",
|
||||
"reference": "b0a21c41163381dd9a5abbd68fe85ed7b4247d30"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/illuminate/support/zipball/b0a21c41163381dd9a5abbd68fe85ed7b4247d30",
|
||||
"reference": "b0a21c41163381dd9a5abbd68fe85ed7b4247d30",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"doctrine/inflector": "^1.4|^2.0",
|
||||
"ext-json": "*",
|
||||
"ext-mbstring": "*",
|
||||
"illuminate/collections": "^8.0",
|
||||
"illuminate/contracts": "^8.0",
|
||||
"illuminate/macroable": "^8.0",
|
||||
"nesbot/carbon": "^2.31",
|
||||
"php": "^7.3|^8.0",
|
||||
"voku/portable-ascii": "^1.4.8"
|
||||
},
|
||||
"conflict": {
|
||||
"tightenco/collect": "<5.5.33"
|
||||
},
|
||||
"suggest": {
|
||||
"illuminate/filesystem": "Required to use the composer class (^8.0).",
|
||||
"league/commonmark": "Required to use Str::markdown() and Stringable::markdown() (^1.3|^2.0).",
|
||||
"ramsey/uuid": "Required to use Str::uuid() (^4.0).",
|
||||
"symfony/process": "Required to use the composer class (^5.1.4).",
|
||||
"symfony/var-dumper": "Required to use the dd function (^5.1.4).",
|
||||
"vlucas/phpdotenv": "Required to use the Env class and env helper (^5.2)."
|
||||
},
|
||||
"time": "2021-09-13T18:43:43+00:00",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "8.x-dev"
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Illuminate\\Support\\": ""
|
||||
},
|
||||
"files": [
|
||||
"helpers.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Taylor Otwell",
|
||||
"email": "taylor@laravel.com"
|
||||
}
|
||||
],
|
||||
"description": "The Illuminate Support package.",
|
||||
"homepage": "https://laravel.com",
|
||||
"support": {
|
||||
"issues": "https://github.com/laravel/framework/issues",
|
||||
"source": "https://github.com/laravel/framework"
|
||||
},
|
||||
"install-path": "../illuminate/support"
|
||||
},
|
||||
{
|
||||
"name": "league/plates",
|
||||
"version": "v3.4.0",
|
||||
@@ -924,6 +1540,103 @@
|
||||
],
|
||||
"install-path": "../monolog/monolog"
|
||||
},
|
||||
{
|
||||
"name": "nesbot/carbon",
|
||||
"version": "2.53.1",
|
||||
"version_normalized": "2.53.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/briannesbitt/Carbon.git",
|
||||
"reference": "f4655858a784988f880c1b8c7feabbf02dfdf045"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/f4655858a784988f880c1b8c7feabbf02dfdf045",
|
||||
"reference": "f4655858a784988f880c1b8c7feabbf02dfdf045",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-json": "*",
|
||||
"php": "^7.1.8 || ^8.0",
|
||||
"symfony/polyfill-mbstring": "^1.0",
|
||||
"symfony/polyfill-php80": "^1.16",
|
||||
"symfony/translation": "^3.4 || ^4.0 || ^5.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/orm": "^2.7",
|
||||
"friendsofphp/php-cs-fixer": "^3.0",
|
||||
"kylekatarnls/multi-tester": "^2.0",
|
||||
"phpmd/phpmd": "^2.9",
|
||||
"phpstan/extension-installer": "^1.0",
|
||||
"phpstan/phpstan": "^0.12.54",
|
||||
"phpunit/phpunit": "^7.5.20 || ^8.5.14",
|
||||
"squizlabs/php_codesniffer": "^3.4"
|
||||
},
|
||||
"time": "2021-09-06T09:29:23+00:00",
|
||||
"bin": [
|
||||
"bin/carbon"
|
||||
],
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-3.x": "3.x-dev",
|
||||
"dev-master": "2.x-dev"
|
||||
},
|
||||
"laravel": {
|
||||
"providers": [
|
||||
"Carbon\\Laravel\\ServiceProvider"
|
||||
]
|
||||
},
|
||||
"phpstan": {
|
||||
"includes": [
|
||||
"extension.neon"
|
||||
]
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Carbon\\": "src/Carbon/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Brian Nesbitt",
|
||||
"email": "brian@nesbot.com",
|
||||
"homepage": "https://markido.com"
|
||||
},
|
||||
{
|
||||
"name": "kylekatarnls",
|
||||
"homepage": "https://github.com/kylekatarnls"
|
||||
}
|
||||
],
|
||||
"description": "An API extension for DateTime that supports 281 different languages.",
|
||||
"homepage": "https://carbon.nesbot.com",
|
||||
"keywords": [
|
||||
"date",
|
||||
"datetime",
|
||||
"time"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/briannesbitt/Carbon/issues",
|
||||
"source": "https://github.com/briannesbitt/Carbon"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://opencollective.com/Carbon",
|
||||
"type": "open_collective"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/nesbot/carbon",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"install-path": "../nesbot/carbon"
|
||||
},
|
||||
{
|
||||
"name": "netresearch/jsonmapper",
|
||||
"version": "v4.0.0",
|
||||
@@ -1729,6 +2442,60 @@
|
||||
},
|
||||
"install-path": "../psr/log"
|
||||
},
|
||||
{
|
||||
"name": "psr/simple-cache",
|
||||
"version": "1.0.1",
|
||||
"version_normalized": "1.0.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/simple-cache.git",
|
||||
"reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b",
|
||||
"reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"time": "2017-10-23T01:57:42+00:00",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Psr\\SimpleCache\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "http://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"description": "Common interfaces for simple caching",
|
||||
"keywords": [
|
||||
"cache",
|
||||
"caching",
|
||||
"psr",
|
||||
"psr-16",
|
||||
"simple-cache"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/php-fig/simple-cache/tree/master"
|
||||
},
|
||||
"install-path": "../psr/simple-cache"
|
||||
},
|
||||
{
|
||||
"name": "ralouphie/getallheaders",
|
||||
"version": "3.0.3",
|
||||
@@ -3062,6 +3829,185 @@
|
||||
],
|
||||
"install-path": "../symfony/string"
|
||||
},
|
||||
{
|
||||
"name": "symfony/translation",
|
||||
"version": "v5.3.7",
|
||||
"version_normalized": "5.3.7.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/translation.git",
|
||||
"reference": "4d595a6d15fd3a2c67f6f31d14d15d3b7356d7a6"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/translation/zipball/4d595a6d15fd3a2c67f6f31d14d15d3b7356d7a6",
|
||||
"reference": "4d595a6d15fd3a2c67f6f31d14d15d3b7356d7a6",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.2.5",
|
||||
"symfony/deprecation-contracts": "^2.1",
|
||||
"symfony/polyfill-mbstring": "~1.0",
|
||||
"symfony/polyfill-php80": "^1.16",
|
||||
"symfony/translation-contracts": "^2.3"
|
||||
},
|
||||
"conflict": {
|
||||
"symfony/config": "<4.4",
|
||||
"symfony/dependency-injection": "<5.0",
|
||||
"symfony/http-kernel": "<5.0",
|
||||
"symfony/twig-bundle": "<5.0",
|
||||
"symfony/yaml": "<4.4"
|
||||
},
|
||||
"provide": {
|
||||
"symfony/translation-implementation": "2.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"psr/log": "^1|^2|^3",
|
||||
"symfony/config": "^4.4|^5.0",
|
||||
"symfony/console": "^4.4|^5.0",
|
||||
"symfony/dependency-injection": "^5.0",
|
||||
"symfony/finder": "^4.4|^5.0",
|
||||
"symfony/http-kernel": "^5.0",
|
||||
"symfony/intl": "^4.4|^5.0",
|
||||
"symfony/polyfill-intl-icu": "^1.21",
|
||||
"symfony/service-contracts": "^1.1.2|^2",
|
||||
"symfony/yaml": "^4.4|^5.0"
|
||||
},
|
||||
"suggest": {
|
||||
"psr/log-implementation": "To use logging capability in translator",
|
||||
"symfony/config": "",
|
||||
"symfony/yaml": ""
|
||||
},
|
||||
"time": "2021-08-26T08:22:53+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"files": [
|
||||
"Resources/functions.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\Translation\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Provides tools to internationalize your application",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/translation/tree/v5.3.7"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"install-path": "../symfony/translation"
|
||||
},
|
||||
{
|
||||
"name": "symfony/translation-contracts",
|
||||
"version": "v2.4.0",
|
||||
"version_normalized": "2.4.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/translation-contracts.git",
|
||||
"reference": "95c812666f3e91db75385749fe219c5e494c7f95"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/translation-contracts/zipball/95c812666f3e91db75385749fe219c5e494c7f95",
|
||||
"reference": "95c812666f3e91db75385749fe219c5e494c7f95",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.2.5"
|
||||
},
|
||||
"suggest": {
|
||||
"symfony/translation-implementation": ""
|
||||
},
|
||||
"time": "2021-03-23T23:28:01+00:00",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "2.4-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/contracts",
|
||||
"url": "https://github.com/symfony/contracts"
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Contracts\\Translation\\": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Nicolas Grekas",
|
||||
"email": "p@tchwork.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Generic abstractions related to translation",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"abstractions",
|
||||
"contracts",
|
||||
"decoupling",
|
||||
"interfaces",
|
||||
"interoperability",
|
||||
"standards"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/translation-contracts/tree/v2.4.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"install-path": "../symfony/translation-contracts"
|
||||
},
|
||||
{
|
||||
"name": "tysonandre/var_representation_polyfill",
|
||||
"version": "0.0.2",
|
||||
@@ -3178,6 +4124,83 @@
|
||||
],
|
||||
"install-path": "../vlucas/valitron"
|
||||
},
|
||||
{
|
||||
"name": "voku/portable-ascii",
|
||||
"version": "1.5.6",
|
||||
"version_normalized": "1.5.6.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/voku/portable-ascii.git",
|
||||
"reference": "80953678b19901e5165c56752d087fc11526017c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/voku/portable-ascii/zipball/80953678b19901e5165c56752d087fc11526017c",
|
||||
"reference": "80953678b19901e5165c56752d087fc11526017c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.0.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~6.0 || ~7.0 || ~9.0"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-intl": "Use Intl for transliterator_transliterate() support"
|
||||
},
|
||||
"time": "2020-11-12T00:07:28+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"voku\\": "src/voku/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Lars Moelleken",
|
||||
"homepage": "http://www.moelleken.org/"
|
||||
}
|
||||
],
|
||||
"description": "Portable ASCII library - performance optimized (ascii) string functions for php.",
|
||||
"homepage": "https://github.com/voku/portable-ascii",
|
||||
"keywords": [
|
||||
"ascii",
|
||||
"clean",
|
||||
"php"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/voku/portable-ascii/issues",
|
||||
"source": "https://github.com/voku/portable-ascii/tree/1.5.6"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://www.paypal.me/moelleken",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/voku",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://opencollective.com/portable-ascii",
|
||||
"type": "open_collective"
|
||||
},
|
||||
{
|
||||
"url": "https://www.patreon.com/voku",
|
||||
"type": "patreon"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/voku/portable-ascii",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"install-path": "../voku/portable-ascii"
|
||||
},
|
||||
{
|
||||
"name": "webmozart/assert",
|
||||
"version": "1.10.0",
|
||||
|
||||
Vendored
+151
-2
@@ -6,7 +6,7 @@
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '5310c2e7f6f872cbb923ed71b72ef01b8df4aaaf',
|
||||
'reference' => '40a20a55d3aa08f0ab58a50b0572b17dce33de80',
|
||||
'name' => 'sammo-hid/sammo',
|
||||
),
|
||||
'versions' =>
|
||||
@@ -47,6 +47,15 @@
|
||||
),
|
||||
'reference' => '84674dd3a7575ba617f5a76d7e9e29a7d3891339',
|
||||
),
|
||||
'doctrine/inflector' =>
|
||||
array (
|
||||
'pretty_version' => '2.0.3',
|
||||
'version' => '2.0.3.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '9cf661f4eb38f7c881cac67c75ea9b00bf97b210',
|
||||
),
|
||||
'erusev/parsedown' =>
|
||||
array (
|
||||
'pretty_version' => '1.7.4',
|
||||
@@ -119,6 +128,87 @@
|
||||
),
|
||||
'reference' => 'dc960a912984efb74d0a90222870c72c87f10c91',
|
||||
),
|
||||
'illuminate/bus' =>
|
||||
array (
|
||||
'pretty_version' => 'v8.61.0',
|
||||
'version' => '8.61.0.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '808097c0dfd893309bd77b00139586c516b965c9',
|
||||
),
|
||||
'illuminate/collections' =>
|
||||
array (
|
||||
'pretty_version' => 'v8.61.0',
|
||||
'version' => '8.61.0.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '18fa841df912ec56849351dd6ca8928e8a98b69d',
|
||||
),
|
||||
'illuminate/container' =>
|
||||
array (
|
||||
'pretty_version' => 'v8.61.0',
|
||||
'version' => '8.61.0.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '862b64ea4ab56e307a1676104a1b93295d347ad0',
|
||||
),
|
||||
'illuminate/contracts' =>
|
||||
array (
|
||||
'pretty_version' => 'v8.61.0',
|
||||
'version' => '8.61.0.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'ab4bb4ec3b36905ccf972c84f9aaa2bdd1153913',
|
||||
),
|
||||
'illuminate/database' =>
|
||||
array (
|
||||
'pretty_version' => 'v8.61.0',
|
||||
'version' => '8.61.0.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'acc11d6839ddb3b694bc6585177fa5141b70c693',
|
||||
),
|
||||
'illuminate/events' =>
|
||||
array (
|
||||
'pretty_version' => 'v8.61.0',
|
||||
'version' => '8.61.0.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '7def78033f29cd0c0383513b27c291d233a7f90e',
|
||||
),
|
||||
'illuminate/macroable' =>
|
||||
array (
|
||||
'pretty_version' => 'v8.61.0',
|
||||
'version' => '8.61.0.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '300aa13c086f25116b5f3cde3ca54ff5c822fb05',
|
||||
),
|
||||
'illuminate/pipeline' =>
|
||||
array (
|
||||
'pretty_version' => 'v8.61.0',
|
||||
'version' => '8.61.0.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '23aeff5b26ae4aee3f370835c76bd0f4e93f71d2',
|
||||
),
|
||||
'illuminate/support' =>
|
||||
array (
|
||||
'pretty_version' => 'v8.61.0',
|
||||
'version' => '8.61.0.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'b0a21c41163381dd9a5abbd68fe85ed7b4247d30',
|
||||
),
|
||||
'league/plates' =>
|
||||
array (
|
||||
'pretty_version' => 'v3.4.0',
|
||||
@@ -146,6 +236,15 @@
|
||||
),
|
||||
'reference' => 'c6b00f05152ae2c9b04a448f99c7590beb6042f5',
|
||||
),
|
||||
'nesbot/carbon' =>
|
||||
array (
|
||||
'pretty_version' => '2.53.1',
|
||||
'version' => '2.53.1.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'f4655858a784988f880c1b8c7feabbf02dfdf045',
|
||||
),
|
||||
'netresearch/jsonmapper' =>
|
||||
array (
|
||||
'pretty_version' => 'v4.0.0',
|
||||
@@ -254,6 +353,13 @@
|
||||
),
|
||||
'reference' => '8622567409010282b7aeebe4bb841fe98b58dcaf',
|
||||
),
|
||||
'psr/container-implementation' =>
|
||||
array (
|
||||
'provided' =>
|
||||
array (
|
||||
0 => '1.0',
|
||||
),
|
||||
),
|
||||
'psr/http-message' =>
|
||||
array (
|
||||
'pretty_version' => '1.0.1',
|
||||
@@ -287,6 +393,15 @@
|
||||
1 => '1.0|2.0',
|
||||
),
|
||||
),
|
||||
'psr/simple-cache' =>
|
||||
array (
|
||||
'pretty_version' => '1.0.1',
|
||||
'version' => '1.0.1.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '408d5eafb83c57f6365a3ca330ff23aa4a5fa39b',
|
||||
),
|
||||
'ralouphie/getallheaders' =>
|
||||
array (
|
||||
'pretty_version' => '3.0.3',
|
||||
@@ -312,7 +427,7 @@
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '5310c2e7f6f872cbb923ed71b72ef01b8df4aaaf',
|
||||
'reference' => '40a20a55d3aa08f0ab58a50b0572b17dce33de80',
|
||||
),
|
||||
'scssphp/scssphp' =>
|
||||
array (
|
||||
@@ -449,6 +564,31 @@
|
||||
),
|
||||
'reference' => 'bd53358e3eccec6a670b5f33ab680d8dbe1d4ae1',
|
||||
),
|
||||
'symfony/translation' =>
|
||||
array (
|
||||
'pretty_version' => 'v5.3.7',
|
||||
'version' => '5.3.7.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '4d595a6d15fd3a2c67f6f31d14d15d3b7356d7a6',
|
||||
),
|
||||
'symfony/translation-contracts' =>
|
||||
array (
|
||||
'pretty_version' => 'v2.4.0',
|
||||
'version' => '2.4.0.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '95c812666f3e91db75385749fe219c5e494c7f95',
|
||||
),
|
||||
'symfony/translation-implementation' =>
|
||||
array (
|
||||
'provided' =>
|
||||
array (
|
||||
0 => '2.3',
|
||||
),
|
||||
),
|
||||
'tysonandre/var_representation_polyfill' =>
|
||||
array (
|
||||
'pretty_version' => '0.0.2',
|
||||
@@ -467,6 +607,15 @@
|
||||
),
|
||||
'reference' => '5ebd5d7af82cc0a9d798e816a2ecad63f1b59ceb',
|
||||
),
|
||||
'voku/portable-ascii' =>
|
||||
array (
|
||||
'pretty_version' => '1.5.6',
|
||||
'version' => '1.5.6.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '80953678b19901e5165c56752d087fc11526017c',
|
||||
),
|
||||
'webmozart/assert' =>
|
||||
array (
|
||||
'pretty_version' => '1.10.0',
|
||||
|
||||
Vendored
+2
-2
@@ -4,8 +4,8 @@
|
||||
|
||||
$issues = array();
|
||||
|
||||
if (!(PHP_VERSION_ID >= 70205)) {
|
||||
$issues[] = 'Your Composer dependencies require a PHP version ">= 7.2.5". You are running ' . PHP_VERSION . '.';
|
||||
if (!(PHP_VERSION_ID >= 70300)) {
|
||||
$issues[] = 'Your Composer dependencies require a PHP version ">= 7.3.0". You are running ' . PHP_VERSION . '.';
|
||||
}
|
||||
|
||||
if ($issues) {
|
||||
|
||||
Vendored
+19
@@ -0,0 +1,19 @@
|
||||
Copyright (c) 2006-2015 Doctrine Project
|
||||
|
||||
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.
|
||||
Vendored
+8
@@ -0,0 +1,8 @@
|
||||
# Doctrine Inflector
|
||||
|
||||
Doctrine Inflector is a small library that can perform string manipulations
|
||||
with regard to uppercase/lowercase and singular/plural forms of words.
|
||||
|
||||
[](https://travis-ci.org/doctrine/inflector)
|
||||
[](https://scrutinizer-ci.com/g/doctrine/inflector/?branch=master)
|
||||
[](https://scrutinizer-ci.com/g/doctrine/inflector/?branch=master)
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"name": "doctrine/inflector",
|
||||
"type": "library",
|
||||
"description": "PHP Doctrine Inflector is a small library that can perform string manipulations with regard to upper/lowercase and singular/plural forms of words.",
|
||||
"keywords": ["php", "strings", "words", "manipulation", "inflector", "inflection", "uppercase", "lowercase", "singular", "plural"],
|
||||
"homepage": "https://www.doctrine-project.org/projects/inflector.html",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{"name": "Guilherme Blanco", "email": "guilhermeblanco@gmail.com"},
|
||||
{"name": "Roman Borschel", "email": "roman@code-factory.org"},
|
||||
{"name": "Benjamin Eberlei", "email": "kontakt@beberlei.de"},
|
||||
{"name": "Jonathan Wage", "email": "jonwage@gmail.com"},
|
||||
{"name": "Johannes Schmitt", "email": "schmittjoh@gmail.com"}
|
||||
],
|
||||
"require": {
|
||||
"php": "^7.2 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/coding-standard": "^7.0",
|
||||
"phpstan/phpstan": "^0.11",
|
||||
"phpstan/phpstan-phpunit": "^0.11",
|
||||
"phpstan/phpstan-strict-rules": "^0.11",
|
||||
"phpunit/phpunit": "^7.0 || ^8.0 || ^9.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Doctrine\\Inflector\\": "lib/Doctrine/Inflector"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Doctrine\\Tests\\Inflector\\": "tests/Doctrine/Tests/Inflector"
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.0.x-dev"
|
||||
}
|
||||
}
|
||||
}
|
||||
+226
@@ -0,0 +1,226 @@
|
||||
Introduction
|
||||
============
|
||||
|
||||
The Doctrine Inflector has methods for inflecting text. The features include pluralization,
|
||||
singularization, converting between camelCase and under_score and capitalizing
|
||||
words.
|
||||
|
||||
Installation
|
||||
============
|
||||
|
||||
You can install the Inflector with composer:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ composer require doctrine/inflector
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
Using the inflector is easy, you can create a new ``Doctrine\Inflector\Inflector`` instance by using
|
||||
the ``Doctrine\Inflector\InflectorFactory`` class:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use Doctrine\Inflector\InflectorFactory;
|
||||
|
||||
$inflector = InflectorFactory::create()->build();
|
||||
|
||||
By default it will create an English inflector. If you want to use another language, just pass the language
|
||||
you want to create an inflector for to the ``createForLanguage()`` method:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use Doctrine\Inflector\InflectorFactory;
|
||||
use Doctrine\Inflector\Language;
|
||||
|
||||
$inflector = InflectorFactory::createForLanguage(Language::SPANISH)->build();
|
||||
|
||||
The supported languages are as follows:
|
||||
|
||||
- ``Language::ENGLISH``
|
||||
- ``Language::FRENCH``
|
||||
- ``Language::NORWEGIAN_BOKMAL``
|
||||
- ``Language::PORTUGUESE``
|
||||
- ``Language::SPANISH``
|
||||
- ``Language::TURKISH``
|
||||
|
||||
If you want to manually construct the inflector instead of using a factory, you can do so like this:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use Doctrine\Inflector\CachedWordInflector;
|
||||
use Doctrine\Inflector\RulesetInflector;
|
||||
use Doctrine\Inflector\Rules\English;
|
||||
|
||||
$inflector = new Inflector(
|
||||
new CachedWordInflector(new RulesetInflector(
|
||||
English\Rules::getSingularRuleset()
|
||||
)),
|
||||
new CachedWordInflector(new RulesetInflector(
|
||||
English\Rules::getPluralRuleset()
|
||||
))
|
||||
);
|
||||
|
||||
Adding Languages
|
||||
----------------
|
||||
|
||||
If you are interested in adding support for your language, take a look at the other languages defined in the
|
||||
``Doctrine\Inflector\Rules`` namespace and the tests located in ``Doctrine\Tests\Inflector\Rules``. You can copy
|
||||
one of the languages and update the rules for your language.
|
||||
|
||||
Once you have done this, send a pull request to the ``doctrine/inflector`` repository with the additions.
|
||||
|
||||
Custom Setup
|
||||
============
|
||||
|
||||
If you want to setup custom singular and plural rules, you can configure these in the factory:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use Doctrine\Inflector\InflectorFactory;
|
||||
use Doctrine\Inflector\Rules\Pattern;
|
||||
use Doctrine\Inflector\Rules\Patterns;
|
||||
use Doctrine\Inflector\Rules\Ruleset;
|
||||
use Doctrine\Inflector\Rules\Substitution;
|
||||
use Doctrine\Inflector\Rules\Substitutions;
|
||||
use Doctrine\Inflector\Rules\Transformation;
|
||||
use Doctrine\Inflector\Rules\Transformations;
|
||||
use Doctrine\Inflector\Rules\Word;
|
||||
|
||||
$inflector = InflectorFactory::create()
|
||||
->withSingularRules(
|
||||
new Ruleset(
|
||||
new Transformations(
|
||||
new Transformation(new Pattern('/^(bil)er$/i'), '\1'),
|
||||
new Transformation(new Pattern('/^(inflec|contribu)tors$/i'), '\1ta')
|
||||
),
|
||||
new Patterns(new Pattern('singulars')),
|
||||
new Substitutions(new Substitution(new Word('spins'), new Word('spinor')))
|
||||
)
|
||||
)
|
||||
->withPluralRules(
|
||||
new Ruleset(
|
||||
new Transformations(
|
||||
new Transformation(new Pattern('^(bil)er$'), '\1'),
|
||||
new Transformation(new Pattern('^(inflec|contribu)tors$'), '\1ta')
|
||||
),
|
||||
new Patterns(new Pattern('noflect'), new Pattern('abtuse')),
|
||||
new Substitutions(
|
||||
new Substitution(new Word('amaze'), new Word('amazable')),
|
||||
new Substitution(new Word('phone'), new Word('phonezes'))
|
||||
)
|
||||
)
|
||||
)
|
||||
->build();
|
||||
|
||||
No operation inflector
|
||||
----------------------
|
||||
|
||||
The ``Doctrine\Inflector\NoopWordInflector`` may be used to configure an inflector that doesn't perform any operation for
|
||||
pluralization and/or singularization. If will simply return the input as output.
|
||||
|
||||
This is an implementation of the `Null Object design pattern <https://sourcemaking.com/design_patterns/null_object>`_.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use Doctrine\Inflector\Inflector;
|
||||
use Doctrine\Inflector\NoopWordInflector;
|
||||
|
||||
$inflector = new Inflector(new NoopWordInflector(), new NoopWordInflector());
|
||||
|
||||
Tableize
|
||||
========
|
||||
|
||||
Converts ``ModelName`` to ``model_name``:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
echo $inflector->tableize('ModelName'); // model_name
|
||||
|
||||
Classify
|
||||
========
|
||||
|
||||
Converts ``model_name`` to ``ModelName``:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
echo $inflector->classify('model_name'); // ModelName
|
||||
|
||||
Camelize
|
||||
========
|
||||
|
||||
This method uses `Classify`_ and then converts the first character to lowercase:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
echo $inflector->camelize('model_name'); // modelName
|
||||
|
||||
Capitalize
|
||||
==========
|
||||
|
||||
Takes a string and capitalizes all of the words, like PHP's built-in
|
||||
``ucwords`` function. This extends that behavior, however, by allowing the
|
||||
word delimiters to be configured, rather than only separating on
|
||||
whitespace.
|
||||
|
||||
Here is an example:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$string = 'top-o-the-morning to all_of_you!';
|
||||
|
||||
echo $inflector->capitalize($string); // Top-O-The-Morning To All_of_you!
|
||||
|
||||
echo $inflector->capitalize($string, '-_ '); // Top-O-The-Morning To All_Of_You!
|
||||
|
||||
Pluralize
|
||||
=========
|
||||
|
||||
Returns a word in plural form.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
echo $inflector->pluralize('browser'); // browsers
|
||||
|
||||
Singularize
|
||||
===========
|
||||
|
||||
Returns a word in singular form.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
echo $inflector->singularize('browsers'); // browser
|
||||
|
||||
Urlize
|
||||
======
|
||||
|
||||
Generate a URL friendly string from a string of text:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
echo $inflector->urlize('My first blog post'); // my-first-blog-post
|
||||
|
||||
Unaccent
|
||||
========
|
||||
|
||||
You can unaccent a string of text using the ``unaccent()`` method:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
echo $inflector->unaccent('año'); // ano
|
||||
|
||||
Legacy API
|
||||
==========
|
||||
|
||||
The API present in Inflector 1.x is still available, but will be deprecated in a future release and dropped for 3.0.
|
||||
Support for languages other than English is available in the 2.0 API only.
|
||||
|
||||
Acknowledgements
|
||||
================
|
||||
|
||||
The language rules in this library have been adapted from several different sources, including but not limited to:
|
||||
|
||||
- `Ruby On Rails Inflector <http://api.rubyonrails.org/classes/ActiveSupport/Inflector.html>`_
|
||||
- `ICanBoogie Inflector <https://github.com/ICanBoogie/Inflector>`_
|
||||
- `CakePHP Inflector <https://book.cakephp.org/3.0/en/core-libraries/inflector.html>`_
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector;
|
||||
|
||||
class CachedWordInflector implements WordInflector
|
||||
{
|
||||
/** @var WordInflector */
|
||||
private $wordInflector;
|
||||
|
||||
/** @var string[] */
|
||||
private $cache = [];
|
||||
|
||||
public function __construct(WordInflector $wordInflector)
|
||||
{
|
||||
$this->wordInflector = $wordInflector;
|
||||
}
|
||||
|
||||
public function inflect(string $word) : string
|
||||
{
|
||||
return $this->cache[$word] ?? $this->cache[$word] = $this->wordInflector->inflect($word);
|
||||
}
|
||||
}
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector;
|
||||
|
||||
use Doctrine\Inflector\Rules\Ruleset;
|
||||
use function array_unshift;
|
||||
|
||||
abstract class GenericLanguageInflectorFactory implements LanguageInflectorFactory
|
||||
{
|
||||
/** @var Ruleset[] */
|
||||
private $singularRulesets = [];
|
||||
|
||||
/** @var Ruleset[] */
|
||||
private $pluralRulesets = [];
|
||||
|
||||
final public function __construct()
|
||||
{
|
||||
$this->singularRulesets[] = $this->getSingularRuleset();
|
||||
$this->pluralRulesets[] = $this->getPluralRuleset();
|
||||
}
|
||||
|
||||
final public function build() : Inflector
|
||||
{
|
||||
return new Inflector(
|
||||
new CachedWordInflector(new RulesetInflector(
|
||||
...$this->singularRulesets
|
||||
)),
|
||||
new CachedWordInflector(new RulesetInflector(
|
||||
...$this->pluralRulesets
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
final public function withSingularRules(?Ruleset $singularRules, bool $reset = false) : LanguageInflectorFactory
|
||||
{
|
||||
if ($reset) {
|
||||
$this->singularRulesets = [];
|
||||
}
|
||||
|
||||
if ($singularRules instanceof Ruleset) {
|
||||
array_unshift($this->singularRulesets, $singularRules);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
final public function withPluralRules(?Ruleset $pluralRules, bool $reset = false) : LanguageInflectorFactory
|
||||
{
|
||||
if ($reset) {
|
||||
$this->pluralRulesets = [];
|
||||
}
|
||||
|
||||
if ($pluralRules instanceof Ruleset) {
|
||||
array_unshift($this->pluralRulesets, $pluralRules);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
abstract protected function getSingularRuleset() : Ruleset;
|
||||
|
||||
abstract protected function getPluralRuleset() : Ruleset;
|
||||
}
|
||||
@@ -0,0 +1,506 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector;
|
||||
|
||||
use RuntimeException;
|
||||
use function chr;
|
||||
use function function_exists;
|
||||
use function lcfirst;
|
||||
use function mb_strtolower;
|
||||
use function ord;
|
||||
use function preg_match;
|
||||
use function preg_replace;
|
||||
use function sprintf;
|
||||
use function str_replace;
|
||||
use function strlen;
|
||||
use function strtolower;
|
||||
use function strtr;
|
||||
use function trim;
|
||||
use function ucwords;
|
||||
|
||||
class Inflector
|
||||
{
|
||||
private const ACCENTED_CHARACTERS = [
|
||||
'À' => 'A',
|
||||
'Á' => 'A',
|
||||
'Â' => 'A',
|
||||
'Ã' => 'A',
|
||||
'Ä' => 'Ae',
|
||||
'Æ' => 'Ae',
|
||||
'Å' => 'Aa',
|
||||
'æ' => 'a',
|
||||
'Ç' => 'C',
|
||||
'È' => 'E',
|
||||
'É' => 'E',
|
||||
'Ê' => 'E',
|
||||
'Ë' => 'E',
|
||||
'Ì' => 'I',
|
||||
'Í' => 'I',
|
||||
'Î' => 'I',
|
||||
'Ï' => 'I',
|
||||
'Ñ' => 'N',
|
||||
'Ò' => 'O',
|
||||
'Ó' => 'O',
|
||||
'Ô' => 'O',
|
||||
'Õ' => 'O',
|
||||
'Ö' => 'Oe',
|
||||
'Ù' => 'U',
|
||||
'Ú' => 'U',
|
||||
'Û' => 'U',
|
||||
'Ü' => 'Ue',
|
||||
'Ý' => 'Y',
|
||||
'ß' => 'ss',
|
||||
'à' => 'a',
|
||||
'á' => 'a',
|
||||
'â' => 'a',
|
||||
'ã' => 'a',
|
||||
'ä' => 'ae',
|
||||
'å' => 'aa',
|
||||
'ç' => 'c',
|
||||
'è' => 'e',
|
||||
'é' => 'e',
|
||||
'ê' => 'e',
|
||||
'ë' => 'e',
|
||||
'ì' => 'i',
|
||||
'í' => 'i',
|
||||
'î' => 'i',
|
||||
'ï' => 'i',
|
||||
'ñ' => 'n',
|
||||
'ò' => 'o',
|
||||
'ó' => 'o',
|
||||
'ô' => 'o',
|
||||
'õ' => 'o',
|
||||
'ö' => 'oe',
|
||||
'ù' => 'u',
|
||||
'ú' => 'u',
|
||||
'û' => 'u',
|
||||
'ü' => 'ue',
|
||||
'ý' => 'y',
|
||||
'ÿ' => 'y',
|
||||
'Ā' => 'A',
|
||||
'ā' => 'a',
|
||||
'Ă' => 'A',
|
||||
'ă' => 'a',
|
||||
'Ą' => 'A',
|
||||
'ą' => 'a',
|
||||
'Ć' => 'C',
|
||||
'ć' => 'c',
|
||||
'Ĉ' => 'C',
|
||||
'ĉ' => 'c',
|
||||
'Ċ' => 'C',
|
||||
'ċ' => 'c',
|
||||
'Č' => 'C',
|
||||
'č' => 'c',
|
||||
'Ď' => 'D',
|
||||
'ď' => 'd',
|
||||
'Đ' => 'D',
|
||||
'đ' => 'd',
|
||||
'Ē' => 'E',
|
||||
'ē' => 'e',
|
||||
'Ĕ' => 'E',
|
||||
'ĕ' => 'e',
|
||||
'Ė' => 'E',
|
||||
'ė' => 'e',
|
||||
'Ę' => 'E',
|
||||
'ę' => 'e',
|
||||
'Ě' => 'E',
|
||||
'ě' => 'e',
|
||||
'Ĝ' => 'G',
|
||||
'ĝ' => 'g',
|
||||
'Ğ' => 'G',
|
||||
'ğ' => 'g',
|
||||
'Ġ' => 'G',
|
||||
'ġ' => 'g',
|
||||
'Ģ' => 'G',
|
||||
'ģ' => 'g',
|
||||
'Ĥ' => 'H',
|
||||
'ĥ' => 'h',
|
||||
'Ħ' => 'H',
|
||||
'ħ' => 'h',
|
||||
'Ĩ' => 'I',
|
||||
'ĩ' => 'i',
|
||||
'Ī' => 'I',
|
||||
'ī' => 'i',
|
||||
'Ĭ' => 'I',
|
||||
'ĭ' => 'i',
|
||||
'Į' => 'I',
|
||||
'į' => 'i',
|
||||
'İ' => 'I',
|
||||
'ı' => 'i',
|
||||
'IJ' => 'IJ',
|
||||
'ij' => 'ij',
|
||||
'Ĵ' => 'J',
|
||||
'ĵ' => 'j',
|
||||
'Ķ' => 'K',
|
||||
'ķ' => 'k',
|
||||
'ĸ' => 'k',
|
||||
'Ĺ' => 'L',
|
||||
'ĺ' => 'l',
|
||||
'Ļ' => 'L',
|
||||
'ļ' => 'l',
|
||||
'Ľ' => 'L',
|
||||
'ľ' => 'l',
|
||||
'Ŀ' => 'L',
|
||||
'ŀ' => 'l',
|
||||
'Ł' => 'L',
|
||||
'ł' => 'l',
|
||||
'Ń' => 'N',
|
||||
'ń' => 'n',
|
||||
'Ņ' => 'N',
|
||||
'ņ' => 'n',
|
||||
'Ň' => 'N',
|
||||
'ň' => 'n',
|
||||
'ʼn' => 'N',
|
||||
'Ŋ' => 'n',
|
||||
'ŋ' => 'N',
|
||||
'Ō' => 'O',
|
||||
'ō' => 'o',
|
||||
'Ŏ' => 'O',
|
||||
'ŏ' => 'o',
|
||||
'Ő' => 'O',
|
||||
'ő' => 'o',
|
||||
'Œ' => 'OE',
|
||||
'œ' => 'oe',
|
||||
'Ø' => 'O',
|
||||
'ø' => 'o',
|
||||
'Ŕ' => 'R',
|
||||
'ŕ' => 'r',
|
||||
'Ŗ' => 'R',
|
||||
'ŗ' => 'r',
|
||||
'Ř' => 'R',
|
||||
'ř' => 'r',
|
||||
'Ś' => 'S',
|
||||
'ś' => 's',
|
||||
'Ŝ' => 'S',
|
||||
'ŝ' => 's',
|
||||
'Ş' => 'S',
|
||||
'ş' => 's',
|
||||
'Š' => 'S',
|
||||
'š' => 's',
|
||||
'Ţ' => 'T',
|
||||
'ţ' => 't',
|
||||
'Ť' => 'T',
|
||||
'ť' => 't',
|
||||
'Ŧ' => 'T',
|
||||
'ŧ' => 't',
|
||||
'Ũ' => 'U',
|
||||
'ũ' => 'u',
|
||||
'Ū' => 'U',
|
||||
'ū' => 'u',
|
||||
'Ŭ' => 'U',
|
||||
'ŭ' => 'u',
|
||||
'Ů' => 'U',
|
||||
'ů' => 'u',
|
||||
'Ű' => 'U',
|
||||
'ű' => 'u',
|
||||
'Ų' => 'U',
|
||||
'ų' => 'u',
|
||||
'Ŵ' => 'W',
|
||||
'ŵ' => 'w',
|
||||
'Ŷ' => 'Y',
|
||||
'ŷ' => 'y',
|
||||
'Ÿ' => 'Y',
|
||||
'Ź' => 'Z',
|
||||
'ź' => 'z',
|
||||
'Ż' => 'Z',
|
||||
'ż' => 'z',
|
||||
'Ž' => 'Z',
|
||||
'ž' => 'z',
|
||||
'ſ' => 's',
|
||||
'€' => 'E',
|
||||
'£' => '',
|
||||
];
|
||||
|
||||
/** @var WordInflector */
|
||||
private $singularizer;
|
||||
|
||||
/** @var WordInflector */
|
||||
private $pluralizer;
|
||||
|
||||
public function __construct(WordInflector $singularizer, WordInflector $pluralizer)
|
||||
{
|
||||
$this->singularizer = $singularizer;
|
||||
$this->pluralizer = $pluralizer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a word into the format for a Doctrine table name. Converts 'ModelName' to 'model_name'.
|
||||
*/
|
||||
public function tableize(string $word) : string
|
||||
{
|
||||
$tableized = preg_replace('~(?<=\\w)([A-Z])~u', '_$1', $word);
|
||||
|
||||
if ($tableized === null) {
|
||||
throw new RuntimeException(sprintf(
|
||||
'preg_replace returned null for value "%s"',
|
||||
$word
|
||||
));
|
||||
}
|
||||
|
||||
return mb_strtolower($tableized);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a word into the format for a Doctrine class name. Converts 'table_name' to 'TableName'.
|
||||
*/
|
||||
public function classify(string $word) : string
|
||||
{
|
||||
return str_replace([' ', '_', '-'], '', ucwords($word, ' _-'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Camelizes a word. This uses the classify() method and turns the first character to lowercase.
|
||||
*/
|
||||
public function camelize(string $word) : string
|
||||
{
|
||||
return lcfirst($this->classify($word));
|
||||
}
|
||||
|
||||
/**
|
||||
* Uppercases words with configurable delimiters between words.
|
||||
*
|
||||
* Takes a string and capitalizes all of the words, like PHP's built-in
|
||||
* ucwords function. This extends that behavior, however, by allowing the
|
||||
* word delimiters to be configured, rather than only separating on
|
||||
* whitespace.
|
||||
*
|
||||
* Here is an example:
|
||||
* <code>
|
||||
* <?php
|
||||
* $string = 'top-o-the-morning to all_of_you!';
|
||||
* echo $inflector->capitalize($string);
|
||||
* // Top-O-The-Morning To All_of_you!
|
||||
*
|
||||
* echo $inflector->capitalize($string, '-_ ');
|
||||
* // Top-O-The-Morning To All_Of_You!
|
||||
* ?>
|
||||
* </code>
|
||||
*
|
||||
* @param string $string The string to operate on.
|
||||
* @param string $delimiters A list of word separators.
|
||||
*
|
||||
* @return string The string with all delimiter-separated words capitalized.
|
||||
*/
|
||||
public function capitalize(string $string, string $delimiters = " \n\t\r\0\x0B-") : string
|
||||
{
|
||||
return ucwords($string, $delimiters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given string seems like it has utf8 characters in it.
|
||||
*
|
||||
* @param string $string The string to check for utf8 characters in.
|
||||
*/
|
||||
public function seemsUtf8(string $string) : bool
|
||||
{
|
||||
for ($i = 0; $i < strlen($string); $i++) {
|
||||
if (ord($string[$i]) < 0x80) {
|
||||
continue; // 0bbbbbbb
|
||||
}
|
||||
|
||||
if ((ord($string[$i]) & 0xE0) === 0xC0) {
|
||||
$n = 1; // 110bbbbb
|
||||
} elseif ((ord($string[$i]) & 0xF0) === 0xE0) {
|
||||
$n = 2; // 1110bbbb
|
||||
} elseif ((ord($string[$i]) & 0xF8) === 0xF0) {
|
||||
$n = 3; // 11110bbb
|
||||
} elseif ((ord($string[$i]) & 0xFC) === 0xF8) {
|
||||
$n = 4; // 111110bb
|
||||
} elseif ((ord($string[$i]) & 0xFE) === 0xFC) {
|
||||
$n = 5; // 1111110b
|
||||
} else {
|
||||
return false; // Does not match any model
|
||||
}
|
||||
|
||||
for ($j = 0; $j < $n; $j++) { // n bytes matching 10bbbbbb follow ?
|
||||
if (++$i === strlen($string) || ((ord($string[$i]) & 0xC0) !== 0x80)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove any illegal characters, accents, etc.
|
||||
*
|
||||
* @param string $string String to unaccent
|
||||
*
|
||||
* @return string Unaccented string
|
||||
*/
|
||||
public function unaccent(string $string) : string
|
||||
{
|
||||
if (preg_match('/[\x80-\xff]/', $string) === false) {
|
||||
return $string;
|
||||
}
|
||||
|
||||
if ($this->seemsUtf8($string)) {
|
||||
$string = strtr($string, self::ACCENTED_CHARACTERS);
|
||||
} else {
|
||||
$characters = [];
|
||||
|
||||
// Assume ISO-8859-1 if not UTF-8
|
||||
$characters['in'] =
|
||||
chr(128)
|
||||
. chr(131)
|
||||
. chr(138)
|
||||
. chr(142)
|
||||
. chr(154)
|
||||
. chr(158)
|
||||
. chr(159)
|
||||
. chr(162)
|
||||
. chr(165)
|
||||
. chr(181)
|
||||
. chr(192)
|
||||
. chr(193)
|
||||
. chr(194)
|
||||
. chr(195)
|
||||
. chr(196)
|
||||
. chr(197)
|
||||
. chr(199)
|
||||
. chr(200)
|
||||
. chr(201)
|
||||
. chr(202)
|
||||
. chr(203)
|
||||
. chr(204)
|
||||
. chr(205)
|
||||
. chr(206)
|
||||
. chr(207)
|
||||
. chr(209)
|
||||
. chr(210)
|
||||
. chr(211)
|
||||
. chr(212)
|
||||
. chr(213)
|
||||
. chr(214)
|
||||
. chr(216)
|
||||
. chr(217)
|
||||
. chr(218)
|
||||
. chr(219)
|
||||
. chr(220)
|
||||
. chr(221)
|
||||
. chr(224)
|
||||
. chr(225)
|
||||
. chr(226)
|
||||
. chr(227)
|
||||
. chr(228)
|
||||
. chr(229)
|
||||
. chr(231)
|
||||
. chr(232)
|
||||
. chr(233)
|
||||
. chr(234)
|
||||
. chr(235)
|
||||
. chr(236)
|
||||
. chr(237)
|
||||
. chr(238)
|
||||
. chr(239)
|
||||
. chr(241)
|
||||
. chr(242)
|
||||
. chr(243)
|
||||
. chr(244)
|
||||
. chr(245)
|
||||
. chr(246)
|
||||
. chr(248)
|
||||
. chr(249)
|
||||
. chr(250)
|
||||
. chr(251)
|
||||
. chr(252)
|
||||
. chr(253)
|
||||
. chr(255);
|
||||
|
||||
$characters['out'] = 'EfSZszYcYuAAAAAACEEEEIIIINOOOOOOUUUUYaaaaaaceeeeiiiinoooooouuuuyy';
|
||||
|
||||
$string = strtr($string, $characters['in'], $characters['out']);
|
||||
|
||||
$doubleChars = [];
|
||||
|
||||
$doubleChars['in'] = [
|
||||
chr(140),
|
||||
chr(156),
|
||||
chr(198),
|
||||
chr(208),
|
||||
chr(222),
|
||||
chr(223),
|
||||
chr(230),
|
||||
chr(240),
|
||||
chr(254),
|
||||
];
|
||||
|
||||
$doubleChars['out'] = ['OE', 'oe', 'AE', 'DH', 'TH', 'ss', 'ae', 'dh', 'th'];
|
||||
|
||||
$string = str_replace($doubleChars['in'], $doubleChars['out'], $string);
|
||||
}
|
||||
|
||||
return $string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert any passed string to a url friendly string.
|
||||
* Converts 'My first blog post' to 'my-first-blog-post'
|
||||
*
|
||||
* @param string $string String to urlize.
|
||||
*
|
||||
* @return string Urlized string.
|
||||
*/
|
||||
public function urlize(string $string) : string
|
||||
{
|
||||
// Remove all non url friendly characters with the unaccent function
|
||||
$unaccented = $this->unaccent($string);
|
||||
|
||||
if (function_exists('mb_strtolower')) {
|
||||
$lowered = mb_strtolower($unaccented);
|
||||
} else {
|
||||
$lowered = strtolower($unaccented);
|
||||
}
|
||||
|
||||
$replacements = [
|
||||
'/\W/' => ' ',
|
||||
'/([A-Z]+)([A-Z][a-z])/' => '\1_\2',
|
||||
'/([a-z\d])([A-Z])/' => '\1_\2',
|
||||
'/[^A-Z^a-z^0-9^\/]+/' => '-',
|
||||
];
|
||||
|
||||
$urlized = $lowered;
|
||||
|
||||
foreach ($replacements as $pattern => $replacement) {
|
||||
$replaced = preg_replace($pattern, $replacement, $urlized);
|
||||
|
||||
if ($replaced === null) {
|
||||
throw new RuntimeException(sprintf(
|
||||
'preg_replace returned null for value "%s"',
|
||||
$urlized
|
||||
));
|
||||
}
|
||||
|
||||
$urlized = $replaced;
|
||||
}
|
||||
|
||||
return trim($urlized, '-');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a word in singular form.
|
||||
*
|
||||
* @param string $word The word in plural form.
|
||||
*
|
||||
* @return string The word in singular form.
|
||||
*/
|
||||
public function singularize(string $word) : string
|
||||
{
|
||||
return $this->singularizer->inflect($word);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a word in plural form.
|
||||
*
|
||||
* @param string $word The word in singular form.
|
||||
*
|
||||
* @return string The word in plural form.
|
||||
*/
|
||||
public function pluralize(string $word) : string
|
||||
{
|
||||
return $this->pluralizer->inflect($word);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector;
|
||||
|
||||
use Doctrine\Inflector\Rules\English;
|
||||
use Doctrine\Inflector\Rules\French;
|
||||
use Doctrine\Inflector\Rules\NorwegianBokmal;
|
||||
use Doctrine\Inflector\Rules\Portuguese;
|
||||
use Doctrine\Inflector\Rules\Spanish;
|
||||
use Doctrine\Inflector\Rules\Turkish;
|
||||
use InvalidArgumentException;
|
||||
use function sprintf;
|
||||
|
||||
final class InflectorFactory
|
||||
{
|
||||
public static function create() : LanguageInflectorFactory
|
||||
{
|
||||
return self::createForLanguage(Language::ENGLISH);
|
||||
}
|
||||
|
||||
public static function createForLanguage(string $language) : LanguageInflectorFactory
|
||||
{
|
||||
switch ($language) {
|
||||
case Language::ENGLISH:
|
||||
return new English\InflectorFactory();
|
||||
case Language::FRENCH:
|
||||
return new French\InflectorFactory();
|
||||
case Language::NORWEGIAN_BOKMAL:
|
||||
return new NorwegianBokmal\InflectorFactory();
|
||||
case Language::PORTUGUESE:
|
||||
return new Portuguese\InflectorFactory();
|
||||
case Language::SPANISH:
|
||||
return new Spanish\InflectorFactory();
|
||||
case Language::TURKISH:
|
||||
return new Turkish\InflectorFactory();
|
||||
default:
|
||||
throw new InvalidArgumentException(sprintf(
|
||||
'Language "%s" is not supported.',
|
||||
$language
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector;
|
||||
|
||||
final class Language
|
||||
{
|
||||
public const ENGLISH = 'english';
|
||||
public const FRENCH = 'french';
|
||||
public const NORWEGIAN_BOKMAL = 'norwegian-bokmal';
|
||||
public const PORTUGUESE = 'portuguese';
|
||||
public const SPANISH = 'spanish';
|
||||
public const TURKISH = 'turkish';
|
||||
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector;
|
||||
|
||||
use Doctrine\Inflector\Rules\Ruleset;
|
||||
|
||||
interface LanguageInflectorFactory
|
||||
{
|
||||
/**
|
||||
* Applies custom rules for singularisation
|
||||
*
|
||||
* @param bool $reset If true, will unset default inflections for all new rules
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function withSingularRules(?Ruleset $singularRules, bool $reset = false) : self;
|
||||
|
||||
/**
|
||||
* Applies custom rules for pluralisation
|
||||
*
|
||||
* @param bool $reset If true, will unset default inflections for all new rules
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function withPluralRules(?Ruleset $pluralRules, bool $reset = false) : self;
|
||||
|
||||
/**
|
||||
* Builds the inflector instance with all applicable rules
|
||||
*/
|
||||
public function build() : Inflector;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector;
|
||||
|
||||
class NoopWordInflector implements WordInflector
|
||||
{
|
||||
public function inflect(string $word) : string
|
||||
{
|
||||
return $word;
|
||||
}
|
||||
}
|
||||
+182
@@ -0,0 +1,182 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector\Rules\English;
|
||||
|
||||
use Doctrine\Inflector\Rules\Pattern;
|
||||
use Doctrine\Inflector\Rules\Substitution;
|
||||
use Doctrine\Inflector\Rules\Transformation;
|
||||
use Doctrine\Inflector\Rules\Word;
|
||||
|
||||
class Inflectible
|
||||
{
|
||||
/**
|
||||
* @return Transformation[]
|
||||
*/
|
||||
public static function getSingular() : iterable
|
||||
{
|
||||
yield new Transformation(new Pattern('(s)tatuses$'), '\1\2tatus');
|
||||
yield new Transformation(new Pattern('(s)tatus$'), '\1\2tatus');
|
||||
yield new Transformation(new Pattern('(c)ampus$'), '\1\2ampus');
|
||||
yield new Transformation(new Pattern('^(.*)(menu)s$'), '\1\2');
|
||||
yield new Transformation(new Pattern('(quiz)zes$'), '\\1');
|
||||
yield new Transformation(new Pattern('(matr)ices$'), '\1ix');
|
||||
yield new Transformation(new Pattern('(vert|ind)ices$'), '\1ex');
|
||||
yield new Transformation(new Pattern('^(ox)en'), '\1');
|
||||
yield new Transformation(new Pattern('(alias)(es)*$'), '\1');
|
||||
yield new Transformation(new Pattern('(buffal|her|potat|tomat|volcan)oes$'), '\1o');
|
||||
yield new Transformation(new Pattern('(alumn|bacill|cact|foc|fung|nucle|radi|stimul|syllab|termin|viri?)i$'), '\1us');
|
||||
yield new Transformation(new Pattern('([ftw]ax)es'), '\1');
|
||||
yield new Transformation(new Pattern('(analys|ax|cris|test|thes)es$'), '\1is');
|
||||
yield new Transformation(new Pattern('(shoe|slave)s$'), '\1');
|
||||
yield new Transformation(new Pattern('(o)es$'), '\1');
|
||||
yield new Transformation(new Pattern('ouses$'), 'ouse');
|
||||
yield new Transformation(new Pattern('([^a])uses$'), '\1us');
|
||||
yield new Transformation(new Pattern('([m|l])ice$'), '\1ouse');
|
||||
yield new Transformation(new Pattern('(x|ch|ss|sh)es$'), '\1');
|
||||
yield new Transformation(new Pattern('(m)ovies$'), '\1\2ovie');
|
||||
yield new Transformation(new Pattern('(s)eries$'), '\1\2eries');
|
||||
yield new Transformation(new Pattern('([^aeiouy]|qu)ies$'), '\1y');
|
||||
yield new Transformation(new Pattern('([lr])ves$'), '\1f');
|
||||
yield new Transformation(new Pattern('(tive)s$'), '\1');
|
||||
yield new Transformation(new Pattern('(hive)s$'), '\1');
|
||||
yield new Transformation(new Pattern('(drive)s$'), '\1');
|
||||
yield new Transformation(new Pattern('(dive)s$'), '\1');
|
||||
yield new Transformation(new Pattern('(olive)s$'), '\1');
|
||||
yield new Transformation(new Pattern('([^fo])ves$'), '\1fe');
|
||||
yield new Transformation(new Pattern('(^analy)ses$'), '\1sis');
|
||||
yield new Transformation(new Pattern('(analy|diagno|^ba|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$'), '\1\2sis');
|
||||
yield new Transformation(new Pattern('(tax)a$'), '\1on');
|
||||
yield new Transformation(new Pattern('(c)riteria$'), '\1riterion');
|
||||
yield new Transformation(new Pattern('([ti])a$'), '\1um');
|
||||
yield new Transformation(new Pattern('(p)eople$'), '\1\2erson');
|
||||
yield new Transformation(new Pattern('(m)en$'), '\1an');
|
||||
yield new Transformation(new Pattern('(c)hildren$'), '\1\2hild');
|
||||
yield new Transformation(new Pattern('(f)eet$'), '\1oot');
|
||||
yield new Transformation(new Pattern('(n)ews$'), '\1\2ews');
|
||||
yield new Transformation(new Pattern('eaus$'), 'eau');
|
||||
yield new Transformation(new Pattern('s$'), '');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Transformation[]
|
||||
*/
|
||||
public static function getPlural() : iterable
|
||||
{
|
||||
yield new Transformation(new Pattern('(s)tatus$'), '\1\2tatuses');
|
||||
yield new Transformation(new Pattern('(quiz)$'), '\1zes');
|
||||
yield new Transformation(new Pattern('^(ox)$'), '\1\2en');
|
||||
yield new Transformation(new Pattern('([m|l])ouse$'), '\1ice');
|
||||
yield new Transformation(new Pattern('(matr|vert|ind)(ix|ex)$'), '\1ices');
|
||||
yield new Transformation(new Pattern('(x|ch|ss|sh)$'), '\1es');
|
||||
yield new Transformation(new Pattern('([^aeiouy]|qu)y$'), '\1ies');
|
||||
yield new Transformation(new Pattern('(hive|gulf)$'), '\1s');
|
||||
yield new Transformation(new Pattern('(?:([^f])fe|([lr])f)$'), '\1\2ves');
|
||||
yield new Transformation(new Pattern('sis$'), 'ses');
|
||||
yield new Transformation(new Pattern('([ti])um$'), '\1a');
|
||||
yield new Transformation(new Pattern('(tax)on$'), '\1a');
|
||||
yield new Transformation(new Pattern('(c)riterion$'), '\1riteria');
|
||||
yield new Transformation(new Pattern('(p)erson$'), '\1eople');
|
||||
yield new Transformation(new Pattern('(m)an$'), '\1en');
|
||||
yield new Transformation(new Pattern('(c)hild$'), '\1hildren');
|
||||
yield new Transformation(new Pattern('(f)oot$'), '\1eet');
|
||||
yield new Transformation(new Pattern('(buffal|her|potat|tomat|volcan)o$'), '\1\2oes');
|
||||
yield new Transformation(new Pattern('(alumn|bacill|cact|foc|fung|nucle|radi|stimul|syllab|termin|vir)us$'), '\1i');
|
||||
yield new Transformation(new Pattern('us$'), 'uses');
|
||||
yield new Transformation(new Pattern('(alias)$'), '\1es');
|
||||
yield new Transformation(new Pattern('(analys|ax|cris|test|thes)is$'), '\1es');
|
||||
yield new Transformation(new Pattern('s$'), 's');
|
||||
yield new Transformation(new Pattern('^$'), '');
|
||||
yield new Transformation(new Pattern('$'), 's');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Substitution[]
|
||||
*/
|
||||
public static function getIrregular() : iterable
|
||||
{
|
||||
yield new Substitution(new Word('atlas'), new Word('atlases'));
|
||||
yield new Substitution(new Word('axe'), new Word('axes'));
|
||||
yield new Substitution(new Word('beef'), new Word('beefs'));
|
||||
yield new Substitution(new Word('brother'), new Word('brothers'));
|
||||
yield new Substitution(new Word('cafe'), new Word('cafes'));
|
||||
yield new Substitution(new Word('chateau'), new Word('chateaux'));
|
||||
yield new Substitution(new Word('niveau'), new Word('niveaux'));
|
||||
yield new Substitution(new Word('child'), new Word('children'));
|
||||
yield new Substitution(new Word('canvas'), new Word('canvases'));
|
||||
yield new Substitution(new Word('cookie'), new Word('cookies'));
|
||||
yield new Substitution(new Word('corpus'), new Word('corpuses'));
|
||||
yield new Substitution(new Word('cow'), new Word('cows'));
|
||||
yield new Substitution(new Word('criterion'), new Word('criteria'));
|
||||
yield new Substitution(new Word('curriculum'), new Word('curricula'));
|
||||
yield new Substitution(new Word('demo'), new Word('demos'));
|
||||
yield new Substitution(new Word('domino'), new Word('dominoes'));
|
||||
yield new Substitution(new Word('echo'), new Word('echoes'));
|
||||
yield new Substitution(new Word('foot'), new Word('feet'));
|
||||
yield new Substitution(new Word('fungus'), new Word('fungi'));
|
||||
yield new Substitution(new Word('ganglion'), new Word('ganglions'));
|
||||
yield new Substitution(new Word('gas'), new Word('gases'));
|
||||
yield new Substitution(new Word('genie'), new Word('genies'));
|
||||
yield new Substitution(new Word('genus'), new Word('genera'));
|
||||
yield new Substitution(new Word('goose'), new Word('geese'));
|
||||
yield new Substitution(new Word('graffito'), new Word('graffiti'));
|
||||
yield new Substitution(new Word('hippopotamus'), new Word('hippopotami'));
|
||||
yield new Substitution(new Word('hoof'), new Word('hoofs'));
|
||||
yield new Substitution(new Word('human'), new Word('humans'));
|
||||
yield new Substitution(new Word('iris'), new Word('irises'));
|
||||
yield new Substitution(new Word('larva'), new Word('larvae'));
|
||||
yield new Substitution(new Word('leaf'), new Word('leaves'));
|
||||
yield new Substitution(new Word('lens'), new Word('lenses'));
|
||||
yield new Substitution(new Word('loaf'), new Word('loaves'));
|
||||
yield new Substitution(new Word('man'), new Word('men'));
|
||||
yield new Substitution(new Word('medium'), new Word('media'));
|
||||
yield new Substitution(new Word('memorandum'), new Word('memoranda'));
|
||||
yield new Substitution(new Word('money'), new Word('monies'));
|
||||
yield new Substitution(new Word('mongoose'), new Word('mongooses'));
|
||||
yield new Substitution(new Word('motto'), new Word('mottoes'));
|
||||
yield new Substitution(new Word('move'), new Word('moves'));
|
||||
yield new Substitution(new Word('mythos'), new Word('mythoi'));
|
||||
yield new Substitution(new Word('niche'), new Word('niches'));
|
||||
yield new Substitution(new Word('nucleus'), new Word('nuclei'));
|
||||
yield new Substitution(new Word('numen'), new Word('numina'));
|
||||
yield new Substitution(new Word('occiput'), new Word('occiputs'));
|
||||
yield new Substitution(new Word('octopus'), new Word('octopuses'));
|
||||
yield new Substitution(new Word('opus'), new Word('opuses'));
|
||||
yield new Substitution(new Word('ox'), new Word('oxen'));
|
||||
yield new Substitution(new Word('passerby'), new Word('passersby'));
|
||||
yield new Substitution(new Word('penis'), new Word('penises'));
|
||||
yield new Substitution(new Word('person'), new Word('people'));
|
||||
yield new Substitution(new Word('plateau'), new Word('plateaux'));
|
||||
yield new Substitution(new Word('runner-up'), new Word('runners-up'));
|
||||
yield new Substitution(new Word('safe'), new Word('safes'));
|
||||
yield new Substitution(new Word('sex'), new Word('sexes'));
|
||||
yield new Substitution(new Word('soliloquy'), new Word('soliloquies'));
|
||||
yield new Substitution(new Word('son-in-law'), new Word('sons-in-law'));
|
||||
yield new Substitution(new Word('syllabus'), new Word('syllabi'));
|
||||
yield new Substitution(new Word('testis'), new Word('testes'));
|
||||
yield new Substitution(new Word('thief'), new Word('thieves'));
|
||||
yield new Substitution(new Word('tooth'), new Word('teeth'));
|
||||
yield new Substitution(new Word('tornado'), new Word('tornadoes'));
|
||||
yield new Substitution(new Word('trilby'), new Word('trilbys'));
|
||||
yield new Substitution(new Word('turf'), new Word('turfs'));
|
||||
yield new Substitution(new Word('valve'), new Word('valves'));
|
||||
yield new Substitution(new Word('volcano'), new Word('volcanoes'));
|
||||
yield new Substitution(new Word('abuse'), new Word('abuses'));
|
||||
yield new Substitution(new Word('avalanche'), new Word('avalanches'));
|
||||
yield new Substitution(new Word('cache'), new Word('caches'));
|
||||
yield new Substitution(new Word('criterion'), new Word('criteria'));
|
||||
yield new Substitution(new Word('curve'), new Word('curves'));
|
||||
yield new Substitution(new Word('emphasis'), new Word('emphases'));
|
||||
yield new Substitution(new Word('foe'), new Word('foes'));
|
||||
yield new Substitution(new Word('grave'), new Word('graves'));
|
||||
yield new Substitution(new Word('hoax'), new Word('hoaxes'));
|
||||
yield new Substitution(new Word('medium'), new Word('media'));
|
||||
yield new Substitution(new Word('neurosis'), new Word('neuroses'));
|
||||
yield new Substitution(new Word('save'), new Word('saves'));
|
||||
yield new Substitution(new Word('wave'), new Word('waves'));
|
||||
yield new Substitution(new Word('oasis'), new Word('oases'));
|
||||
yield new Substitution(new Word('valve'), new Word('valves'));
|
||||
yield new Substitution(new Word('zombie'), new Word('zombies'));
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector\Rules\English;
|
||||
|
||||
use Doctrine\Inflector\GenericLanguageInflectorFactory;
|
||||
use Doctrine\Inflector\Rules\Ruleset;
|
||||
|
||||
final class InflectorFactory extends GenericLanguageInflectorFactory
|
||||
{
|
||||
protected function getSingularRuleset() : Ruleset
|
||||
{
|
||||
return Rules::getSingularRuleset();
|
||||
}
|
||||
|
||||
protected function getPluralRuleset() : Ruleset
|
||||
{
|
||||
return Rules::getPluralRuleset();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector\Rules\English;
|
||||
|
||||
use Doctrine\Inflector\Rules\Patterns;
|
||||
use Doctrine\Inflector\Rules\Ruleset;
|
||||
use Doctrine\Inflector\Rules\Substitutions;
|
||||
use Doctrine\Inflector\Rules\Transformations;
|
||||
|
||||
final class Rules
|
||||
{
|
||||
public static function getSingularRuleset() : Ruleset
|
||||
{
|
||||
return new Ruleset(
|
||||
new Transformations(...Inflectible::getSingular()),
|
||||
new Patterns(...Uninflected::getSingular()),
|
||||
(new Substitutions(...Inflectible::getIrregular()))->getFlippedSubstitutions()
|
||||
);
|
||||
}
|
||||
|
||||
public static function getPluralRuleset() : Ruleset
|
||||
{
|
||||
return new Ruleset(
|
||||
new Transformations(...Inflectible::getPlural()),
|
||||
new Patterns(...Uninflected::getPlural()),
|
||||
new Substitutions(...Inflectible::getIrregular())
|
||||
);
|
||||
}
|
||||
}
|
||||
+193
@@ -0,0 +1,193 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector\Rules\English;
|
||||
|
||||
use Doctrine\Inflector\Rules\Pattern;
|
||||
|
||||
final class Uninflected
|
||||
{
|
||||
/**
|
||||
* @return Pattern[]
|
||||
*/
|
||||
public static function getSingular() : iterable
|
||||
{
|
||||
yield from self::getDefault();
|
||||
|
||||
yield new Pattern('.*ss');
|
||||
yield new Pattern('clothes');
|
||||
yield new Pattern('data');
|
||||
yield new Pattern('fascia');
|
||||
yield new Pattern('fuchsia');
|
||||
yield new Pattern('galleria');
|
||||
yield new Pattern('mafia');
|
||||
yield new Pattern('militia');
|
||||
yield new Pattern('pants');
|
||||
yield new Pattern('petunia');
|
||||
yield new Pattern('sepia');
|
||||
yield new Pattern('trivia');
|
||||
yield new Pattern('utopia');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Pattern[]
|
||||
*/
|
||||
public static function getPlural() : iterable
|
||||
{
|
||||
yield from self::getDefault();
|
||||
|
||||
yield new Pattern('people');
|
||||
yield new Pattern('trivia');
|
||||
yield new Pattern('\w+ware$');
|
||||
yield new Pattern('media');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Pattern[]
|
||||
*/
|
||||
private static function getDefault() : iterable
|
||||
{
|
||||
yield new Pattern('\w+media');
|
||||
yield new Pattern('advice');
|
||||
yield new Pattern('aircraft');
|
||||
yield new Pattern('amoyese');
|
||||
yield new Pattern('art');
|
||||
yield new Pattern('audio');
|
||||
yield new Pattern('baggage');
|
||||
yield new Pattern('bison');
|
||||
yield new Pattern('borghese');
|
||||
yield new Pattern('bream');
|
||||
yield new Pattern('breeches');
|
||||
yield new Pattern('britches');
|
||||
yield new Pattern('buffalo');
|
||||
yield new Pattern('butter');
|
||||
yield new Pattern('cantus');
|
||||
yield new Pattern('carp');
|
||||
yield new Pattern('chassis');
|
||||
yield new Pattern('clippers');
|
||||
yield new Pattern('clothing');
|
||||
yield new Pattern('coal');
|
||||
yield new Pattern('cod');
|
||||
yield new Pattern('coitus');
|
||||
yield new Pattern('compensation');
|
||||
yield new Pattern('congoese');
|
||||
yield new Pattern('contretemps');
|
||||
yield new Pattern('coreopsis');
|
||||
yield new Pattern('corps');
|
||||
yield new Pattern('cotton');
|
||||
yield new Pattern('data');
|
||||
yield new Pattern('debris');
|
||||
yield new Pattern('deer');
|
||||
yield new Pattern('diabetes');
|
||||
yield new Pattern('djinn');
|
||||
yield new Pattern('education');
|
||||
yield new Pattern('eland');
|
||||
yield new Pattern('elk');
|
||||
yield new Pattern('emoji');
|
||||
yield new Pattern('equipment');
|
||||
yield new Pattern('evidence');
|
||||
yield new Pattern('faroese');
|
||||
yield new Pattern('feedback');
|
||||
yield new Pattern('fish');
|
||||
yield new Pattern('flounder');
|
||||
yield new Pattern('flour');
|
||||
yield new Pattern('foochowese');
|
||||
yield new Pattern('food');
|
||||
yield new Pattern('furniture');
|
||||
yield new Pattern('gallows');
|
||||
yield new Pattern('genevese');
|
||||
yield new Pattern('genoese');
|
||||
yield new Pattern('gilbertese');
|
||||
yield new Pattern('gold');
|
||||
yield new Pattern('headquarters');
|
||||
yield new Pattern('herpes');
|
||||
yield new Pattern('hijinks');
|
||||
yield new Pattern('homework');
|
||||
yield new Pattern('hottentotese');
|
||||
yield new Pattern('impatience');
|
||||
yield new Pattern('information');
|
||||
yield new Pattern('innings');
|
||||
yield new Pattern('jackanapes');
|
||||
yield new Pattern('jeans');
|
||||
yield new Pattern('jedi');
|
||||
yield new Pattern('kiplingese');
|
||||
yield new Pattern('knowledge');
|
||||
yield new Pattern('kongoese');
|
||||
yield new Pattern('leather');
|
||||
yield new Pattern('love');
|
||||
yield new Pattern('lucchese');
|
||||
yield new Pattern('luggage');
|
||||
yield new Pattern('mackerel');
|
||||
yield new Pattern('Maltese');
|
||||
yield new Pattern('management');
|
||||
yield new Pattern('metadata');
|
||||
yield new Pattern('mews');
|
||||
yield new Pattern('money');
|
||||
yield new Pattern('moose');
|
||||
yield new Pattern('mumps');
|
||||
yield new Pattern('music');
|
||||
yield new Pattern('nankingese');
|
||||
yield new Pattern('news');
|
||||
yield new Pattern('nexus');
|
||||
yield new Pattern('niasese');
|
||||
yield new Pattern('nutrition');
|
||||
yield new Pattern('offspring');
|
||||
yield new Pattern('oil');
|
||||
yield new Pattern('patience');
|
||||
yield new Pattern('pekingese');
|
||||
yield new Pattern('piedmontese');
|
||||
yield new Pattern('pincers');
|
||||
yield new Pattern('pistoiese');
|
||||
yield new Pattern('plankton');
|
||||
yield new Pattern('pliers');
|
||||
yield new Pattern('pokemon');
|
||||
yield new Pattern('police');
|
||||
yield new Pattern('polish');
|
||||
yield new Pattern('portuguese');
|
||||
yield new Pattern('proceedings');
|
||||
yield new Pattern('progress');
|
||||
yield new Pattern('rabies');
|
||||
yield new Pattern('rain');
|
||||
yield new Pattern('research');
|
||||
yield new Pattern('rhinoceros');
|
||||
yield new Pattern('rice');
|
||||
yield new Pattern('salmon');
|
||||
yield new Pattern('sand');
|
||||
yield new Pattern('sarawakese');
|
||||
yield new Pattern('scissors');
|
||||
yield new Pattern('sea[- ]bass');
|
||||
yield new Pattern('series');
|
||||
yield new Pattern('shavese');
|
||||
yield new Pattern('shears');
|
||||
yield new Pattern('sheep');
|
||||
yield new Pattern('siemens');
|
||||
yield new Pattern('silk');
|
||||
yield new Pattern('sms');
|
||||
yield new Pattern('soap');
|
||||
yield new Pattern('social media');
|
||||
yield new Pattern('spam');
|
||||
yield new Pattern('species');
|
||||
yield new Pattern('staff');
|
||||
yield new Pattern('sugar');
|
||||
yield new Pattern('swine');
|
||||
yield new Pattern('talent');
|
||||
yield new Pattern('toothpaste');
|
||||
yield new Pattern('traffic');
|
||||
yield new Pattern('travel');
|
||||
yield new Pattern('trousers');
|
||||
yield new Pattern('trout');
|
||||
yield new Pattern('tuna');
|
||||
yield new Pattern('us');
|
||||
yield new Pattern('vermontese');
|
||||
yield new Pattern('vinegar');
|
||||
yield new Pattern('weather');
|
||||
yield new Pattern('wenchowese');
|
||||
yield new Pattern('wheat');
|
||||
yield new Pattern('whiting');
|
||||
yield new Pattern('wildebeest');
|
||||
yield new Pattern('wood');
|
||||
yield new Pattern('wool');
|
||||
yield new Pattern('yengeese');
|
||||
}
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector\Rules\French;
|
||||
|
||||
use Doctrine\Inflector\Rules\Pattern;
|
||||
use Doctrine\Inflector\Rules\Substitution;
|
||||
use Doctrine\Inflector\Rules\Transformation;
|
||||
use Doctrine\Inflector\Rules\Word;
|
||||
|
||||
class Inflectible
|
||||
{
|
||||
/**
|
||||
* @return Transformation[]
|
||||
*/
|
||||
public static function getSingular() : iterable
|
||||
{
|
||||
yield new Transformation(new Pattern('/(b|cor|ém|gemm|soupir|trav|vant|vitr)aux$/'), '\1ail');
|
||||
yield new Transformation(new Pattern('/ails$/'), 'ail');
|
||||
yield new Transformation(new Pattern('/(journ|chev)aux$/'), '\1al');
|
||||
yield new Transformation(new Pattern('/(bijou|caillou|chou|genou|hibou|joujou|pou|au|eu|eau)x$/'), '\1');
|
||||
yield new Transformation(new Pattern('/s$/'), '');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Transformation[]
|
||||
*/
|
||||
public static function getPlural() : iterable
|
||||
{
|
||||
yield new Transformation(new Pattern('/(s|x|z)$/'), '\1');
|
||||
yield new Transformation(new Pattern('/(b|cor|ém|gemm|soupir|trav|vant|vitr)ail$/'), '\1aux');
|
||||
yield new Transformation(new Pattern('/ail$/'), 'ails');
|
||||
yield new Transformation(new Pattern('/al$/'), 'aux');
|
||||
yield new Transformation(new Pattern('/(bleu|émeu|landau|lieu|pneu|sarrau)$/'), '\1s');
|
||||
yield new Transformation(new Pattern('/(bijou|caillou|chou|genou|hibou|joujou|pou|au|eu|eau)$/'), '\1x');
|
||||
yield new Transformation(new Pattern('/$/'), 's');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Substitution[]
|
||||
*/
|
||||
public static function getIrregular() : iterable
|
||||
{
|
||||
yield new Substitution(new Word('monsieur'), new Word('messieurs'));
|
||||
yield new Substitution(new Word('madame'), new Word('mesdames'));
|
||||
yield new Substitution(new Word('mademoiselle'), new Word('mesdemoiselles'));
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector\Rules\French;
|
||||
|
||||
use Doctrine\Inflector\GenericLanguageInflectorFactory;
|
||||
use Doctrine\Inflector\Rules\Ruleset;
|
||||
|
||||
final class InflectorFactory extends GenericLanguageInflectorFactory
|
||||
{
|
||||
protected function getSingularRuleset() : Ruleset
|
||||
{
|
||||
return Rules::getSingularRuleset();
|
||||
}
|
||||
|
||||
protected function getPluralRuleset() : Ruleset
|
||||
{
|
||||
return Rules::getPluralRuleset();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector\Rules\French;
|
||||
|
||||
use Doctrine\Inflector\Rules\Patterns;
|
||||
use Doctrine\Inflector\Rules\Ruleset;
|
||||
use Doctrine\Inflector\Rules\Substitutions;
|
||||
use Doctrine\Inflector\Rules\Transformations;
|
||||
|
||||
final class Rules
|
||||
{
|
||||
public static function getSingularRuleset() : Ruleset
|
||||
{
|
||||
return new Ruleset(
|
||||
new Transformations(...Inflectible::getSingular()),
|
||||
new Patterns(...Uninflected::getSingular()),
|
||||
(new Substitutions(...Inflectible::getIrregular()))->getFlippedSubstitutions()
|
||||
);
|
||||
}
|
||||
|
||||
public static function getPluralRuleset() : Ruleset
|
||||
{
|
||||
return new Ruleset(
|
||||
new Transformations(...Inflectible::getPlural()),
|
||||
new Patterns(...Uninflected::getPlural()),
|
||||
new Substitutions(...Inflectible::getIrregular())
|
||||
);
|
||||
}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector\Rules\French;
|
||||
|
||||
use Doctrine\Inflector\Rules\Pattern;
|
||||
|
||||
final class Uninflected
|
||||
{
|
||||
/**
|
||||
* @return Pattern[]
|
||||
*/
|
||||
public static function getSingular() : iterable
|
||||
{
|
||||
yield from self::getDefault();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Pattern[]
|
||||
*/
|
||||
public static function getPlural() : iterable
|
||||
{
|
||||
yield from self::getDefault();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Pattern[]
|
||||
*/
|
||||
private static function getDefault() : iterable
|
||||
{
|
||||
yield new Pattern('');
|
||||
}
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector\Rules\NorwegianBokmal;
|
||||
|
||||
use Doctrine\Inflector\Rules\Pattern;
|
||||
use Doctrine\Inflector\Rules\Substitution;
|
||||
use Doctrine\Inflector\Rules\Transformation;
|
||||
use Doctrine\Inflector\Rules\Word;
|
||||
|
||||
class Inflectible
|
||||
{
|
||||
/**
|
||||
* @return Transformation[]
|
||||
*/
|
||||
public static function getSingular() : iterable
|
||||
{
|
||||
yield new Transformation(new Pattern('/re$/i'), 'r');
|
||||
yield new Transformation(new Pattern('/er$/i'), '');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Transformation[]
|
||||
*/
|
||||
public static function getPlural() : iterable
|
||||
{
|
||||
yield new Transformation(new Pattern('/e$/i'), 'er');
|
||||
yield new Transformation(new Pattern('/r$/i'), 're');
|
||||
yield new Transformation(new Pattern('/$/'), 'er');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Substitution[]
|
||||
*/
|
||||
public static function getIrregular() : iterable
|
||||
{
|
||||
yield new Substitution(new Word('konto'), new Word('konti'));
|
||||
}
|
||||
}
|
||||
Vendored
+21
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector\Rules\NorwegianBokmal;
|
||||
|
||||
use Doctrine\Inflector\GenericLanguageInflectorFactory;
|
||||
use Doctrine\Inflector\Rules\Ruleset;
|
||||
|
||||
final class InflectorFactory extends GenericLanguageInflectorFactory
|
||||
{
|
||||
protected function getSingularRuleset() : Ruleset
|
||||
{
|
||||
return Rules::getSingularRuleset();
|
||||
}
|
||||
|
||||
protected function getPluralRuleset() : Ruleset
|
||||
{
|
||||
return Rules::getPluralRuleset();
|
||||
}
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector\Rules\NorwegianBokmal;
|
||||
|
||||
use Doctrine\Inflector\Rules\Patterns;
|
||||
use Doctrine\Inflector\Rules\Ruleset;
|
||||
use Doctrine\Inflector\Rules\Substitutions;
|
||||
use Doctrine\Inflector\Rules\Transformations;
|
||||
|
||||
final class Rules
|
||||
{
|
||||
public static function getSingularRuleset() : Ruleset
|
||||
{
|
||||
return new Ruleset(
|
||||
new Transformations(...Inflectible::getSingular()),
|
||||
new Patterns(...Uninflected::getSingular()),
|
||||
(new Substitutions(...Inflectible::getIrregular()))->getFlippedSubstitutions()
|
||||
);
|
||||
}
|
||||
|
||||
public static function getPluralRuleset() : Ruleset
|
||||
{
|
||||
return new Ruleset(
|
||||
new Transformations(...Inflectible::getPlural()),
|
||||
new Patterns(...Uninflected::getPlural()),
|
||||
new Substitutions(...Inflectible::getIrregular())
|
||||
);
|
||||
}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector\Rules\NorwegianBokmal;
|
||||
|
||||
use Doctrine\Inflector\Rules\Pattern;
|
||||
|
||||
final class Uninflected
|
||||
{
|
||||
/**
|
||||
* @return Pattern[]
|
||||
*/
|
||||
public static function getSingular() : iterable
|
||||
{
|
||||
yield from self::getDefault();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Pattern[]
|
||||
*/
|
||||
public static function getPlural() : iterable
|
||||
{
|
||||
yield from self::getDefault();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Pattern[]
|
||||
*/
|
||||
private static function getDefault() : iterable
|
||||
{
|
||||
yield new Pattern('barn');
|
||||
yield new Pattern('fjell');
|
||||
yield new Pattern('hus');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector\Rules;
|
||||
|
||||
use function preg_match;
|
||||
|
||||
final class Pattern
|
||||
{
|
||||
/** @var string */
|
||||
private $pattern;
|
||||
|
||||
/** @var string */
|
||||
private $regex;
|
||||
|
||||
public function __construct(string $pattern)
|
||||
{
|
||||
$this->pattern = $pattern;
|
||||
|
||||
if (isset($this->pattern[0]) && $this->pattern[0] === '/') {
|
||||
$this->regex = $this->pattern;
|
||||
} else {
|
||||
$this->regex = '/' . $this->pattern . '/i';
|
||||
}
|
||||
}
|
||||
|
||||
public function getPattern() : string
|
||||
{
|
||||
return $this->pattern;
|
||||
}
|
||||
|
||||
public function getRegex() : string
|
||||
{
|
||||
return $this->regex;
|
||||
}
|
||||
|
||||
public function matches(string $word) : bool
|
||||
{
|
||||
return preg_match($this->getRegex(), $word) === 1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector\Rules;
|
||||
|
||||
use function array_map;
|
||||
use function implode;
|
||||
use function preg_match;
|
||||
|
||||
class Patterns
|
||||
{
|
||||
/** @var Pattern[] */
|
||||
private $patterns;
|
||||
|
||||
/** @var string */
|
||||
private $regex;
|
||||
|
||||
public function __construct(Pattern ...$patterns)
|
||||
{
|
||||
$this->patterns = $patterns;
|
||||
|
||||
$patterns = array_map(static function (Pattern $pattern) : string {
|
||||
return $pattern->getPattern();
|
||||
}, $this->patterns);
|
||||
|
||||
$this->regex = '/^(?:' . implode('|', $patterns) . ')$/i';
|
||||
}
|
||||
|
||||
public function matches(string $word) : bool
|
||||
{
|
||||
return preg_match($this->regex, $word, $regs) === 1;
|
||||
}
|
||||
}
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector\Rules\Portuguese;
|
||||
|
||||
use Doctrine\Inflector\Rules\Pattern;
|
||||
use Doctrine\Inflector\Rules\Substitution;
|
||||
use Doctrine\Inflector\Rules\Transformation;
|
||||
use Doctrine\Inflector\Rules\Word;
|
||||
|
||||
class Inflectible
|
||||
{
|
||||
/**
|
||||
* @return Transformation[]
|
||||
*/
|
||||
public static function getSingular() : iterable
|
||||
{
|
||||
yield new Transformation(new Pattern('/^(g|)ases$/i'), '\1ás');
|
||||
yield new Transformation(new Pattern('/(japon|escoc|ingl|dinamarqu|fregu|portugu)eses$/i'), '\1ês');
|
||||
yield new Transformation(new Pattern('/(ae|ao|oe)s$/'), 'ao');
|
||||
yield new Transformation(new Pattern('/(ãe|ão|õe)s$/'), 'ão');
|
||||
yield new Transformation(new Pattern('/^(.*[^s]s)es$/i'), '\1');
|
||||
yield new Transformation(new Pattern('/sses$/i'), 'sse');
|
||||
yield new Transformation(new Pattern('/ns$/i'), 'm');
|
||||
yield new Transformation(new Pattern('/(r|t|f|v)is$/i'), '\1il');
|
||||
yield new Transformation(new Pattern('/uis$/i'), 'ul');
|
||||
yield new Transformation(new Pattern('/ois$/i'), 'ol');
|
||||
yield new Transformation(new Pattern('/eis$/i'), 'ei');
|
||||
yield new Transformation(new Pattern('/éis$/i'), 'el');
|
||||
yield new Transformation(new Pattern('/([^p])ais$/i'), '\1al');
|
||||
yield new Transformation(new Pattern('/(r|z)es$/i'), '\1');
|
||||
yield new Transformation(new Pattern('/^(á|gá)s$/i'), '\1s');
|
||||
yield new Transformation(new Pattern('/([^ê])s$/i'), '\1');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Transformation[]
|
||||
*/
|
||||
public static function getPlural() : iterable
|
||||
{
|
||||
yield new Transformation(new Pattern('/^(alem|c|p)ao$/i'), '\1aes');
|
||||
yield new Transformation(new Pattern('/^(irm|m)ao$/i'), '\1aos');
|
||||
yield new Transformation(new Pattern('/ao$/i'), 'oes');
|
||||
yield new Transformation(new Pattern('/^(alem|c|p)ão$/i'), '\1ães');
|
||||
yield new Transformation(new Pattern('/^(irm|m)ão$/i'), '\1ãos');
|
||||
yield new Transformation(new Pattern('/ão$/i'), 'ões');
|
||||
yield new Transformation(new Pattern('/^(|g)ás$/i'), '\1ases');
|
||||
yield new Transformation(new Pattern('/^(japon|escoc|ingl|dinamarqu|fregu|portugu)ês$/i'), '\1eses');
|
||||
yield new Transformation(new Pattern('/m$/i'), 'ns');
|
||||
yield new Transformation(new Pattern('/([^aeou])il$/i'), '\1is');
|
||||
yield new Transformation(new Pattern('/ul$/i'), 'uis');
|
||||
yield new Transformation(new Pattern('/ol$/i'), 'ois');
|
||||
yield new Transformation(new Pattern('/el$/i'), 'eis');
|
||||
yield new Transformation(new Pattern('/al$/i'), 'ais');
|
||||
yield new Transformation(new Pattern('/(z|r)$/i'), '\1es');
|
||||
yield new Transformation(new Pattern('/(s)$/i'), '\1');
|
||||
yield new Transformation(new Pattern('/$/'), 's');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Substitution[]
|
||||
*/
|
||||
public static function getIrregular() : iterable
|
||||
{
|
||||
yield new Substitution(new Word('abdomen'), new Word('abdomens'));
|
||||
yield new Substitution(new Word('alemão'), new Word('alemães'));
|
||||
yield new Substitution(new Word('artesã'), new Word('artesãos'));
|
||||
yield new Substitution(new Word('álcool'), new Word('álcoois'));
|
||||
yield new Substitution(new Word('árvore'), new Word('árvores'));
|
||||
yield new Substitution(new Word('bencão'), new Word('bencãos'));
|
||||
yield new Substitution(new Word('cão'), new Word('cães'));
|
||||
yield new Substitution(new Word('campus'), new Word('campi'));
|
||||
yield new Substitution(new Word('cadáver'), new Word('cadáveres'));
|
||||
yield new Substitution(new Word('capelão'), new Word('capelães'));
|
||||
yield new Substitution(new Word('capitão'), new Word('capitães'));
|
||||
yield new Substitution(new Word('chão'), new Word('chãos'));
|
||||
yield new Substitution(new Word('charlatão'), new Word('charlatães'));
|
||||
yield new Substitution(new Word('cidadão'), new Word('cidadãos'));
|
||||
yield new Substitution(new Word('consul'), new Word('consules'));
|
||||
yield new Substitution(new Word('cristão'), new Word('cristãos'));
|
||||
yield new Substitution(new Word('difícil'), new Word('difíceis'));
|
||||
yield new Substitution(new Word('email'), new Word('emails'));
|
||||
yield new Substitution(new Word('escrivão'), new Word('escrivães'));
|
||||
yield new Substitution(new Word('fóssil'), new Word('fósseis'));
|
||||
yield new Substitution(new Word('gás'), new Word('gases'));
|
||||
yield new Substitution(new Word('germens'), new Word('germen'));
|
||||
yield new Substitution(new Word('grão'), new Word('grãos'));
|
||||
yield new Substitution(new Word('hífen'), new Word('hífens'));
|
||||
yield new Substitution(new Word('irmão'), new Word('irmãos'));
|
||||
yield new Substitution(new Word('liquens'), new Word('liquen'));
|
||||
yield new Substitution(new Word('mal'), new Word('males'));
|
||||
yield new Substitution(new Word('mão'), new Word('mãos'));
|
||||
yield new Substitution(new Word('orfão'), new Word('orfãos'));
|
||||
yield new Substitution(new Word('país'), new Word('países'));
|
||||
yield new Substitution(new Word('pai'), new Word('pais'));
|
||||
yield new Substitution(new Word('pão'), new Word('pães'));
|
||||
yield new Substitution(new Word('projétil'), new Word('projéteis'));
|
||||
yield new Substitution(new Word('réptil'), new Word('répteis'));
|
||||
yield new Substitution(new Word('sacristão'), new Word('sacristães'));
|
||||
yield new Substitution(new Word('sotão'), new Word('sotãos'));
|
||||
yield new Substitution(new Word('tabelião'), new Word('tabeliães'));
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector\Rules\Portuguese;
|
||||
|
||||
use Doctrine\Inflector\GenericLanguageInflectorFactory;
|
||||
use Doctrine\Inflector\Rules\Ruleset;
|
||||
|
||||
final class InflectorFactory extends GenericLanguageInflectorFactory
|
||||
{
|
||||
protected function getSingularRuleset() : Ruleset
|
||||
{
|
||||
return Rules::getSingularRuleset();
|
||||
}
|
||||
|
||||
protected function getPluralRuleset() : Ruleset
|
||||
{
|
||||
return Rules::getPluralRuleset();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector\Rules\Portuguese;
|
||||
|
||||
use Doctrine\Inflector\Rules\Patterns;
|
||||
use Doctrine\Inflector\Rules\Ruleset;
|
||||
use Doctrine\Inflector\Rules\Substitutions;
|
||||
use Doctrine\Inflector\Rules\Transformations;
|
||||
|
||||
final class Rules
|
||||
{
|
||||
public static function getSingularRuleset() : Ruleset
|
||||
{
|
||||
return new Ruleset(
|
||||
new Transformations(...Inflectible::getSingular()),
|
||||
new Patterns(...Uninflected::getSingular()),
|
||||
(new Substitutions(...Inflectible::getIrregular()))->getFlippedSubstitutions()
|
||||
);
|
||||
}
|
||||
|
||||
public static function getPluralRuleset() : Ruleset
|
||||
{
|
||||
return new Ruleset(
|
||||
new Transformations(...Inflectible::getPlural()),
|
||||
new Patterns(...Uninflected::getPlural()),
|
||||
new Substitutions(...Inflectible::getIrregular())
|
||||
);
|
||||
}
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector\Rules\Portuguese;
|
||||
|
||||
use Doctrine\Inflector\Rules\Pattern;
|
||||
|
||||
final class Uninflected
|
||||
{
|
||||
/**
|
||||
* @return Pattern[]
|
||||
*/
|
||||
public static function getSingular() : iterable
|
||||
{
|
||||
yield from self::getDefault();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Pattern[]
|
||||
*/
|
||||
public static function getPlural() : iterable
|
||||
{
|
||||
yield from self::getDefault();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Pattern[]
|
||||
*/
|
||||
private static function getDefault() : iterable
|
||||
{
|
||||
yield new Pattern('tórax');
|
||||
yield new Pattern('tênis');
|
||||
yield new Pattern('ônibus');
|
||||
yield new Pattern('lápis');
|
||||
yield new Pattern('fênix');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector\Rules;
|
||||
|
||||
class Ruleset
|
||||
{
|
||||
/** @var Transformations */
|
||||
private $regular;
|
||||
|
||||
/** @var Patterns */
|
||||
private $uninflected;
|
||||
|
||||
/** @var Substitutions */
|
||||
private $irregular;
|
||||
|
||||
public function __construct(Transformations $regular, Patterns $uninflected, Substitutions $irregular)
|
||||
{
|
||||
$this->regular = $regular;
|
||||
$this->uninflected = $uninflected;
|
||||
$this->irregular = $irregular;
|
||||
}
|
||||
|
||||
public function getRegular() : Transformations
|
||||
{
|
||||
return $this->regular;
|
||||
}
|
||||
|
||||
public function getUninflected() : Patterns
|
||||
{
|
||||
return $this->uninflected;
|
||||
}
|
||||
|
||||
public function getIrregular() : Substitutions
|
||||
{
|
||||
return $this->irregular;
|
||||
}
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector\Rules\Spanish;
|
||||
|
||||
use Doctrine\Inflector\Rules\Pattern;
|
||||
use Doctrine\Inflector\Rules\Substitution;
|
||||
use Doctrine\Inflector\Rules\Transformation;
|
||||
use Doctrine\Inflector\Rules\Word;
|
||||
|
||||
class Inflectible
|
||||
{
|
||||
/**
|
||||
* @return Transformation[]
|
||||
*/
|
||||
public static function getSingular() : iterable
|
||||
{
|
||||
yield new Transformation(new Pattern('/ereses$/'), 'erés');
|
||||
yield new Transformation(new Pattern('/iones$/'), 'ión');
|
||||
yield new Transformation(new Pattern('/ces$/'), 'z');
|
||||
yield new Transformation(new Pattern('/es$/'), '');
|
||||
yield new Transformation(new Pattern('/s$/'), '');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Transformation[]
|
||||
*/
|
||||
public static function getPlural() : iterable
|
||||
{
|
||||
yield new Transformation(new Pattern('/ú([sn])$/i'), 'u\1es');
|
||||
yield new Transformation(new Pattern('/ó([sn])$/i'), 'o\1es');
|
||||
yield new Transformation(new Pattern('/í([sn])$/i'), 'i\1es');
|
||||
yield new Transformation(new Pattern('/é([sn])$/i'), 'e\1es');
|
||||
yield new Transformation(new Pattern('/á([sn])$/i'), 'a\1es');
|
||||
yield new Transformation(new Pattern('/z$/i'), 'ces');
|
||||
yield new Transformation(new Pattern('/([aeiou]s)$/i'), '\1');
|
||||
yield new Transformation(new Pattern('/([^aeéiou])$/i'), '\1es');
|
||||
yield new Transformation(new Pattern('/$/'), 's');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Substitution[]
|
||||
*/
|
||||
public static function getIrregular() : iterable
|
||||
{
|
||||
yield new Substitution(new Word('el'), new Word('los'));
|
||||
yield new Substitution(new Word('papá'), new Word('papás'));
|
||||
yield new Substitution(new Word('mamá'), new Word('mamás'));
|
||||
yield new Substitution(new Word('sofá'), new Word('sofás'));
|
||||
yield new Substitution(new Word('mes'), new Word('meses'));
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector\Rules\Spanish;
|
||||
|
||||
use Doctrine\Inflector\GenericLanguageInflectorFactory;
|
||||
use Doctrine\Inflector\Rules\Ruleset;
|
||||
|
||||
final class InflectorFactory extends GenericLanguageInflectorFactory
|
||||
{
|
||||
protected function getSingularRuleset() : Ruleset
|
||||
{
|
||||
return Rules::getSingularRuleset();
|
||||
}
|
||||
|
||||
protected function getPluralRuleset() : Ruleset
|
||||
{
|
||||
return Rules::getPluralRuleset();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector\Rules\Spanish;
|
||||
|
||||
use Doctrine\Inflector\Rules\Patterns;
|
||||
use Doctrine\Inflector\Rules\Ruleset;
|
||||
use Doctrine\Inflector\Rules\Substitutions;
|
||||
use Doctrine\Inflector\Rules\Transformations;
|
||||
|
||||
final class Rules
|
||||
{
|
||||
public static function getSingularRuleset() : Ruleset
|
||||
{
|
||||
return new Ruleset(
|
||||
new Transformations(...Inflectible::getSingular()),
|
||||
new Patterns(...Uninflected::getSingular()),
|
||||
(new Substitutions(...Inflectible::getIrregular()))->getFlippedSubstitutions()
|
||||
);
|
||||
}
|
||||
|
||||
public static function getPluralRuleset() : Ruleset
|
||||
{
|
||||
return new Ruleset(
|
||||
new Transformations(...Inflectible::getPlural()),
|
||||
new Patterns(...Uninflected::getPlural()),
|
||||
new Substitutions(...Inflectible::getIrregular())
|
||||
);
|
||||
}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector\Rules\Spanish;
|
||||
|
||||
use Doctrine\Inflector\Rules\Pattern;
|
||||
|
||||
final class Uninflected
|
||||
{
|
||||
/**
|
||||
* @return Pattern[]
|
||||
*/
|
||||
public static function getSingular() : iterable
|
||||
{
|
||||
yield from self::getDefault();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Pattern[]
|
||||
*/
|
||||
public static function getPlural() : iterable
|
||||
{
|
||||
yield from self::getDefault();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Pattern[]
|
||||
*/
|
||||
private static function getDefault() : iterable
|
||||
{
|
||||
yield new Pattern('lunes');
|
||||
yield new Pattern('rompecabezas');
|
||||
yield new Pattern('crisis');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector\Rules;
|
||||
|
||||
final class Substitution
|
||||
{
|
||||
/** @var Word */
|
||||
private $from;
|
||||
|
||||
/** @var Word */
|
||||
private $to;
|
||||
|
||||
public function __construct(Word $from, Word $to)
|
||||
{
|
||||
$this->from = $from;
|
||||
$this->to = $to;
|
||||
}
|
||||
|
||||
public function getFrom() : Word
|
||||
{
|
||||
return $this->from;
|
||||
}
|
||||
|
||||
public function getTo() : Word
|
||||
{
|
||||
return $this->to;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector\Rules;
|
||||
|
||||
use Doctrine\Inflector\WordInflector;
|
||||
use function strtolower;
|
||||
use function strtoupper;
|
||||
use function substr;
|
||||
|
||||
class Substitutions implements WordInflector
|
||||
{
|
||||
/** @var Substitution[] */
|
||||
private $substitutions;
|
||||
|
||||
public function __construct(Substitution ...$substitutions)
|
||||
{
|
||||
foreach ($substitutions as $substitution) {
|
||||
$this->substitutions[$substitution->getFrom()->getWord()] = $substitution;
|
||||
}
|
||||
}
|
||||
|
||||
public function getFlippedSubstitutions() : Substitutions
|
||||
{
|
||||
$substitutions = [];
|
||||
|
||||
foreach ($this->substitutions as $substitution) {
|
||||
$substitutions[] = new Substitution(
|
||||
$substitution->getTo(),
|
||||
$substitution->getFrom()
|
||||
);
|
||||
}
|
||||
|
||||
return new Substitutions(...$substitutions);
|
||||
}
|
||||
|
||||
public function inflect(string $word) : string
|
||||
{
|
||||
$lowerWord = strtolower($word);
|
||||
|
||||
if (isset($this->substitutions[$lowerWord])) {
|
||||
$firstLetterUppercase = $lowerWord[0] !== $word[0];
|
||||
|
||||
$toWord = $this->substitutions[$lowerWord]->getTo()->getWord();
|
||||
|
||||
if ($firstLetterUppercase) {
|
||||
return strtoupper($toWord[0]) . substr($toWord, 1);
|
||||
}
|
||||
|
||||
return $toWord;
|
||||
}
|
||||
|
||||
return $word;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector\Rules;
|
||||
|
||||
use Doctrine\Inflector\WordInflector;
|
||||
use function preg_replace;
|
||||
|
||||
final class Transformation implements WordInflector
|
||||
{
|
||||
/** @var Pattern */
|
||||
private $pattern;
|
||||
|
||||
/** @var string */
|
||||
private $replacement;
|
||||
|
||||
public function __construct(Pattern $pattern, string $replacement)
|
||||
{
|
||||
$this->pattern = $pattern;
|
||||
$this->replacement = $replacement;
|
||||
}
|
||||
|
||||
public function getPattern() : Pattern
|
||||
{
|
||||
return $this->pattern;
|
||||
}
|
||||
|
||||
public function getReplacement() : string
|
||||
{
|
||||
return $this->replacement;
|
||||
}
|
||||
|
||||
public function inflect(string $word) : string
|
||||
{
|
||||
return (string) preg_replace($this->pattern->getRegex(), $this->replacement, $word);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector\Rules;
|
||||
|
||||
use Doctrine\Inflector\WordInflector;
|
||||
|
||||
class Transformations implements WordInflector
|
||||
{
|
||||
/** @var Transformation[] */
|
||||
private $transformations;
|
||||
|
||||
public function __construct(Transformation ...$transformations)
|
||||
{
|
||||
$this->transformations = $transformations;
|
||||
}
|
||||
|
||||
public function inflect(string $word) : string
|
||||
{
|
||||
foreach ($this->transformations as $transformation) {
|
||||
if ($transformation->getPattern()->matches($word)) {
|
||||
return $transformation->inflect($word);
|
||||
}
|
||||
}
|
||||
|
||||
return $word;
|
||||
}
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector\Rules\Turkish;
|
||||
|
||||
use Doctrine\Inflector\Rules\Pattern;
|
||||
use Doctrine\Inflector\Rules\Substitution;
|
||||
use Doctrine\Inflector\Rules\Transformation;
|
||||
use Doctrine\Inflector\Rules\Word;
|
||||
|
||||
class Inflectible
|
||||
{
|
||||
/**
|
||||
* @return Transformation[]
|
||||
*/
|
||||
public static function getSingular() : iterable
|
||||
{
|
||||
yield new Transformation(new Pattern('/l[ae]r$/i'), '');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Transformation[]
|
||||
*/
|
||||
public static function getPlural() : iterable
|
||||
{
|
||||
yield new Transformation(new Pattern('/([eöiü][^aoıueöiü]{0,6})$/u'), '\1ler');
|
||||
yield new Transformation(new Pattern('/([aoıu][^aoıueöiü]{0,6})$/u'), '\1lar');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Substitution[]
|
||||
*/
|
||||
public static function getIrregular() : iterable
|
||||
{
|
||||
yield new Substitution(new Word('ben'), new Word('biz'));
|
||||
yield new Substitution(new Word('sen'), new Word('siz'));
|
||||
yield new Substitution(new Word('o'), new Word('onlar'));
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector\Rules\Turkish;
|
||||
|
||||
use Doctrine\Inflector\GenericLanguageInflectorFactory;
|
||||
use Doctrine\Inflector\Rules\Ruleset;
|
||||
|
||||
final class InflectorFactory extends GenericLanguageInflectorFactory
|
||||
{
|
||||
protected function getSingularRuleset() : Ruleset
|
||||
{
|
||||
return Rules::getSingularRuleset();
|
||||
}
|
||||
|
||||
protected function getPluralRuleset() : Ruleset
|
||||
{
|
||||
return Rules::getPluralRuleset();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector\Rules\Turkish;
|
||||
|
||||
use Doctrine\Inflector\Rules\Patterns;
|
||||
use Doctrine\Inflector\Rules\Ruleset;
|
||||
use Doctrine\Inflector\Rules\Substitutions;
|
||||
use Doctrine\Inflector\Rules\Transformations;
|
||||
|
||||
final class Rules
|
||||
{
|
||||
public static function getSingularRuleset() : Ruleset
|
||||
{
|
||||
return new Ruleset(
|
||||
new Transformations(...Inflectible::getSingular()),
|
||||
new Patterns(...Uninflected::getSingular()),
|
||||
(new Substitutions(...Inflectible::getIrregular()))->getFlippedSubstitutions()
|
||||
);
|
||||
}
|
||||
|
||||
public static function getPluralRuleset() : Ruleset
|
||||
{
|
||||
return new Ruleset(
|
||||
new Transformations(...Inflectible::getPlural()),
|
||||
new Patterns(...Uninflected::getPlural()),
|
||||
new Substitutions(...Inflectible::getIrregular())
|
||||
);
|
||||
}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector\Rules\Turkish;
|
||||
|
||||
use Doctrine\Inflector\Rules\Pattern;
|
||||
|
||||
final class Uninflected
|
||||
{
|
||||
/**
|
||||
* @return Pattern[]
|
||||
*/
|
||||
public static function getSingular() : iterable
|
||||
{
|
||||
yield from self::getDefault();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Pattern[]
|
||||
*/
|
||||
public static function getPlural() : iterable
|
||||
{
|
||||
yield from self::getDefault();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Pattern[]
|
||||
*/
|
||||
private static function getDefault() : iterable
|
||||
{
|
||||
yield new Pattern('lunes');
|
||||
yield new Pattern('rompecabezas');
|
||||
yield new Pattern('crisis');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector\Rules;
|
||||
|
||||
class Word
|
||||
{
|
||||
/** @var string */
|
||||
private $word;
|
||||
|
||||
public function __construct(string $word)
|
||||
{
|
||||
$this->word = $word;
|
||||
}
|
||||
|
||||
public function getWord() : string
|
||||
{
|
||||
return $this->word;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector;
|
||||
|
||||
use Doctrine\Inflector\Rules\Ruleset;
|
||||
use function array_merge;
|
||||
|
||||
/**
|
||||
* Inflects based on multiple rulesets.
|
||||
*
|
||||
* Rules:
|
||||
* - If the word matches any uninflected word pattern, it is not inflected
|
||||
* - The first ruleset that returns a different value for an irregular word wins
|
||||
* - The first ruleset that returns a different value for a regular word wins
|
||||
* - If none of the above match, the word is left as-is
|
||||
*/
|
||||
class RulesetInflector implements WordInflector
|
||||
{
|
||||
/** @var Ruleset[] */
|
||||
private $rulesets;
|
||||
|
||||
public function __construct(Ruleset $ruleset, Ruleset ...$rulesets)
|
||||
{
|
||||
$this->rulesets = array_merge([$ruleset], $rulesets);
|
||||
}
|
||||
|
||||
public function inflect(string $word) : string
|
||||
{
|
||||
if ($word === '') {
|
||||
return '';
|
||||
}
|
||||
|
||||
foreach ($this->rulesets as $ruleset) {
|
||||
if ($ruleset->getUninflected()->matches($word)) {
|
||||
return $word;
|
||||
}
|
||||
|
||||
$inflected = $ruleset->getIrregular()->inflect($word);
|
||||
|
||||
if ($inflected !== $word) {
|
||||
return $inflected;
|
||||
}
|
||||
|
||||
$inflected = $ruleset->getRegular()->inflect($word);
|
||||
|
||||
if ($inflected !== $word) {
|
||||
return $inflected;
|
||||
}
|
||||
}
|
||||
|
||||
return $word;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Inflector;
|
||||
|
||||
interface WordInflector
|
||||
{
|
||||
public function inflect(string $word) : string;
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
includes:
|
||||
- vendor/phpstan/phpstan-phpunit/extension.neon
|
||||
- vendor/phpstan/phpstan-phpunit/rules.neon
|
||||
- vendor/phpstan/phpstan-strict-rules/rules.neon
|
||||
|
||||
parameters:
|
||||
level: 7
|
||||
paths:
|
||||
- lib
|
||||
- tests
|
||||
|
||||
excludes_analyse:
|
||||
- %rootDir%/../../../tests/Doctrine/Tests/Common/*
|
||||
Vendored
+473
@@ -0,0 +1,473 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Bus;
|
||||
|
||||
use Carbon\CarbonImmutable;
|
||||
use Closure;
|
||||
use Illuminate\Contracts\Queue\Factory as QueueFactory;
|
||||
use Illuminate\Contracts\Support\Arrayable;
|
||||
use Illuminate\Queue\CallQueuedClosure;
|
||||
use Illuminate\Queue\SerializableClosure;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Collection;
|
||||
use JsonSerializable;
|
||||
use Throwable;
|
||||
|
||||
class Batch implements Arrayable, JsonSerializable
|
||||
{
|
||||
/**
|
||||
* The queue factory implementation.
|
||||
*
|
||||
* @var \Illuminate\Contracts\Queue\Factory
|
||||
*/
|
||||
protected $queue;
|
||||
|
||||
/**
|
||||
* The repository implementation.
|
||||
*
|
||||
* @var \Illuminate\Bus\BatchRepository
|
||||
*/
|
||||
protected $repository;
|
||||
|
||||
/**
|
||||
* The batch ID.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $id;
|
||||
|
||||
/**
|
||||
* The batch name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $name;
|
||||
|
||||
/**
|
||||
* The total number of jobs that belong to the batch.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $totalJobs;
|
||||
|
||||
/**
|
||||
* The total number of jobs that are still pending.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $pendingJobs;
|
||||
|
||||
/**
|
||||
* The total number of jobs that have failed.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $failedJobs;
|
||||
|
||||
/**
|
||||
* The IDs of the jobs that have failed.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $failedJobIds;
|
||||
|
||||
/**
|
||||
* The batch options.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $options;
|
||||
|
||||
/**
|
||||
* The date indicating when the batch was created.
|
||||
*
|
||||
* @var \Carbon\CarbonImmutable
|
||||
*/
|
||||
public $createdAt;
|
||||
|
||||
/**
|
||||
* The date indicating when the batch was cancelled.
|
||||
*
|
||||
* @var \Carbon\CarbonImmutable|null
|
||||
*/
|
||||
public $cancelledAt;
|
||||
|
||||
/**
|
||||
* The date indicating when the batch was finished.
|
||||
*
|
||||
* @var \Carbon\CarbonImmutable|null
|
||||
*/
|
||||
public $finishedAt;
|
||||
|
||||
/**
|
||||
* Create a new batch instance.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Queue\Factory $queue
|
||||
* @param \Illuminate\Bus\BatchRepository $repository
|
||||
* @param string $id
|
||||
* @param string $name
|
||||
* @param int $totalJobs
|
||||
* @param int $pendingJobs
|
||||
* @param int $failedJobs
|
||||
* @param array $failedJobIds
|
||||
* @param array $options
|
||||
* @param \Carbon\CarbonImmutable $createdAt
|
||||
* @param \Carbon\CarbonImmutable|null $cancelledAt
|
||||
* @param \Carbon\CarbonImmutable|null $finishedAt
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(QueueFactory $queue,
|
||||
BatchRepository $repository,
|
||||
string $id,
|
||||
string $name,
|
||||
int $totalJobs,
|
||||
int $pendingJobs,
|
||||
int $failedJobs,
|
||||
array $failedJobIds,
|
||||
array $options,
|
||||
CarbonImmutable $createdAt,
|
||||
?CarbonImmutable $cancelledAt = null,
|
||||
?CarbonImmutable $finishedAt = null)
|
||||
{
|
||||
$this->queue = $queue;
|
||||
$this->repository = $repository;
|
||||
$this->id = $id;
|
||||
$this->name = $name;
|
||||
$this->totalJobs = $totalJobs;
|
||||
$this->pendingJobs = $pendingJobs;
|
||||
$this->failedJobs = $failedJobs;
|
||||
$this->failedJobIds = $failedJobIds;
|
||||
$this->options = $options;
|
||||
$this->createdAt = $createdAt;
|
||||
$this->cancelledAt = $cancelledAt;
|
||||
$this->finishedAt = $finishedAt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a fresh instance of the batch represented by this ID.
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function fresh()
|
||||
{
|
||||
return $this->repository->find($this->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add additional jobs to the batch.
|
||||
*
|
||||
* @param \Illuminate\Support\Enumerable|array $jobs
|
||||
* @return self
|
||||
*/
|
||||
public function add($jobs)
|
||||
{
|
||||
$count = 0;
|
||||
|
||||
$jobs = Collection::wrap($jobs)->map(function ($job) use (&$count) {
|
||||
$job = $job instanceof Closure ? CallQueuedClosure::create($job) : $job;
|
||||
|
||||
if (is_array($job)) {
|
||||
$count += count($job);
|
||||
|
||||
return with($this->prepareBatchedChain($job), function ($chain) {
|
||||
return $chain->first()
|
||||
->allOnQueue($this->options['queue'] ?? null)
|
||||
->allOnConnection($this->options['connection'] ?? null)
|
||||
->chain($chain->slice(1)->values()->all());
|
||||
});
|
||||
} else {
|
||||
$job->withBatchId($this->id);
|
||||
|
||||
$count++;
|
||||
}
|
||||
|
||||
return $job;
|
||||
});
|
||||
|
||||
$this->repository->transaction(function () use ($jobs, $count) {
|
||||
$this->repository->incrementTotalJobs($this->id, $count);
|
||||
|
||||
$this->queue->connection($this->options['connection'] ?? null)->bulk(
|
||||
$jobs->all(),
|
||||
$data = '',
|
||||
$this->options['queue'] ?? null
|
||||
);
|
||||
});
|
||||
|
||||
return $this->fresh();
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare a chain that exists within the jobs being added.
|
||||
*
|
||||
* @param array $chain
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
protected function prepareBatchedChain(array $chain)
|
||||
{
|
||||
return collect($chain)->map(function ($job) {
|
||||
$job = $job instanceof Closure ? CallQueuedClosure::create($job) : $job;
|
||||
|
||||
return $job->withBatchId($this->id);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the total number of jobs that have been processed by the batch thus far.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function processedJobs()
|
||||
{
|
||||
return $this->totalJobs - $this->pendingJobs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the percentage of jobs that have been processed (between 0-100).
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function progress()
|
||||
{
|
||||
return $this->totalJobs > 0 ? round(($this->processedJobs() / $this->totalJobs) * 100) : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Record that a job within the batch finished successfully, executing any callbacks if necessary.
|
||||
*
|
||||
* @param string $jobId
|
||||
* @return void
|
||||
*/
|
||||
public function recordSuccessfulJob(string $jobId)
|
||||
{
|
||||
$counts = $this->decrementPendingJobs($jobId);
|
||||
|
||||
if ($counts->pendingJobs === 0) {
|
||||
$this->repository->markAsFinished($this->id);
|
||||
}
|
||||
|
||||
if ($counts->pendingJobs === 0 && $this->hasThenCallbacks()) {
|
||||
$batch = $this->fresh();
|
||||
|
||||
collect($this->options['then'])->each(function ($handler) use ($batch) {
|
||||
$this->invokeHandlerCallback($handler, $batch);
|
||||
});
|
||||
}
|
||||
|
||||
if ($counts->allJobsHaveRanExactlyOnce() && $this->hasFinallyCallbacks()) {
|
||||
$batch = $this->fresh();
|
||||
|
||||
collect($this->options['finally'])->each(function ($handler) use ($batch) {
|
||||
$this->invokeHandlerCallback($handler, $batch);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrement the pending jobs for the batch.
|
||||
*
|
||||
* @param string $jobId
|
||||
* @return \Illuminate\Bus\UpdatedBatchJobCounts
|
||||
*/
|
||||
public function decrementPendingJobs(string $jobId)
|
||||
{
|
||||
return $this->repository->decrementPendingJobs($this->id, $jobId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the batch has finished executing.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function finished()
|
||||
{
|
||||
return ! is_null($this->finishedAt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the batch has "success" callbacks.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasThenCallbacks()
|
||||
{
|
||||
return isset($this->options['then']) && ! empty($this->options['then']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the batch allows jobs to fail without cancelling the batch.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function allowsFailures()
|
||||
{
|
||||
return Arr::get($this->options, 'allowFailures', false) === true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the batch has job failures.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasFailures()
|
||||
{
|
||||
return $this->failedJobs > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Record that a job within the batch failed to finish successfully, executing any callbacks if necessary.
|
||||
*
|
||||
* @param string $jobId
|
||||
* @param \Throwable $e
|
||||
* @return void
|
||||
*/
|
||||
public function recordFailedJob(string $jobId, $e)
|
||||
{
|
||||
$counts = $this->incrementFailedJobs($jobId);
|
||||
|
||||
if ($counts->failedJobs === 1 && ! $this->allowsFailures()) {
|
||||
$this->cancel();
|
||||
}
|
||||
|
||||
if ($counts->failedJobs === 1 && $this->hasCatchCallbacks()) {
|
||||
$batch = $this->fresh();
|
||||
|
||||
collect($this->options['catch'])->each(function ($handler) use ($batch, $e) {
|
||||
$this->invokeHandlerCallback($handler, $batch, $e);
|
||||
});
|
||||
}
|
||||
|
||||
if ($counts->allJobsHaveRanExactlyOnce() && $this->hasFinallyCallbacks()) {
|
||||
$batch = $this->fresh();
|
||||
|
||||
collect($this->options['finally'])->each(function ($handler) use ($batch, $e) {
|
||||
$this->invokeHandlerCallback($handler, $batch, $e);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Increment the failed jobs for the batch.
|
||||
*
|
||||
* @param string $jobId
|
||||
* @return \Illuminate\Bus\UpdatedBatchJobCounts
|
||||
*/
|
||||
public function incrementFailedJobs(string $jobId)
|
||||
{
|
||||
return $this->repository->incrementFailedJobs($this->id, $jobId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the batch has "catch" callbacks.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasCatchCallbacks()
|
||||
{
|
||||
return isset($this->options['catch']) && ! empty($this->options['catch']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the batch has "finally" callbacks.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasFinallyCallbacks()
|
||||
{
|
||||
return isset($this->options['finally']) && ! empty($this->options['finally']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel the batch.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function cancel()
|
||||
{
|
||||
$this->repository->cancel($this->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the batch has been cancelled.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function canceled()
|
||||
{
|
||||
return $this->cancelled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the batch has been cancelled.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function cancelled()
|
||||
{
|
||||
return ! is_null($this->cancelledAt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the batch from storage.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function delete()
|
||||
{
|
||||
$this->repository->delete($this->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke a batch callback handler.
|
||||
*
|
||||
* @param \Illuminate\Queue\SerializableClosure|callable $handler
|
||||
* @param \Illuminate\Bus\Batch $batch
|
||||
* @param \Throwable|null $e
|
||||
* @return void
|
||||
*/
|
||||
protected function invokeHandlerCallback($handler, Batch $batch, Throwable $e = null)
|
||||
{
|
||||
try {
|
||||
return $handler instanceof SerializableClosure
|
||||
? $handler->__invoke($batch, $e)
|
||||
: call_user_func($handler, $batch, $e);
|
||||
} catch (Throwable $e) {
|
||||
if (function_exists('report')) {
|
||||
report($e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the batch to an array.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function toArray()
|
||||
{
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'name' => $this->name,
|
||||
'totalJobs' => $this->totalJobs,
|
||||
'pendingJobs' => $this->pendingJobs,
|
||||
'processedJobs' => $this->processedJobs(),
|
||||
'progress' => $this->progress(),
|
||||
'failedJobs' => $this->failedJobs,
|
||||
'options' => $this->options,
|
||||
'createdAt' => $this->createdAt,
|
||||
'cancelledAt' => $this->cancelledAt,
|
||||
'finishedAt' => $this->finishedAt,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the JSON serializable representation of the object.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function jsonSerialize()
|
||||
{
|
||||
return $this->toArray();
|
||||
}
|
||||
}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Bus;
|
||||
|
||||
use Carbon\CarbonImmutable;
|
||||
use Illuminate\Contracts\Queue\Factory as QueueFactory;
|
||||
|
||||
class BatchFactory
|
||||
{
|
||||
/**
|
||||
* The queue factory implementation.
|
||||
*
|
||||
* @var \Illuminate\Contracts\Queue\Factory
|
||||
*/
|
||||
protected $queue;
|
||||
|
||||
/**
|
||||
* Create a new batch factory instance.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Queue\Factory $queue
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(QueueFactory $queue)
|
||||
{
|
||||
$this->queue = $queue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new batch instance.
|
||||
*
|
||||
* @param \Illuminate\Bus\BatchRepository $repository
|
||||
* @param string $id
|
||||
* @param string $name
|
||||
* @param int $totalJobs
|
||||
* @param int $pendingJobs
|
||||
* @param int $failedJobs
|
||||
* @param array $failedJobIds
|
||||
* @param array $options
|
||||
* @param \Carbon\CarbonImmutable $createdAt
|
||||
* @param \Carbon\CarbonImmutable|null $cancelledAt
|
||||
* @param \Carbon\CarbonImmutable|null $finishedAt
|
||||
* @return \Illuminate\Bus\Batch
|
||||
*/
|
||||
public function make(BatchRepository $repository,
|
||||
string $id,
|
||||
string $name,
|
||||
int $totalJobs,
|
||||
int $pendingJobs,
|
||||
int $failedJobs,
|
||||
array $failedJobIds,
|
||||
array $options,
|
||||
CarbonImmutable $createdAt,
|
||||
?CarbonImmutable $cancelledAt,
|
||||
?CarbonImmutable $finishedAt)
|
||||
{
|
||||
return new Batch($this->queue, $repository, $id, $name, $totalJobs, $pendingJobs, $failedJobs, $failedJobIds, $options, $createdAt, $cancelledAt, $finishedAt);
|
||||
}
|
||||
}
|
||||
+92
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Bus;
|
||||
|
||||
use Closure;
|
||||
|
||||
interface BatchRepository
|
||||
{
|
||||
/**
|
||||
* Retrieve a list of batches.
|
||||
*
|
||||
* @param int $limit
|
||||
* @param mixed $before
|
||||
* @return \Illuminate\Bus\Batch[]
|
||||
*/
|
||||
public function get($limit, $before);
|
||||
|
||||
/**
|
||||
* Retrieve information about an existing batch.
|
||||
*
|
||||
* @param string $batchId
|
||||
* @return \Illuminate\Bus\Batch|null
|
||||
*/
|
||||
public function find(string $batchId);
|
||||
|
||||
/**
|
||||
* Store a new pending batch.
|
||||
*
|
||||
* @param \Illuminate\Bus\PendingBatch $batch
|
||||
* @return \Illuminate\Bus\Batch
|
||||
*/
|
||||
public function store(PendingBatch $batch);
|
||||
|
||||
/**
|
||||
* Increment the total number of jobs within the batch.
|
||||
*
|
||||
* @param string $batchId
|
||||
* @param int $amount
|
||||
* @return void
|
||||
*/
|
||||
public function incrementTotalJobs(string $batchId, int $amount);
|
||||
|
||||
/**
|
||||
* Decrement the total number of pending jobs for the batch.
|
||||
*
|
||||
* @param string $batchId
|
||||
* @param string $jobId
|
||||
* @return \Illuminate\Bus\UpdatedBatchJobCounts
|
||||
*/
|
||||
public function decrementPendingJobs(string $batchId, string $jobId);
|
||||
|
||||
/**
|
||||
* Increment the total number of failed jobs for the batch.
|
||||
*
|
||||
* @param string $batchId
|
||||
* @param string $jobId
|
||||
* @return \Illuminate\Bus\UpdatedBatchJobCounts
|
||||
*/
|
||||
public function incrementFailedJobs(string $batchId, string $jobId);
|
||||
|
||||
/**
|
||||
* Mark the batch that has the given ID as finished.
|
||||
*
|
||||
* @param string $batchId
|
||||
* @return void
|
||||
*/
|
||||
public function markAsFinished(string $batchId);
|
||||
|
||||
/**
|
||||
* Cancel the batch that has the given ID.
|
||||
*
|
||||
* @param string $batchId
|
||||
* @return void
|
||||
*/
|
||||
public function cancel(string $batchId);
|
||||
|
||||
/**
|
||||
* Delete the batch that has the given ID.
|
||||
*
|
||||
* @param string $batchId
|
||||
* @return void
|
||||
*/
|
||||
public function delete(string $batchId);
|
||||
|
||||
/**
|
||||
* Execute the given Closure within a storage specific transaction.
|
||||
*
|
||||
* @param \Closure $callback
|
||||
* @return mixed
|
||||
*/
|
||||
public function transaction(Closure $callback);
|
||||
}
|
||||
Vendored
+52
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Bus;
|
||||
|
||||
use Illuminate\Container\Container;
|
||||
|
||||
trait Batchable
|
||||
{
|
||||
/**
|
||||
* The batch ID (if applicable).
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $batchId;
|
||||
|
||||
/**
|
||||
* Get the batch instance for the job, if applicable.
|
||||
*
|
||||
* @return \Illuminate\Bus\Batch|null
|
||||
*/
|
||||
public function batch()
|
||||
{
|
||||
if ($this->batchId) {
|
||||
return Container::getInstance()->make(BatchRepository::class)->find($this->batchId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the batch is still active and processing.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function batching()
|
||||
{
|
||||
$batch = $this->batch();
|
||||
|
||||
return $batch && ! $batch->cancelled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the batch ID on the job.
|
||||
*
|
||||
* @param string $batchId
|
||||
* @return $this
|
||||
*/
|
||||
public function withBatchId(string $batchId)
|
||||
{
|
||||
$this->batchId = $batchId;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Bus;
|
||||
|
||||
use Illuminate\Contracts\Bus\Dispatcher as DispatcherContract;
|
||||
use Illuminate\Contracts\Bus\QueueingDispatcher as QueueingDispatcherContract;
|
||||
use Illuminate\Contracts\Queue\Factory as QueueFactoryContract;
|
||||
use Illuminate\Contracts\Support\DeferrableProvider;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
||||
class BusServiceProvider extends ServiceProvider implements DeferrableProvider
|
||||
{
|
||||
/**
|
||||
* Register the service provider.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
$this->app->singleton(Dispatcher::class, function ($app) {
|
||||
return new Dispatcher($app, function ($connection = null) use ($app) {
|
||||
return $app[QueueFactoryContract::class]->connection($connection);
|
||||
});
|
||||
});
|
||||
|
||||
$this->registerBatchServices();
|
||||
|
||||
$this->app->alias(
|
||||
Dispatcher::class, DispatcherContract::class
|
||||
);
|
||||
|
||||
$this->app->alias(
|
||||
Dispatcher::class, QueueingDispatcherContract::class
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the batch handling services.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function registerBatchServices()
|
||||
{
|
||||
$this->app->singleton(BatchRepository::class, DatabaseBatchRepository::class);
|
||||
|
||||
$this->app->singleton(DatabaseBatchRepository::class, function ($app) {
|
||||
return new DatabaseBatchRepository(
|
||||
$app->make(BatchFactory::class),
|
||||
$app->make('db')->connection(config('queue.batching.database')),
|
||||
config('queue.batching.table', 'job_batches')
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the services provided by the provider.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function provides()
|
||||
{
|
||||
return [
|
||||
Dispatcher::class,
|
||||
DispatcherContract::class,
|
||||
QueueingDispatcherContract::class,
|
||||
BatchRepository::class,
|
||||
];
|
||||
}
|
||||
}
|
||||
+347
@@ -0,0 +1,347 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Bus;
|
||||
|
||||
use Carbon\CarbonImmutable;
|
||||
use Closure;
|
||||
use DateTimeInterface;
|
||||
use Illuminate\Database\Connection;
|
||||
use Illuminate\Database\PostgresConnection;
|
||||
use Illuminate\Database\Query\Expression;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class DatabaseBatchRepository implements PrunableBatchRepository
|
||||
{
|
||||
/**
|
||||
* The batch factory instance.
|
||||
*
|
||||
* @var \Illuminate\Bus\BatchFactory
|
||||
*/
|
||||
protected $factory;
|
||||
|
||||
/**
|
||||
* The database connection instance.
|
||||
*
|
||||
* @var \Illuminate\Database\Connection
|
||||
*/
|
||||
protected $connection;
|
||||
|
||||
/**
|
||||
* The database table to use to store batch information.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $table;
|
||||
|
||||
/**
|
||||
* Create a new batch repository instance.
|
||||
*
|
||||
* @param \Illuminate\Bus\BatchFactory $factory
|
||||
* @param \Illuminate\Database\Connection $connection
|
||||
* @param string $table
|
||||
*/
|
||||
public function __construct(BatchFactory $factory, Connection $connection, string $table)
|
||||
{
|
||||
$this->factory = $factory;
|
||||
$this->connection = $connection;
|
||||
$this->table = $table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a list of batches.
|
||||
*
|
||||
* @param int $limit
|
||||
* @param mixed $before
|
||||
* @return \Illuminate\Bus\Batch[]
|
||||
*/
|
||||
public function get($limit = 50, $before = null)
|
||||
{
|
||||
return $this->connection->table($this->table)
|
||||
->orderByDesc('id')
|
||||
->take($limit)
|
||||
->when($before, function ($q) use ($before) {
|
||||
return $q->where('id', '<', $before);
|
||||
})
|
||||
->get()
|
||||
->map(function ($batch) {
|
||||
return $this->toBatch($batch);
|
||||
})
|
||||
->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve information about an existing batch.
|
||||
*
|
||||
* @param string $batchId
|
||||
* @return \Illuminate\Bus\Batch|null
|
||||
*/
|
||||
public function find(string $batchId)
|
||||
{
|
||||
$batch = $this->connection->table($this->table)
|
||||
->where('id', $batchId)
|
||||
->first();
|
||||
|
||||
if ($batch) {
|
||||
return $this->toBatch($batch);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a new pending batch.
|
||||
*
|
||||
* @param \Illuminate\Bus\PendingBatch $batch
|
||||
* @return \Illuminate\Bus\Batch
|
||||
*/
|
||||
public function store(PendingBatch $batch)
|
||||
{
|
||||
$id = (string) Str::orderedUuid();
|
||||
|
||||
$this->connection->table($this->table)->insert([
|
||||
'id' => $id,
|
||||
'name' => $batch->name,
|
||||
'total_jobs' => 0,
|
||||
'pending_jobs' => 0,
|
||||
'failed_jobs' => 0,
|
||||
'failed_job_ids' => '[]',
|
||||
'options' => $this->serialize($batch->options),
|
||||
'created_at' => time(),
|
||||
'cancelled_at' => null,
|
||||
'finished_at' => null,
|
||||
]);
|
||||
|
||||
return $this->find($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Increment the total number of jobs within the batch.
|
||||
*
|
||||
* @param string $batchId
|
||||
* @param int $amount
|
||||
* @return void
|
||||
*/
|
||||
public function incrementTotalJobs(string $batchId, int $amount)
|
||||
{
|
||||
$this->connection->table($this->table)->where('id', $batchId)->update([
|
||||
'total_jobs' => new Expression('total_jobs + '.$amount),
|
||||
'pending_jobs' => new Expression('pending_jobs + '.$amount),
|
||||
'finished_at' => null,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrement the total number of pending jobs for the batch.
|
||||
*
|
||||
* @param string $batchId
|
||||
* @param string $jobId
|
||||
* @return \Illuminate\Bus\UpdatedBatchJobCounts
|
||||
*/
|
||||
public function decrementPendingJobs(string $batchId, string $jobId)
|
||||
{
|
||||
$values = $this->updateAtomicValues($batchId, function ($batch) use ($jobId) {
|
||||
return [
|
||||
'pending_jobs' => $batch->pending_jobs - 1,
|
||||
'failed_jobs' => $batch->failed_jobs,
|
||||
'failed_job_ids' => json_encode(array_values(array_diff(json_decode($batch->failed_job_ids, true), [$jobId]))),
|
||||
];
|
||||
});
|
||||
|
||||
return new UpdatedBatchJobCounts(
|
||||
$values['pending_jobs'],
|
||||
$values['failed_jobs']
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Increment the total number of failed jobs for the batch.
|
||||
*
|
||||
* @param string $batchId
|
||||
* @param string $jobId
|
||||
* @return \Illuminate\Bus\UpdatedBatchJobCounts
|
||||
*/
|
||||
public function incrementFailedJobs(string $batchId, string $jobId)
|
||||
{
|
||||
$values = $this->updateAtomicValues($batchId, function ($batch) use ($jobId) {
|
||||
return [
|
||||
'pending_jobs' => $batch->pending_jobs,
|
||||
'failed_jobs' => $batch->failed_jobs + 1,
|
||||
'failed_job_ids' => json_encode(array_values(array_unique(array_merge(json_decode($batch->failed_job_ids, true), [$jobId])))),
|
||||
];
|
||||
});
|
||||
|
||||
return new UpdatedBatchJobCounts(
|
||||
$values['pending_jobs'],
|
||||
$values['failed_jobs']
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update an atomic value within the batch.
|
||||
*
|
||||
* @param string $batchId
|
||||
* @param \Closure $callback
|
||||
* @return int|null
|
||||
*/
|
||||
protected function updateAtomicValues(string $batchId, Closure $callback)
|
||||
{
|
||||
return $this->connection->transaction(function () use ($batchId, $callback) {
|
||||
$batch = $this->connection->table($this->table)->where('id', $batchId)
|
||||
->lockForUpdate()
|
||||
->first();
|
||||
|
||||
return is_null($batch) ? [] : tap($callback($batch), function ($values) use ($batchId) {
|
||||
$this->connection->table($this->table)->where('id', $batchId)->update($values);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark the batch that has the given ID as finished.
|
||||
*
|
||||
* @param string $batchId
|
||||
* @return void
|
||||
*/
|
||||
public function markAsFinished(string $batchId)
|
||||
{
|
||||
$this->connection->table($this->table)->where('id', $batchId)->update([
|
||||
'finished_at' => time(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel the batch that has the given ID.
|
||||
*
|
||||
* @param string $batchId
|
||||
* @return void
|
||||
*/
|
||||
public function cancel(string $batchId)
|
||||
{
|
||||
$this->connection->table($this->table)->where('id', $batchId)->update([
|
||||
'cancelled_at' => time(),
|
||||
'finished_at' => time(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the batch that has the given ID.
|
||||
*
|
||||
* @param string $batchId
|
||||
* @return void
|
||||
*/
|
||||
public function delete(string $batchId)
|
||||
{
|
||||
$this->connection->table($this->table)->where('id', $batchId)->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Prune all of the entries older than the given date.
|
||||
*
|
||||
* @param \DateTimeInterface $before
|
||||
* @return int
|
||||
*/
|
||||
public function prune(DateTimeInterface $before)
|
||||
{
|
||||
$query = $this->connection->table($this->table)
|
||||
->whereNotNull('finished_at')
|
||||
->where('finished_at', '<', $before->getTimestamp());
|
||||
|
||||
$totalDeleted = 0;
|
||||
|
||||
do {
|
||||
$deleted = $query->take(1000)->delete();
|
||||
|
||||
$totalDeleted += $deleted;
|
||||
} while ($deleted !== 0);
|
||||
|
||||
return $totalDeleted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prune all of the unfinished entries older than the given date.
|
||||
*
|
||||
* @param \DateTimeInterface $before
|
||||
* @return int
|
||||
*/
|
||||
public function pruneUnfinished(DateTimeInterface $before)
|
||||
{
|
||||
$query = $this->connection->table($this->table)
|
||||
->whereNull('finished_at')
|
||||
->where('created_at', '<', $before->getTimestamp());
|
||||
|
||||
$totalDeleted = 0;
|
||||
|
||||
do {
|
||||
$deleted = $query->take(1000)->delete();
|
||||
|
||||
$totalDeleted += $deleted;
|
||||
} while ($deleted !== 0);
|
||||
|
||||
return $totalDeleted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the given Closure within a storage specific transaction.
|
||||
*
|
||||
* @param \Closure $callback
|
||||
* @return mixed
|
||||
*/
|
||||
public function transaction(Closure $callback)
|
||||
{
|
||||
return $this->connection->transaction(function () use ($callback) {
|
||||
return $callback();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize the given value.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return string
|
||||
*/
|
||||
protected function serialize($value)
|
||||
{
|
||||
$serialized = serialize($value);
|
||||
|
||||
return $this->connection instanceof PostgresConnection
|
||||
? base64_encode($serialized)
|
||||
: $serialized;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unserialize the given value.
|
||||
*
|
||||
* @param string $serialized
|
||||
* @return mixed
|
||||
*/
|
||||
protected function unserialize($serialized)
|
||||
{
|
||||
if ($this->connection instanceof PostgresConnection &&
|
||||
! Str::contains($serialized, [':', ';'])) {
|
||||
$serialized = base64_decode($serialized);
|
||||
}
|
||||
|
||||
return unserialize($serialized);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the given raw batch to a Batch object.
|
||||
*
|
||||
* @param object $batch
|
||||
* @return \Illuminate\Bus\Batch
|
||||
*/
|
||||
protected function toBatch($batch)
|
||||
{
|
||||
return $this->factory->make(
|
||||
$this,
|
||||
$batch->id,
|
||||
$batch->name,
|
||||
(int) $batch->total_jobs,
|
||||
(int) $batch->pending_jobs,
|
||||
(int) $batch->failed_jobs,
|
||||
json_decode($batch->failed_job_ids, true),
|
||||
$this->unserialize($batch->options),
|
||||
CarbonImmutable::createFromTimestamp($batch->created_at),
|
||||
$batch->cancelled_at ? CarbonImmutable::createFromTimestamp($batch->cancelled_at) : $batch->cancelled_at,
|
||||
$batch->finished_at ? CarbonImmutable::createFromTimestamp($batch->finished_at) : $batch->finished_at
|
||||
);
|
||||
}
|
||||
}
|
||||
Vendored
+295
@@ -0,0 +1,295 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Bus;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Contracts\Bus\QueueingDispatcher;
|
||||
use Illuminate\Contracts\Container\Container;
|
||||
use Illuminate\Contracts\Queue\Queue;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\PendingChain;
|
||||
use Illuminate\Pipeline\Pipeline;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\Jobs\SyncJob;
|
||||
use Illuminate\Support\Collection;
|
||||
use RuntimeException;
|
||||
|
||||
class Dispatcher implements QueueingDispatcher
|
||||
{
|
||||
/**
|
||||
* The container implementation.
|
||||
*
|
||||
* @var \Illuminate\Contracts\Container\Container
|
||||
*/
|
||||
protected $container;
|
||||
|
||||
/**
|
||||
* The pipeline instance for the bus.
|
||||
*
|
||||
* @var \Illuminate\Pipeline\Pipeline
|
||||
*/
|
||||
protected $pipeline;
|
||||
|
||||
/**
|
||||
* The pipes to send commands through before dispatching.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $pipes = [];
|
||||
|
||||
/**
|
||||
* The command to handler mapping for non-self-handling events.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $handlers = [];
|
||||
|
||||
/**
|
||||
* The queue resolver callback.
|
||||
*
|
||||
* @var \Closure|null
|
||||
*/
|
||||
protected $queueResolver;
|
||||
|
||||
/**
|
||||
* Create a new command dispatcher instance.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Container\Container $container
|
||||
* @param \Closure|null $queueResolver
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Container $container, Closure $queueResolver = null)
|
||||
{
|
||||
$this->container = $container;
|
||||
$this->queueResolver = $queueResolver;
|
||||
$this->pipeline = new Pipeline($container);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatch a command to its appropriate handler.
|
||||
*
|
||||
* @param mixed $command
|
||||
* @return mixed
|
||||
*/
|
||||
public function dispatch($command)
|
||||
{
|
||||
return $this->queueResolver && $this->commandShouldBeQueued($command)
|
||||
? $this->dispatchToQueue($command)
|
||||
: $this->dispatchNow($command);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatch a command to its appropriate handler in the current process.
|
||||
*
|
||||
* Queueable jobs will be dispatched to the "sync" queue.
|
||||
*
|
||||
* @param mixed $command
|
||||
* @param mixed $handler
|
||||
* @return mixed
|
||||
*/
|
||||
public function dispatchSync($command, $handler = null)
|
||||
{
|
||||
if ($this->queueResolver &&
|
||||
$this->commandShouldBeQueued($command) &&
|
||||
method_exists($command, 'onConnection')) {
|
||||
return $this->dispatchToQueue($command->onConnection('sync'));
|
||||
}
|
||||
|
||||
return $this->dispatchNow($command, $handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatch a command to its appropriate handler in the current process without using the synchronous queue.
|
||||
*
|
||||
* @param mixed $command
|
||||
* @param mixed $handler
|
||||
* @return mixed
|
||||
*/
|
||||
public function dispatchNow($command, $handler = null)
|
||||
{
|
||||
$uses = class_uses_recursive($command);
|
||||
|
||||
if (in_array(InteractsWithQueue::class, $uses) &&
|
||||
in_array(Queueable::class, $uses) &&
|
||||
! $command->job) {
|
||||
$command->setJob(new SyncJob($this->container, json_encode([]), 'sync', 'sync'));
|
||||
}
|
||||
|
||||
if ($handler || $handler = $this->getCommandHandler($command)) {
|
||||
$callback = function ($command) use ($handler) {
|
||||
$method = method_exists($handler, 'handle') ? 'handle' : '__invoke';
|
||||
|
||||
return $handler->{$method}($command);
|
||||
};
|
||||
} else {
|
||||
$callback = function ($command) {
|
||||
$method = method_exists($command, 'handle') ? 'handle' : '__invoke';
|
||||
|
||||
return $this->container->call([$command, $method]);
|
||||
};
|
||||
}
|
||||
|
||||
return $this->pipeline->send($command)->through($this->pipes)->then($callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to find the batch with the given ID.
|
||||
*
|
||||
* @param string $batchId
|
||||
* @return \Illuminate\Bus\Batch|null
|
||||
*/
|
||||
public function findBatch(string $batchId)
|
||||
{
|
||||
return $this->container->make(BatchRepository::class)->find($batchId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new batch of queueable jobs.
|
||||
*
|
||||
* @param \Illuminate\Support\Collection|array|mixed $jobs
|
||||
* @return \Illuminate\Bus\PendingBatch
|
||||
*/
|
||||
public function batch($jobs)
|
||||
{
|
||||
return new PendingBatch($this->container, Collection::wrap($jobs));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new chain of queueable jobs.
|
||||
*
|
||||
* @param \Illuminate\Support\Collection|array $jobs
|
||||
* @return \Illuminate\Foundation\Bus\PendingChain
|
||||
*/
|
||||
public function chain($jobs)
|
||||
{
|
||||
$jobs = Collection::wrap($jobs);
|
||||
|
||||
return new PendingChain($jobs->shift(), $jobs->toArray());
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given command has a handler.
|
||||
*
|
||||
* @param mixed $command
|
||||
* @return bool
|
||||
*/
|
||||
public function hasCommandHandler($command)
|
||||
{
|
||||
return array_key_exists(get_class($command), $this->handlers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the handler for a command.
|
||||
*
|
||||
* @param mixed $command
|
||||
* @return bool|mixed
|
||||
*/
|
||||
public function getCommandHandler($command)
|
||||
{
|
||||
if ($this->hasCommandHandler($command)) {
|
||||
return $this->container->make($this->handlers[get_class($command)]);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given command should be queued.
|
||||
*
|
||||
* @param mixed $command
|
||||
* @return bool
|
||||
*/
|
||||
protected function commandShouldBeQueued($command)
|
||||
{
|
||||
return $command instanceof ShouldQueue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatch a command to its appropriate handler behind a queue.
|
||||
*
|
||||
* @param mixed $command
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function dispatchToQueue($command)
|
||||
{
|
||||
$connection = $command->connection ?? null;
|
||||
|
||||
$queue = call_user_func($this->queueResolver, $connection);
|
||||
|
||||
if (! $queue instanceof Queue) {
|
||||
throw new RuntimeException('Queue resolver did not return a Queue implementation.');
|
||||
}
|
||||
|
||||
if (method_exists($command, 'queue')) {
|
||||
return $command->queue($queue, $command);
|
||||
}
|
||||
|
||||
return $this->pushCommandToQueue($queue, $command);
|
||||
}
|
||||
|
||||
/**
|
||||
* Push the command onto the given queue instance.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Queue\Queue $queue
|
||||
* @param mixed $command
|
||||
* @return mixed
|
||||
*/
|
||||
protected function pushCommandToQueue($queue, $command)
|
||||
{
|
||||
if (isset($command->queue, $command->delay)) {
|
||||
return $queue->laterOn($command->queue, $command->delay, $command);
|
||||
}
|
||||
|
||||
if (isset($command->queue)) {
|
||||
return $queue->pushOn($command->queue, $command);
|
||||
}
|
||||
|
||||
if (isset($command->delay)) {
|
||||
return $queue->later($command->delay, $command);
|
||||
}
|
||||
|
||||
return $queue->push($command);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatch a command to its appropriate handler after the current process.
|
||||
*
|
||||
* @param mixed $command
|
||||
* @param mixed $handler
|
||||
* @return void
|
||||
*/
|
||||
public function dispatchAfterResponse($command, $handler = null)
|
||||
{
|
||||
$this->container->terminating(function () use ($command, $handler) {
|
||||
$this->dispatchNow($command, $handler);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the pipes through which commands should be piped before dispatching.
|
||||
*
|
||||
* @param array $pipes
|
||||
* @return $this
|
||||
*/
|
||||
public function pipeThrough(array $pipes)
|
||||
{
|
||||
$this->pipes = $pipes;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Map a command to a handler.
|
||||
*
|
||||
* @param array $map
|
||||
* @return $this
|
||||
*/
|
||||
public function map(array $map)
|
||||
{
|
||||
$this->handlers = array_merge($this->handlers, $map);
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Bus\Events;
|
||||
|
||||
use Illuminate\Bus\Batch;
|
||||
|
||||
class BatchDispatched
|
||||
{
|
||||
/**
|
||||
* The batch instance.
|
||||
*
|
||||
* @var \Illuminate\Bus\Batch
|
||||
*/
|
||||
public $batch;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param \Illuminate\Bus\Batch $batch
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Batch $batch)
|
||||
{
|
||||
$this->batch = $batch;
|
||||
}
|
||||
}
|
||||
Vendored
+21
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) Taylor Otwell
|
||||
|
||||
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.
|
||||
+258
@@ -0,0 +1,258 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Bus;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Bus\Events\BatchDispatched;
|
||||
use Illuminate\Contracts\Container\Container;
|
||||
use Illuminate\Contracts\Events\Dispatcher as EventDispatcher;
|
||||
use Illuminate\Queue\SerializableClosure;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Collection;
|
||||
use Throwable;
|
||||
|
||||
class PendingBatch
|
||||
{
|
||||
/**
|
||||
* The IoC container instance.
|
||||
*
|
||||
* @var \Illuminate\Contracts\Container\Container
|
||||
*/
|
||||
protected $container;
|
||||
|
||||
/**
|
||||
* The batch name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $name = '';
|
||||
|
||||
/**
|
||||
* The jobs that belong to the batch.
|
||||
*
|
||||
* @var \Illuminate\Support\Collection
|
||||
*/
|
||||
public $jobs;
|
||||
|
||||
/**
|
||||
* The batch options.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $options = [];
|
||||
|
||||
/**
|
||||
* Create a new pending batch instance.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Container\Container $container
|
||||
* @param \Illuminate\Support\Collection $jobs
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Container $container, Collection $jobs)
|
||||
{
|
||||
$this->container = $container;
|
||||
$this->jobs = $jobs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add jobs to the batch.
|
||||
*
|
||||
* @param iterable $jobs
|
||||
* @return $this
|
||||
*/
|
||||
public function add($jobs)
|
||||
{
|
||||
foreach ($jobs as $job) {
|
||||
$this->jobs->push($job);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a callback to be executed after all jobs in the batch have executed successfully.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @return $this
|
||||
*/
|
||||
public function then($callback)
|
||||
{
|
||||
$this->options['then'][] = $callback instanceof Closure
|
||||
? new SerializableClosure($callback)
|
||||
: $callback;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the "then" callbacks that have been registered with the pending batch.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function thenCallbacks()
|
||||
{
|
||||
return $this->options['then'] ?? [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a callback to be executed after the first failing job in the batch.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @return $this
|
||||
*/
|
||||
public function catch($callback)
|
||||
{
|
||||
$this->options['catch'][] = $callback instanceof Closure
|
||||
? new SerializableClosure($callback)
|
||||
: $callback;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the "catch" callbacks that have been registered with the pending batch.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function catchCallbacks()
|
||||
{
|
||||
return $this->options['catch'] ?? [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a callback to be executed after the batch has finished executing.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @return $this
|
||||
*/
|
||||
public function finally($callback)
|
||||
{
|
||||
$this->options['finally'][] = $callback instanceof Closure
|
||||
? new SerializableClosure($callback)
|
||||
: $callback;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the "finally" callbacks that have been registered with the pending batch.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function finallyCallbacks()
|
||||
{
|
||||
return $this->options['finally'] ?? [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate that the batch should not be cancelled when a job within the batch fails.
|
||||
*
|
||||
* @param bool $allowFailures
|
||||
* @return $this
|
||||
*/
|
||||
public function allowFailures($allowFailures = true)
|
||||
{
|
||||
$this->options['allowFailures'] = $allowFailures;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the pending batch allows jobs to fail without cancelling the batch.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function allowsFailures()
|
||||
{
|
||||
return Arr::get($this->options, 'allowFailures', false) === true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the name for the batch.
|
||||
*
|
||||
* @param string $name
|
||||
* @return $this
|
||||
*/
|
||||
public function name(string $name)
|
||||
{
|
||||
$this->name = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the queue connection that the batched jobs should run on.
|
||||
*
|
||||
* @param string $connection
|
||||
* @return $this
|
||||
*/
|
||||
public function onConnection(string $connection)
|
||||
{
|
||||
$this->options['connection'] = $connection;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the connection used by the pending batch.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function connection()
|
||||
{
|
||||
return $this->options['connection'] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the queue that the batched jobs should run on.
|
||||
*
|
||||
* @param string $queue
|
||||
* @return $this
|
||||
*/
|
||||
public function onQueue(string $queue)
|
||||
{
|
||||
$this->options['queue'] = $queue;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the queue used by the pending batch.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function queue()
|
||||
{
|
||||
return $this->options['queue'] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatch the batch.
|
||||
*
|
||||
* @return \Illuminate\Bus\Batch
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function dispatch()
|
||||
{
|
||||
$repository = $this->container->make(BatchRepository::class);
|
||||
|
||||
try {
|
||||
$batch = $repository->store($this);
|
||||
|
||||
$batch = $batch->add($this->jobs);
|
||||
} catch (Throwable $e) {
|
||||
if (isset($batch)) {
|
||||
$repository->delete($batch->id);
|
||||
}
|
||||
|
||||
throw $e;
|
||||
}
|
||||
|
||||
$this->container->make(EventDispatcher::class)->dispatch(
|
||||
new BatchDispatched($batch)
|
||||
);
|
||||
|
||||
return $batch;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Bus;
|
||||
|
||||
use DateTimeInterface;
|
||||
|
||||
interface PrunableBatchRepository extends BatchRepository
|
||||
{
|
||||
/**
|
||||
* Prune all of the entries older than the given date.
|
||||
*
|
||||
* @param \DateTimeInterface $before
|
||||
* @return int
|
||||
*/
|
||||
public function prune(DateTimeInterface $before);
|
||||
}
|
||||
Vendored
+251
@@ -0,0 +1,251 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Bus;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Queue\CallQueuedClosure;
|
||||
use Illuminate\Queue\SerializableClosure;
|
||||
use Illuminate\Support\Arr;
|
||||
use RuntimeException;
|
||||
|
||||
trait Queueable
|
||||
{
|
||||
/**
|
||||
* The name of the connection the job should be sent to.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
public $connection;
|
||||
|
||||
/**
|
||||
* The name of the queue the job should be sent to.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
public $queue;
|
||||
|
||||
/**
|
||||
* The name of the connection the chain should be sent to.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
public $chainConnection;
|
||||
|
||||
/**
|
||||
* The name of the queue the chain should be sent to.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
public $chainQueue;
|
||||
|
||||
/**
|
||||
* The callbacks to be executed on chain failure.
|
||||
*
|
||||
* @var array|null
|
||||
*/
|
||||
public $chainCatchCallbacks;
|
||||
|
||||
/**
|
||||
* The number of seconds before the job should be made available.
|
||||
*
|
||||
* @var \DateTimeInterface|\DateInterval|int|null
|
||||
*/
|
||||
public $delay;
|
||||
|
||||
/**
|
||||
* Indicates whether the job should be dispatched after all database transactions have committed.
|
||||
*
|
||||
* @var bool|null
|
||||
*/
|
||||
public $afterCommit;
|
||||
|
||||
/**
|
||||
* The middleware the job should be dispatched through.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $middleware = [];
|
||||
|
||||
/**
|
||||
* The jobs that should run if this job is successful.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $chained = [];
|
||||
|
||||
/**
|
||||
* Set the desired connection for the job.
|
||||
*
|
||||
* @param string|null $connection
|
||||
* @return $this
|
||||
*/
|
||||
public function onConnection($connection)
|
||||
{
|
||||
$this->connection = $connection;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the desired queue for the job.
|
||||
*
|
||||
* @param string|null $queue
|
||||
* @return $this
|
||||
*/
|
||||
public function onQueue($queue)
|
||||
{
|
||||
$this->queue = $queue;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the desired connection for the chain.
|
||||
*
|
||||
* @param string|null $connection
|
||||
* @return $this
|
||||
*/
|
||||
public function allOnConnection($connection)
|
||||
{
|
||||
$this->chainConnection = $connection;
|
||||
$this->connection = $connection;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the desired queue for the chain.
|
||||
*
|
||||
* @param string|null $queue
|
||||
* @return $this
|
||||
*/
|
||||
public function allOnQueue($queue)
|
||||
{
|
||||
$this->chainQueue = $queue;
|
||||
$this->queue = $queue;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the desired delay for the job.
|
||||
*
|
||||
* @param \DateTimeInterface|\DateInterval|int|null $delay
|
||||
* @return $this
|
||||
*/
|
||||
public function delay($delay)
|
||||
{
|
||||
$this->delay = $delay;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate that the job should be dispatched after all database transactions have committed.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function afterCommit()
|
||||
{
|
||||
$this->afterCommit = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate that the job should not wait until database transactions have been committed before dispatching.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function beforeCommit()
|
||||
{
|
||||
$this->afterCommit = false;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the middleware the job should be dispatched through.
|
||||
*
|
||||
* @param array|object $middleware
|
||||
* @return $this
|
||||
*/
|
||||
public function through($middleware)
|
||||
{
|
||||
$this->middleware = Arr::wrap($middleware);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the jobs that should run if this job is successful.
|
||||
*
|
||||
* @param array $chain
|
||||
* @return $this
|
||||
*/
|
||||
public function chain($chain)
|
||||
{
|
||||
$this->chained = collect($chain)->map(function ($job) {
|
||||
return $this->serializeJob($job);
|
||||
})->all();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize a job for queuing.
|
||||
*
|
||||
* @param mixed $job
|
||||
* @return string
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
protected function serializeJob($job)
|
||||
{
|
||||
if ($job instanceof Closure) {
|
||||
if (! class_exists(CallQueuedClosure::class)) {
|
||||
throw new RuntimeException(
|
||||
'To enable support for closure jobs, please install the illuminate/queue package.'
|
||||
);
|
||||
}
|
||||
|
||||
$job = CallQueuedClosure::create($job);
|
||||
}
|
||||
|
||||
return serialize($job);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatch the next job on the chain.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function dispatchNextJobInChain()
|
||||
{
|
||||
if (! empty($this->chained)) {
|
||||
dispatch(tap(unserialize(array_shift($this->chained)), function ($next) {
|
||||
$next->chained = $this->chained;
|
||||
|
||||
$next->onConnection($next->connection ?: $this->chainConnection);
|
||||
$next->onQueue($next->queue ?: $this->chainQueue);
|
||||
|
||||
$next->chainConnection = $this->chainConnection;
|
||||
$next->chainQueue = $this->chainQueue;
|
||||
$next->chainCatchCallbacks = $this->chainCatchCallbacks;
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke all of the chain's failed job callbacks.
|
||||
*
|
||||
* @param \Throwable $e
|
||||
* @return void
|
||||
*/
|
||||
public function invokeChainCatchCallbacks($e)
|
||||
{
|
||||
collect($this->chainCatchCallbacks)->each(function ($callback) use ($e) {
|
||||
$callback instanceof SerializableClosure ? $callback->__invoke($e) : call_user_func($callback, $e);
|
||||
});
|
||||
}
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Bus;
|
||||
|
||||
class UpdatedBatchJobCounts
|
||||
{
|
||||
/**
|
||||
* The number of pending jobs remaining for the batch.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $pendingJobs;
|
||||
|
||||
/**
|
||||
* The number of failed jobs that belong to the batch.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $failedJobs;
|
||||
|
||||
/**
|
||||
* Create a new batch job counts object.
|
||||
*
|
||||
* @param int $pendingJobs
|
||||
* @param int $failedJobs
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(int $pendingJobs = 0, int $failedJobs = 0)
|
||||
{
|
||||
$this->pendingJobs = $pendingJobs;
|
||||
$this->failedJobs = $failedJobs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if all jobs have run exactly once.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function allJobsHaveRanExactlyOnce()
|
||||
{
|
||||
return ($this->pendingJobs - $this->failedJobs) === 0;
|
||||
}
|
||||
}
|
||||
Vendored
+40
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"name": "illuminate/bus",
|
||||
"description": "The Illuminate Bus package.",
|
||||
"license": "MIT",
|
||||
"homepage": "https://laravel.com",
|
||||
"support": {
|
||||
"issues": "https://github.com/laravel/framework/issues",
|
||||
"source": "https://github.com/laravel/framework"
|
||||
},
|
||||
"authors": [
|
||||
{
|
||||
"name": "Taylor Otwell",
|
||||
"email": "taylor@laravel.com"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": "^7.3|^8.0",
|
||||
"illuminate/collections": "^8.0",
|
||||
"illuminate/contracts": "^8.0",
|
||||
"illuminate/pipeline": "^8.0",
|
||||
"illuminate/support": "^8.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Illuminate\\Bus\\": ""
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "8.x-dev"
|
||||
}
|
||||
},
|
||||
"suggest": {
|
||||
"illuminate/queue": "Required to use closures when chaining jobs (^7.0)."
|
||||
},
|
||||
"config": {
|
||||
"sort-packages": true
|
||||
},
|
||||
"minimum-stability": "dev"
|
||||
}
|
||||
+704
@@ -0,0 +1,704 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Support;
|
||||
|
||||
use ArrayAccess;
|
||||
use Illuminate\Support\Traits\Macroable;
|
||||
use InvalidArgumentException;
|
||||
|
||||
class Arr
|
||||
{
|
||||
use Macroable;
|
||||
|
||||
/**
|
||||
* Determine whether the given value is array accessible.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return bool
|
||||
*/
|
||||
public static function accessible($value)
|
||||
{
|
||||
return is_array($value) || $value instanceof ArrayAccess;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an element to an array using "dot" notation if it doesn't exist.
|
||||
*
|
||||
* @param array $array
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @return array
|
||||
*/
|
||||
public static function add($array, $key, $value)
|
||||
{
|
||||
if (is_null(static::get($array, $key))) {
|
||||
static::set($array, $key, $value);
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Collapse an array of arrays into a single array.
|
||||
*
|
||||
* @param iterable $array
|
||||
* @return array
|
||||
*/
|
||||
public static function collapse($array)
|
||||
{
|
||||
$results = [];
|
||||
|
||||
foreach ($array as $values) {
|
||||
if ($values instanceof Collection) {
|
||||
$values = $values->all();
|
||||
} elseif (! is_array($values)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$results[] = $values;
|
||||
}
|
||||
|
||||
return array_merge([], ...$results);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cross join the given arrays, returning all possible permutations.
|
||||
*
|
||||
* @param iterable ...$arrays
|
||||
* @return array
|
||||
*/
|
||||
public static function crossJoin(...$arrays)
|
||||
{
|
||||
$results = [[]];
|
||||
|
||||
foreach ($arrays as $index => $array) {
|
||||
$append = [];
|
||||
|
||||
foreach ($results as $product) {
|
||||
foreach ($array as $item) {
|
||||
$product[$index] = $item;
|
||||
|
||||
$append[] = $product;
|
||||
}
|
||||
}
|
||||
|
||||
$results = $append;
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Divide an array into two arrays. One with keys and the other with values.
|
||||
*
|
||||
* @param array $array
|
||||
* @return array
|
||||
*/
|
||||
public static function divide($array)
|
||||
{
|
||||
return [array_keys($array), array_values($array)];
|
||||
}
|
||||
|
||||
/**
|
||||
* Flatten a multi-dimensional associative array with dots.
|
||||
*
|
||||
* @param iterable $array
|
||||
* @param string $prepend
|
||||
* @return array
|
||||
*/
|
||||
public static function dot($array, $prepend = '')
|
||||
{
|
||||
$results = [];
|
||||
|
||||
foreach ($array as $key => $value) {
|
||||
if (is_array($value) && ! empty($value)) {
|
||||
$results = array_merge($results, static::dot($value, $prepend.$key.'.'));
|
||||
} else {
|
||||
$results[$prepend.$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the given array except for a specified array of keys.
|
||||
*
|
||||
* @param array $array
|
||||
* @param array|string $keys
|
||||
* @return array
|
||||
*/
|
||||
public static function except($array, $keys)
|
||||
{
|
||||
static::forget($array, $keys);
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given key exists in the provided array.
|
||||
*
|
||||
* @param \ArrayAccess|array $array
|
||||
* @param string|int $key
|
||||
* @return bool
|
||||
*/
|
||||
public static function exists($array, $key)
|
||||
{
|
||||
if ($array instanceof Enumerable) {
|
||||
return $array->has($key);
|
||||
}
|
||||
|
||||
if ($array instanceof ArrayAccess) {
|
||||
return $array->offsetExists($key);
|
||||
}
|
||||
|
||||
return array_key_exists($key, $array);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the first element in an array passing a given truth test.
|
||||
*
|
||||
* @param iterable $array
|
||||
* @param callable|null $callback
|
||||
* @param mixed $default
|
||||
* @return mixed
|
||||
*/
|
||||
public static function first($array, callable $callback = null, $default = null)
|
||||
{
|
||||
if (is_null($callback)) {
|
||||
if (empty($array)) {
|
||||
return value($default);
|
||||
}
|
||||
|
||||
foreach ($array as $item) {
|
||||
return $item;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($array as $key => $value) {
|
||||
if ($callback($value, $key)) {
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
||||
return value($default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the last element in an array passing a given truth test.
|
||||
*
|
||||
* @param array $array
|
||||
* @param callable|null $callback
|
||||
* @param mixed $default
|
||||
* @return mixed
|
||||
*/
|
||||
public static function last($array, callable $callback = null, $default = null)
|
||||
{
|
||||
if (is_null($callback)) {
|
||||
return empty($array) ? value($default) : end($array);
|
||||
}
|
||||
|
||||
return static::first(array_reverse($array, true), $callback, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Flatten a multi-dimensional array into a single level.
|
||||
*
|
||||
* @param iterable $array
|
||||
* @param int $depth
|
||||
* @return array
|
||||
*/
|
||||
public static function flatten($array, $depth = INF)
|
||||
{
|
||||
$result = [];
|
||||
|
||||
foreach ($array as $item) {
|
||||
$item = $item instanceof Collection ? $item->all() : $item;
|
||||
|
||||
if (! is_array($item)) {
|
||||
$result[] = $item;
|
||||
} else {
|
||||
$values = $depth === 1
|
||||
? array_values($item)
|
||||
: static::flatten($item, $depth - 1);
|
||||
|
||||
foreach ($values as $value) {
|
||||
$result[] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove one or many array items from a given array using "dot" notation.
|
||||
*
|
||||
* @param array $array
|
||||
* @param array|string $keys
|
||||
* @return void
|
||||
*/
|
||||
public static function forget(&$array, $keys)
|
||||
{
|
||||
$original = &$array;
|
||||
|
||||
$keys = (array) $keys;
|
||||
|
||||
if (count($keys) === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($keys as $key) {
|
||||
// if the exact key exists in the top-level, remove it
|
||||
if (static::exists($array, $key)) {
|
||||
unset($array[$key]);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$parts = explode('.', $key);
|
||||
|
||||
// clean up before each pass
|
||||
$array = &$original;
|
||||
|
||||
while (count($parts) > 1) {
|
||||
$part = array_shift($parts);
|
||||
|
||||
if (isset($array[$part]) && is_array($array[$part])) {
|
||||
$array = &$array[$part];
|
||||
} else {
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
|
||||
unset($array[array_shift($parts)]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an item from an array using "dot" notation.
|
||||
*
|
||||
* @param \ArrayAccess|array $array
|
||||
* @param string|int|null $key
|
||||
* @param mixed $default
|
||||
* @return mixed
|
||||
*/
|
||||
public static function get($array, $key, $default = null)
|
||||
{
|
||||
if (! static::accessible($array)) {
|
||||
return value($default);
|
||||
}
|
||||
|
||||
if (is_null($key)) {
|
||||
return $array;
|
||||
}
|
||||
|
||||
if (static::exists($array, $key)) {
|
||||
return $array[$key];
|
||||
}
|
||||
|
||||
if (strpos($key, '.') === false) {
|
||||
return $array[$key] ?? value($default);
|
||||
}
|
||||
|
||||
foreach (explode('.', $key) as $segment) {
|
||||
if (static::accessible($array) && static::exists($array, $segment)) {
|
||||
$array = $array[$segment];
|
||||
} else {
|
||||
return value($default);
|
||||
}
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if an item or items exist in an array using "dot" notation.
|
||||
*
|
||||
* @param \ArrayAccess|array $array
|
||||
* @param string|array $keys
|
||||
* @return bool
|
||||
*/
|
||||
public static function has($array, $keys)
|
||||
{
|
||||
$keys = (array) $keys;
|
||||
|
||||
if (! $array || $keys === []) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ($keys as $key) {
|
||||
$subKeyArray = $array;
|
||||
|
||||
if (static::exists($array, $key)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (explode('.', $key) as $segment) {
|
||||
if (static::accessible($subKeyArray) && static::exists($subKeyArray, $segment)) {
|
||||
$subKeyArray = $subKeyArray[$segment];
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if any of the keys exist in an array using "dot" notation.
|
||||
*
|
||||
* @param \ArrayAccess|array $array
|
||||
* @param string|array $keys
|
||||
* @return bool
|
||||
*/
|
||||
public static function hasAny($array, $keys)
|
||||
{
|
||||
if (is_null($keys)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$keys = (array) $keys;
|
||||
|
||||
if (! $array) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($keys === []) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ($keys as $key) {
|
||||
if (static::has($array, $key)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if an array is associative.
|
||||
*
|
||||
* An array is "associative" if it doesn't have sequential numerical keys beginning with zero.
|
||||
*
|
||||
* @param array $array
|
||||
* @return bool
|
||||
*/
|
||||
public static function isAssoc(array $array)
|
||||
{
|
||||
$keys = array_keys($array);
|
||||
|
||||
return array_keys($keys) !== $keys;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a subset of the items from the given array.
|
||||
*
|
||||
* @param array $array
|
||||
* @param array|string $keys
|
||||
* @return array
|
||||
*/
|
||||
public static function only($array, $keys)
|
||||
{
|
||||
return array_intersect_key($array, array_flip((array) $keys));
|
||||
}
|
||||
|
||||
/**
|
||||
* Pluck an array of values from an array.
|
||||
*
|
||||
* @param iterable $array
|
||||
* @param string|array|int|null $value
|
||||
* @param string|array|null $key
|
||||
* @return array
|
||||
*/
|
||||
public static function pluck($array, $value, $key = null)
|
||||
{
|
||||
$results = [];
|
||||
|
||||
[$value, $key] = static::explodePluckParameters($value, $key);
|
||||
|
||||
foreach ($array as $item) {
|
||||
$itemValue = data_get($item, $value);
|
||||
|
||||
// If the key is "null", we will just append the value to the array and keep
|
||||
// looping. Otherwise we will key the array using the value of the key we
|
||||
// received from the developer. Then we'll return the final array form.
|
||||
if (is_null($key)) {
|
||||
$results[] = $itemValue;
|
||||
} else {
|
||||
$itemKey = data_get($item, $key);
|
||||
|
||||
if (is_object($itemKey) && method_exists($itemKey, '__toString')) {
|
||||
$itemKey = (string) $itemKey;
|
||||
}
|
||||
|
||||
$results[$itemKey] = $itemValue;
|
||||
}
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Explode the "value" and "key" arguments passed to "pluck".
|
||||
*
|
||||
* @param string|array $value
|
||||
* @param string|array|null $key
|
||||
* @return array
|
||||
*/
|
||||
protected static function explodePluckParameters($value, $key)
|
||||
{
|
||||
$value = is_string($value) ? explode('.', $value) : $value;
|
||||
|
||||
$key = is_null($key) || is_array($key) ? $key : explode('.', $key);
|
||||
|
||||
return [$value, $key];
|
||||
}
|
||||
|
||||
/**
|
||||
* Push an item onto the beginning of an array.
|
||||
*
|
||||
* @param array $array
|
||||
* @param mixed $value
|
||||
* @param mixed $key
|
||||
* @return array
|
||||
*/
|
||||
public static function prepend($array, $value, $key = null)
|
||||
{
|
||||
if (func_num_args() == 2) {
|
||||
array_unshift($array, $value);
|
||||
} else {
|
||||
$array = [$key => $value] + $array;
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a value from the array, and remove it.
|
||||
*
|
||||
* @param array $array
|
||||
* @param string $key
|
||||
* @param mixed $default
|
||||
* @return mixed
|
||||
*/
|
||||
public static function pull(&$array, $key, $default = null)
|
||||
{
|
||||
$value = static::get($array, $key, $default);
|
||||
|
||||
static::forget($array, $key);
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the array into a query string.
|
||||
*
|
||||
* @param array $array
|
||||
* @return string
|
||||
*/
|
||||
public static function query($array)
|
||||
{
|
||||
return http_build_query($array, '', '&', PHP_QUERY_RFC3986);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get one or a specified number of random values from an array.
|
||||
*
|
||||
* @param array $array
|
||||
* @param int|null $number
|
||||
* @param bool|false $preserveKeys
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public static function random($array, $number = null, $preserveKeys = false)
|
||||
{
|
||||
$requested = is_null($number) ? 1 : $number;
|
||||
|
||||
$count = count($array);
|
||||
|
||||
if ($requested > $count) {
|
||||
throw new InvalidArgumentException(
|
||||
"You requested {$requested} items, but there are only {$count} items available."
|
||||
);
|
||||
}
|
||||
|
||||
if (is_null($number)) {
|
||||
return $array[array_rand($array)];
|
||||
}
|
||||
|
||||
if ((int) $number === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$keys = array_rand($array, $number);
|
||||
|
||||
$results = [];
|
||||
|
||||
if ($preserveKeys) {
|
||||
foreach ((array) $keys as $key) {
|
||||
$results[$key] = $array[$key];
|
||||
}
|
||||
} else {
|
||||
foreach ((array) $keys as $key) {
|
||||
$results[] = $array[$key];
|
||||
}
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an array item to a given value using "dot" notation.
|
||||
*
|
||||
* If no key is given to the method, the entire array will be replaced.
|
||||
*
|
||||
* @param array $array
|
||||
* @param string|null $key
|
||||
* @param mixed $value
|
||||
* @return array
|
||||
*/
|
||||
public static function set(&$array, $key, $value)
|
||||
{
|
||||
if (is_null($key)) {
|
||||
return $array = $value;
|
||||
}
|
||||
|
||||
$keys = explode('.', $key);
|
||||
|
||||
foreach ($keys as $i => $key) {
|
||||
if (count($keys) === 1) {
|
||||
break;
|
||||
}
|
||||
|
||||
unset($keys[$i]);
|
||||
|
||||
// If the key doesn't exist at this depth, we will just create an empty array
|
||||
// to hold the next value, allowing us to create the arrays to hold final
|
||||
// values at the correct depth. Then we'll keep digging into the array.
|
||||
if (! isset($array[$key]) || ! is_array($array[$key])) {
|
||||
$array[$key] = [];
|
||||
}
|
||||
|
||||
$array = &$array[$key];
|
||||
}
|
||||
|
||||
$array[array_shift($keys)] = $value;
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shuffle the given array and return the result.
|
||||
*
|
||||
* @param array $array
|
||||
* @param int|null $seed
|
||||
* @return array
|
||||
*/
|
||||
public static function shuffle($array, $seed = null)
|
||||
{
|
||||
if (is_null($seed)) {
|
||||
shuffle($array);
|
||||
} else {
|
||||
mt_srand($seed);
|
||||
shuffle($array);
|
||||
mt_srand();
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort the array using the given callback or "dot" notation.
|
||||
*
|
||||
* @param array $array
|
||||
* @param callable|array|string|null $callback
|
||||
* @return array
|
||||
*/
|
||||
public static function sort($array, $callback = null)
|
||||
{
|
||||
return Collection::make($array)->sortBy($callback)->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively sort an array by keys and values.
|
||||
*
|
||||
* @param array $array
|
||||
* @param int $options
|
||||
* @param bool $descending
|
||||
* @return array
|
||||
*/
|
||||
public static function sortRecursive($array, $options = SORT_REGULAR, $descending = false)
|
||||
{
|
||||
foreach ($array as &$value) {
|
||||
if (is_array($value)) {
|
||||
$value = static::sortRecursive($value, $options, $descending);
|
||||
}
|
||||
}
|
||||
|
||||
if (static::isAssoc($array)) {
|
||||
$descending
|
||||
? krsort($array, $options)
|
||||
: ksort($array, $options);
|
||||
} else {
|
||||
$descending
|
||||
? rsort($array, $options)
|
||||
: sort($array, $options);
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Conditionally compile classes from an array into a CSS class list.
|
||||
*
|
||||
* @param array $array
|
||||
* @return string
|
||||
*/
|
||||
public static function toCssClasses($array)
|
||||
{
|
||||
$classList = static::wrap($array);
|
||||
|
||||
$classes = [];
|
||||
|
||||
foreach ($classList as $class => $constraint) {
|
||||
if (is_numeric($class)) {
|
||||
$classes[] = $constraint;
|
||||
} elseif ($constraint) {
|
||||
$classes[] = $class;
|
||||
}
|
||||
}
|
||||
|
||||
return implode(' ', $classes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the array using the given callback.
|
||||
*
|
||||
* @param array $array
|
||||
* @param callable $callback
|
||||
* @return array
|
||||
*/
|
||||
public static function where($array, callable $callback)
|
||||
{
|
||||
return array_filter($array, $callback, ARRAY_FILTER_USE_BOTH);
|
||||
}
|
||||
|
||||
/**
|
||||
* If the given value is not an array and not null, wrap it in one.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return array
|
||||
*/
|
||||
public static function wrap($value)
|
||||
{
|
||||
if (is_null($value)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return is_array($value) ? $value : [$value];
|
||||
}
|
||||
}
|
||||
+1566
@@ -0,0 +1,1566 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Support;
|
||||
|
||||
use ArrayAccess;
|
||||
use ArrayIterator;
|
||||
use Illuminate\Support\Traits\EnumeratesValues;
|
||||
use Illuminate\Support\Traits\Macroable;
|
||||
use stdClass;
|
||||
|
||||
class Collection implements ArrayAccess, Enumerable
|
||||
{
|
||||
use EnumeratesValues, Macroable;
|
||||
|
||||
/**
|
||||
* The items contained in the collection.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $items = [];
|
||||
|
||||
/**
|
||||
* Create a new collection.
|
||||
*
|
||||
* @param mixed $items
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($items = [])
|
||||
{
|
||||
$this->items = $this->getArrayableItems($items);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a collection with the given range.
|
||||
*
|
||||
* @param int $from
|
||||
* @param int $to
|
||||
* @return static
|
||||
*/
|
||||
public static function range($from, $to)
|
||||
{
|
||||
return new static(range($from, $to));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the items in the collection.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function all()
|
||||
{
|
||||
return $this->items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a lazy collection for the items in this collection.
|
||||
*
|
||||
* @return \Illuminate\Support\LazyCollection
|
||||
*/
|
||||
public function lazy()
|
||||
{
|
||||
return new LazyCollection($this->items);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the average value of a given key.
|
||||
*
|
||||
* @param callable|string|null $callback
|
||||
* @return mixed
|
||||
*/
|
||||
public function avg($callback = null)
|
||||
{
|
||||
$callback = $this->valueRetriever($callback);
|
||||
|
||||
$items = $this->map(function ($value) use ($callback) {
|
||||
return $callback($value);
|
||||
})->filter(function ($value) {
|
||||
return ! is_null($value);
|
||||
});
|
||||
|
||||
if ($count = $items->count()) {
|
||||
return $items->sum() / $count;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the median of a given key.
|
||||
*
|
||||
* @param string|array|null $key
|
||||
* @return mixed
|
||||
*/
|
||||
public function median($key = null)
|
||||
{
|
||||
$values = (isset($key) ? $this->pluck($key) : $this)
|
||||
->filter(function ($item) {
|
||||
return ! is_null($item);
|
||||
})->sort()->values();
|
||||
|
||||
$count = $values->count();
|
||||
|
||||
if ($count === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$middle = (int) ($count / 2);
|
||||
|
||||
if ($count % 2) {
|
||||
return $values->get($middle);
|
||||
}
|
||||
|
||||
return (new static([
|
||||
$values->get($middle - 1), $values->get($middle),
|
||||
]))->average();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mode of a given key.
|
||||
*
|
||||
* @param string|array|null $key
|
||||
* @return array|null
|
||||
*/
|
||||
public function mode($key = null)
|
||||
{
|
||||
if ($this->count() === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$collection = isset($key) ? $this->pluck($key) : $this;
|
||||
|
||||
$counts = new static;
|
||||
|
||||
$collection->each(function ($value) use ($counts) {
|
||||
$counts[$value] = isset($counts[$value]) ? $counts[$value] + 1 : 1;
|
||||
});
|
||||
|
||||
$sorted = $counts->sort();
|
||||
|
||||
$highestValue = $sorted->last();
|
||||
|
||||
return $sorted->filter(function ($value) use ($highestValue) {
|
||||
return $value == $highestValue;
|
||||
})->sort()->keys()->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Collapse the collection of items into a single array.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function collapse()
|
||||
{
|
||||
return new static(Arr::collapse($this->items));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if an item exists in the collection.
|
||||
*
|
||||
* @param mixed $key
|
||||
* @param mixed $operator
|
||||
* @param mixed $value
|
||||
* @return bool
|
||||
*/
|
||||
public function contains($key, $operator = null, $value = null)
|
||||
{
|
||||
if (func_num_args() === 1) {
|
||||
if ($this->useAsCallable($key)) {
|
||||
$placeholder = new stdClass;
|
||||
|
||||
return $this->first($key, $placeholder) !== $placeholder;
|
||||
}
|
||||
|
||||
return in_array($key, $this->items);
|
||||
}
|
||||
|
||||
return $this->contains($this->operatorForWhere(...func_get_args()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Cross join with the given lists, returning all possible permutations.
|
||||
*
|
||||
* @param mixed ...$lists
|
||||
* @return static
|
||||
*/
|
||||
public function crossJoin(...$lists)
|
||||
{
|
||||
return new static(Arr::crossJoin(
|
||||
$this->items, ...array_map([$this, 'getArrayableItems'], $lists)
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the items in the collection that are not present in the given items.
|
||||
*
|
||||
* @param mixed $items
|
||||
* @return static
|
||||
*/
|
||||
public function diff($items)
|
||||
{
|
||||
return new static(array_diff($this->items, $this->getArrayableItems($items)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the items in the collection that are not present in the given items, using the callback.
|
||||
*
|
||||
* @param mixed $items
|
||||
* @param callable $callback
|
||||
* @return static
|
||||
*/
|
||||
public function diffUsing($items, callable $callback)
|
||||
{
|
||||
return new static(array_udiff($this->items, $this->getArrayableItems($items), $callback));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the items in the collection whose keys and values are not present in the given items.
|
||||
*
|
||||
* @param mixed $items
|
||||
* @return static
|
||||
*/
|
||||
public function diffAssoc($items)
|
||||
{
|
||||
return new static(array_diff_assoc($this->items, $this->getArrayableItems($items)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the items in the collection whose keys and values are not present in the given items, using the callback.
|
||||
*
|
||||
* @param mixed $items
|
||||
* @param callable $callback
|
||||
* @return static
|
||||
*/
|
||||
public function diffAssocUsing($items, callable $callback)
|
||||
{
|
||||
return new static(array_diff_uassoc($this->items, $this->getArrayableItems($items), $callback));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the items in the collection whose keys are not present in the given items.
|
||||
*
|
||||
* @param mixed $items
|
||||
* @return static
|
||||
*/
|
||||
public function diffKeys($items)
|
||||
{
|
||||
return new static(array_diff_key($this->items, $this->getArrayableItems($items)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the items in the collection whose keys are not present in the given items, using the callback.
|
||||
*
|
||||
* @param mixed $items
|
||||
* @param callable $callback
|
||||
* @return static
|
||||
*/
|
||||
public function diffKeysUsing($items, callable $callback)
|
||||
{
|
||||
return new static(array_diff_ukey($this->items, $this->getArrayableItems($items), $callback));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve duplicate items from the collection.
|
||||
*
|
||||
* @param callable|string|null $callback
|
||||
* @param bool $strict
|
||||
* @return static
|
||||
*/
|
||||
public function duplicates($callback = null, $strict = false)
|
||||
{
|
||||
$items = $this->map($this->valueRetriever($callback));
|
||||
|
||||
$uniqueItems = $items->unique(null, $strict);
|
||||
|
||||
$compare = $this->duplicateComparator($strict);
|
||||
|
||||
$duplicates = new static;
|
||||
|
||||
foreach ($items as $key => $value) {
|
||||
if ($uniqueItems->isNotEmpty() && $compare($value, $uniqueItems->first())) {
|
||||
$uniqueItems->shift();
|
||||
} else {
|
||||
$duplicates[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $duplicates;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve duplicate items from the collection using strict comparison.
|
||||
*
|
||||
* @param callable|string|null $callback
|
||||
* @return static
|
||||
*/
|
||||
public function duplicatesStrict($callback = null)
|
||||
{
|
||||
return $this->duplicates($callback, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the comparison function to detect duplicates.
|
||||
*
|
||||
* @param bool $strict
|
||||
* @return \Closure
|
||||
*/
|
||||
protected function duplicateComparator($strict)
|
||||
{
|
||||
if ($strict) {
|
||||
return function ($a, $b) {
|
||||
return $a === $b;
|
||||
};
|
||||
}
|
||||
|
||||
return function ($a, $b) {
|
||||
return $a == $b;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all items except for those with the specified keys.
|
||||
*
|
||||
* @param \Illuminate\Support\Collection|mixed $keys
|
||||
* @return static
|
||||
*/
|
||||
public function except($keys)
|
||||
{
|
||||
if ($keys instanceof Enumerable) {
|
||||
$keys = $keys->all();
|
||||
} elseif (! is_array($keys)) {
|
||||
$keys = func_get_args();
|
||||
}
|
||||
|
||||
return new static(Arr::except($this->items, $keys));
|
||||
}
|
||||
|
||||
/**
|
||||
* Run a filter over each of the items.
|
||||
*
|
||||
* @param callable|null $callback
|
||||
* @return static
|
||||
*/
|
||||
public function filter(callable $callback = null)
|
||||
{
|
||||
if ($callback) {
|
||||
return new static(Arr::where($this->items, $callback));
|
||||
}
|
||||
|
||||
return new static(array_filter($this->items));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the first item from the collection passing the given truth test.
|
||||
*
|
||||
* @param callable|null $callback
|
||||
* @param mixed $default
|
||||
* @return mixed
|
||||
*/
|
||||
public function first(callable $callback = null, $default = null)
|
||||
{
|
||||
return Arr::first($this->items, $callback, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a flattened array of the items in the collection.
|
||||
*
|
||||
* @param int $depth
|
||||
* @return static
|
||||
*/
|
||||
public function flatten($depth = INF)
|
||||
{
|
||||
return new static(Arr::flatten($this->items, $depth));
|
||||
}
|
||||
|
||||
/**
|
||||
* Flip the items in the collection.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function flip()
|
||||
{
|
||||
return new static(array_flip($this->items));
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an item from the collection by key.
|
||||
*
|
||||
* @param string|array $keys
|
||||
* @return $this
|
||||
*/
|
||||
public function forget($keys)
|
||||
{
|
||||
foreach ((array) $keys as $key) {
|
||||
$this->offsetUnset($key);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an item from the collection by key.
|
||||
*
|
||||
* @param mixed $key
|
||||
* @param mixed $default
|
||||
* @return mixed
|
||||
*/
|
||||
public function get($key, $default = null)
|
||||
{
|
||||
if (array_key_exists($key, $this->items)) {
|
||||
return $this->items[$key];
|
||||
}
|
||||
|
||||
return value($default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Group an associative array by a field or using a callback.
|
||||
*
|
||||
* @param array|callable|string $groupBy
|
||||
* @param bool $preserveKeys
|
||||
* @return static
|
||||
*/
|
||||
public function groupBy($groupBy, $preserveKeys = false)
|
||||
{
|
||||
if (! $this->useAsCallable($groupBy) && is_array($groupBy)) {
|
||||
$nextGroups = $groupBy;
|
||||
|
||||
$groupBy = array_shift($nextGroups);
|
||||
}
|
||||
|
||||
$groupBy = $this->valueRetriever($groupBy);
|
||||
|
||||
$results = [];
|
||||
|
||||
foreach ($this->items as $key => $value) {
|
||||
$groupKeys = $groupBy($value, $key);
|
||||
|
||||
if (! is_array($groupKeys)) {
|
||||
$groupKeys = [$groupKeys];
|
||||
}
|
||||
|
||||
foreach ($groupKeys as $groupKey) {
|
||||
$groupKey = is_bool($groupKey) ? (int) $groupKey : $groupKey;
|
||||
|
||||
if (! array_key_exists($groupKey, $results)) {
|
||||
$results[$groupKey] = new static;
|
||||
}
|
||||
|
||||
$results[$groupKey]->offsetSet($preserveKeys ? $key : null, $value);
|
||||
}
|
||||
}
|
||||
|
||||
$result = new static($results);
|
||||
|
||||
if (! empty($nextGroups)) {
|
||||
return $result->map->groupBy($nextGroups, $preserveKeys);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Key an associative array by a field or using a callback.
|
||||
*
|
||||
* @param callable|string $keyBy
|
||||
* @return static
|
||||
*/
|
||||
public function keyBy($keyBy)
|
||||
{
|
||||
$keyBy = $this->valueRetriever($keyBy);
|
||||
|
||||
$results = [];
|
||||
|
||||
foreach ($this->items as $key => $item) {
|
||||
$resolvedKey = $keyBy($item, $key);
|
||||
|
||||
if (is_object($resolvedKey)) {
|
||||
$resolvedKey = (string) $resolvedKey;
|
||||
}
|
||||
|
||||
$results[$resolvedKey] = $item;
|
||||
}
|
||||
|
||||
return new static($results);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if an item exists in the collection by key.
|
||||
*
|
||||
* @param mixed $key
|
||||
* @return bool
|
||||
*/
|
||||
public function has($key)
|
||||
{
|
||||
$keys = is_array($key) ? $key : func_get_args();
|
||||
|
||||
foreach ($keys as $value) {
|
||||
if (! array_key_exists($value, $this->items)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Concatenate values of a given key as a string.
|
||||
*
|
||||
* @param string $value
|
||||
* @param string|null $glue
|
||||
* @return string
|
||||
*/
|
||||
public function implode($value, $glue = null)
|
||||
{
|
||||
$first = $this->first();
|
||||
|
||||
if (is_array($first) || (is_object($first) && ! $first instanceof Stringable)) {
|
||||
return implode($glue ?? '', $this->pluck($value)->all());
|
||||
}
|
||||
|
||||
return implode($value ?? '', $this->items);
|
||||
}
|
||||
|
||||
/**
|
||||
* Intersect the collection with the given items.
|
||||
*
|
||||
* @param mixed $items
|
||||
* @return static
|
||||
*/
|
||||
public function intersect($items)
|
||||
{
|
||||
return new static(array_intersect($this->items, $this->getArrayableItems($items)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Intersect the collection with the given items by key.
|
||||
*
|
||||
* @param mixed $items
|
||||
* @return static
|
||||
*/
|
||||
public function intersectByKeys($items)
|
||||
{
|
||||
return new static(array_intersect_key(
|
||||
$this->items, $this->getArrayableItems($items)
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the collection is empty or not.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isEmpty()
|
||||
{
|
||||
return empty($this->items);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the collection contains a single item.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function containsOneItem()
|
||||
{
|
||||
return $this->count() === 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Join all items from the collection using a string. The final items can use a separate glue string.
|
||||
*
|
||||
* @param string $glue
|
||||
* @param string $finalGlue
|
||||
* @return string
|
||||
*/
|
||||
public function join($glue, $finalGlue = '')
|
||||
{
|
||||
if ($finalGlue === '') {
|
||||
return $this->implode($glue);
|
||||
}
|
||||
|
||||
$count = $this->count();
|
||||
|
||||
if ($count === 0) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if ($count === 1) {
|
||||
return $this->last();
|
||||
}
|
||||
|
||||
$collection = new static($this->items);
|
||||
|
||||
$finalItem = $collection->pop();
|
||||
|
||||
return $collection->implode($glue).$finalGlue.$finalItem;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the keys of the collection items.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function keys()
|
||||
{
|
||||
return new static(array_keys($this->items));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the last item from the collection.
|
||||
*
|
||||
* @param callable|null $callback
|
||||
* @param mixed $default
|
||||
* @return mixed
|
||||
*/
|
||||
public function last(callable $callback = null, $default = null)
|
||||
{
|
||||
return Arr::last($this->items, $callback, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the values of a given key.
|
||||
*
|
||||
* @param string|array|int|null $value
|
||||
* @param string|null $key
|
||||
* @return static
|
||||
*/
|
||||
public function pluck($value, $key = null)
|
||||
{
|
||||
return new static(Arr::pluck($this->items, $value, $key));
|
||||
}
|
||||
|
||||
/**
|
||||
* Run a map over each of the items.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @return static
|
||||
*/
|
||||
public function map(callable $callback)
|
||||
{
|
||||
$keys = array_keys($this->items);
|
||||
|
||||
$items = array_map($callback, $this->items, $keys);
|
||||
|
||||
return new static(array_combine($keys, $items));
|
||||
}
|
||||
|
||||
/**
|
||||
* Run a dictionary map over the items.
|
||||
*
|
||||
* The callback should return an associative array with a single key/value pair.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @return static
|
||||
*/
|
||||
public function mapToDictionary(callable $callback)
|
||||
{
|
||||
$dictionary = [];
|
||||
|
||||
foreach ($this->items as $key => $item) {
|
||||
$pair = $callback($item, $key);
|
||||
|
||||
$key = key($pair);
|
||||
|
||||
$value = reset($pair);
|
||||
|
||||
if (! isset($dictionary[$key])) {
|
||||
$dictionary[$key] = [];
|
||||
}
|
||||
|
||||
$dictionary[$key][] = $value;
|
||||
}
|
||||
|
||||
return new static($dictionary);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run an associative map over each of the items.
|
||||
*
|
||||
* The callback should return an associative array with a single key/value pair.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @return static
|
||||
*/
|
||||
public function mapWithKeys(callable $callback)
|
||||
{
|
||||
$result = [];
|
||||
|
||||
foreach ($this->items as $key => $value) {
|
||||
$assoc = $callback($value, $key);
|
||||
|
||||
foreach ($assoc as $mapKey => $mapValue) {
|
||||
$result[$mapKey] = $mapValue;
|
||||
}
|
||||
}
|
||||
|
||||
return new static($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge the collection with the given items.
|
||||
*
|
||||
* @param mixed $items
|
||||
* @return static
|
||||
*/
|
||||
public function merge($items)
|
||||
{
|
||||
return new static(array_merge($this->items, $this->getArrayableItems($items)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively merge the collection with the given items.
|
||||
*
|
||||
* @param mixed $items
|
||||
* @return static
|
||||
*/
|
||||
public function mergeRecursive($items)
|
||||
{
|
||||
return new static(array_merge_recursive($this->items, $this->getArrayableItems($items)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a collection by using this collection for keys and another for its values.
|
||||
*
|
||||
* @param mixed $values
|
||||
* @return static
|
||||
*/
|
||||
public function combine($values)
|
||||
{
|
||||
return new static(array_combine($this->all(), $this->getArrayableItems($values)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Union the collection with the given items.
|
||||
*
|
||||
* @param mixed $items
|
||||
* @return static
|
||||
*/
|
||||
public function union($items)
|
||||
{
|
||||
return new static($this->items + $this->getArrayableItems($items));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new collection consisting of every n-th element.
|
||||
*
|
||||
* @param int $step
|
||||
* @param int $offset
|
||||
* @return static
|
||||
*/
|
||||
public function nth($step, $offset = 0)
|
||||
{
|
||||
$new = [];
|
||||
|
||||
$position = 0;
|
||||
|
||||
foreach ($this->items as $item) {
|
||||
if ($position % $step === $offset) {
|
||||
$new[] = $item;
|
||||
}
|
||||
|
||||
$position++;
|
||||
}
|
||||
|
||||
return new static($new);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the items with the specified keys.
|
||||
*
|
||||
* @param mixed $keys
|
||||
* @return static
|
||||
*/
|
||||
public function only($keys)
|
||||
{
|
||||
if (is_null($keys)) {
|
||||
return new static($this->items);
|
||||
}
|
||||
|
||||
if ($keys instanceof Enumerable) {
|
||||
$keys = $keys->all();
|
||||
}
|
||||
|
||||
$keys = is_array($keys) ? $keys : func_get_args();
|
||||
|
||||
return new static(Arr::only($this->items, $keys));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get and remove the last N items from the collection.
|
||||
*
|
||||
* @param int $count
|
||||
* @return mixed
|
||||
*/
|
||||
public function pop($count = 1)
|
||||
{
|
||||
if ($count === 1) {
|
||||
return array_pop($this->items);
|
||||
}
|
||||
|
||||
if ($this->isEmpty()) {
|
||||
return new static;
|
||||
}
|
||||
|
||||
$results = [];
|
||||
|
||||
$collectionCount = $this->count();
|
||||
|
||||
foreach (range(1, min($count, $collectionCount)) as $item) {
|
||||
array_push($results, array_pop($this->items));
|
||||
}
|
||||
|
||||
return new static($results);
|
||||
}
|
||||
|
||||
/**
|
||||
* Push an item onto the beginning of the collection.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @param mixed $key
|
||||
* @return $this
|
||||
*/
|
||||
public function prepend($value, $key = null)
|
||||
{
|
||||
$this->items = Arr::prepend($this->items, ...func_get_args());
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Push one or more items onto the end of the collection.
|
||||
*
|
||||
* @param mixed $values
|
||||
* @return $this
|
||||
*/
|
||||
public function push(...$values)
|
||||
{
|
||||
foreach ($values as $value) {
|
||||
$this->items[] = $value;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Push all of the given items onto the collection.
|
||||
*
|
||||
* @param iterable $source
|
||||
* @return static
|
||||
*/
|
||||
public function concat($source)
|
||||
{
|
||||
$result = new static($this);
|
||||
|
||||
foreach ($source as $item) {
|
||||
$result->push($item);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get and remove an item from the collection.
|
||||
*
|
||||
* @param mixed $key
|
||||
* @param mixed $default
|
||||
* @return mixed
|
||||
*/
|
||||
public function pull($key, $default = null)
|
||||
{
|
||||
return Arr::pull($this->items, $key, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Put an item in the collection by key.
|
||||
*
|
||||
* @param mixed $key
|
||||
* @param mixed $value
|
||||
* @return $this
|
||||
*/
|
||||
public function put($key, $value)
|
||||
{
|
||||
$this->offsetSet($key, $value);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get one or a specified number of items randomly from the collection.
|
||||
*
|
||||
* @param int|null $number
|
||||
* @return static|mixed
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function random($number = null)
|
||||
{
|
||||
if (is_null($number)) {
|
||||
return Arr::random($this->items);
|
||||
}
|
||||
|
||||
return new static(Arr::random($this->items, $number));
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the collection items with the given items.
|
||||
*
|
||||
* @param mixed $items
|
||||
* @return static
|
||||
*/
|
||||
public function replace($items)
|
||||
{
|
||||
return new static(array_replace($this->items, $this->getArrayableItems($items)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively replace the collection items with the given items.
|
||||
*
|
||||
* @param mixed $items
|
||||
* @return static
|
||||
*/
|
||||
public function replaceRecursive($items)
|
||||
{
|
||||
return new static(array_replace_recursive($this->items, $this->getArrayableItems($items)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse items order.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function reverse()
|
||||
{
|
||||
return new static(array_reverse($this->items, true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Search the collection for a given value and return the corresponding key if successful.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @param bool $strict
|
||||
* @return mixed
|
||||
*/
|
||||
public function search($value, $strict = false)
|
||||
{
|
||||
if (! $this->useAsCallable($value)) {
|
||||
return array_search($value, $this->items, $strict);
|
||||
}
|
||||
|
||||
foreach ($this->items as $key => $item) {
|
||||
if ($value($item, $key)) {
|
||||
return $key;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get and remove the first N items from the collection.
|
||||
*
|
||||
* @param int $count
|
||||
* @return mixed
|
||||
*/
|
||||
public function shift($count = 1)
|
||||
{
|
||||
if ($count === 1) {
|
||||
return array_shift($this->items);
|
||||
}
|
||||
|
||||
if ($this->isEmpty()) {
|
||||
return new static;
|
||||
}
|
||||
|
||||
$results = [];
|
||||
|
||||
$collectionCount = $this->count();
|
||||
|
||||
foreach (range(1, min($count, $collectionCount)) as $item) {
|
||||
array_push($results, array_shift($this->items));
|
||||
}
|
||||
|
||||
return new static($results);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shuffle the items in the collection.
|
||||
*
|
||||
* @param int|null $seed
|
||||
* @return static
|
||||
*/
|
||||
public function shuffle($seed = null)
|
||||
{
|
||||
return new static(Arr::shuffle($this->items, $seed));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create chunks representing a "sliding window" view of the items in the collection.
|
||||
*
|
||||
* @param int $size
|
||||
* @param int $step
|
||||
* @return static
|
||||
*/
|
||||
public function sliding($size = 2, $step = 1)
|
||||
{
|
||||
$chunks = floor(($this->count() - $size) / $step) + 1;
|
||||
|
||||
return static::times($chunks, function ($number) use ($size, $step) {
|
||||
return $this->slice(($number - 1) * $step, $size);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Skip the first {$count} items.
|
||||
*
|
||||
* @param int $count
|
||||
* @return static
|
||||
*/
|
||||
public function skip($count)
|
||||
{
|
||||
return $this->slice($count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Skip items in the collection until the given condition is met.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return static
|
||||
*/
|
||||
public function skipUntil($value)
|
||||
{
|
||||
return new static($this->lazy()->skipUntil($value)->all());
|
||||
}
|
||||
|
||||
/**
|
||||
* Skip items in the collection while the given condition is met.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return static
|
||||
*/
|
||||
public function skipWhile($value)
|
||||
{
|
||||
return new static($this->lazy()->skipWhile($value)->all());
|
||||
}
|
||||
|
||||
/**
|
||||
* Slice the underlying collection array.
|
||||
*
|
||||
* @param int $offset
|
||||
* @param int|null $length
|
||||
* @return static
|
||||
*/
|
||||
public function slice($offset, $length = null)
|
||||
{
|
||||
return new static(array_slice($this->items, $offset, $length, true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Split a collection into a certain number of groups.
|
||||
*
|
||||
* @param int $numberOfGroups
|
||||
* @return static
|
||||
*/
|
||||
public function split($numberOfGroups)
|
||||
{
|
||||
if ($this->isEmpty()) {
|
||||
return new static;
|
||||
}
|
||||
|
||||
$groups = new static;
|
||||
|
||||
$groupSize = floor($this->count() / $numberOfGroups);
|
||||
|
||||
$remain = $this->count() % $numberOfGroups;
|
||||
|
||||
$start = 0;
|
||||
|
||||
for ($i = 0; $i < $numberOfGroups; $i++) {
|
||||
$size = $groupSize;
|
||||
|
||||
if ($i < $remain) {
|
||||
$size++;
|
||||
}
|
||||
|
||||
if ($size) {
|
||||
$groups->push(new static(array_slice($this->items, $start, $size)));
|
||||
|
||||
$start += $size;
|
||||
}
|
||||
}
|
||||
|
||||
return $groups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Split a collection into a certain number of groups, and fill the first groups completely.
|
||||
*
|
||||
* @param int $numberOfGroups
|
||||
* @return static
|
||||
*/
|
||||
public function splitIn($numberOfGroups)
|
||||
{
|
||||
return $this->chunk(ceil($this->count() / $numberOfGroups));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the first item in the collection, but only if exactly one item exists. Otherwise, throw an exception.
|
||||
*
|
||||
* @param mixed $key
|
||||
* @param mixed $operator
|
||||
* @param mixed $value
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \Illuminate\Support\ItemNotFoundException
|
||||
* @throws \Illuminate\Support\MultipleItemsFoundException
|
||||
*/
|
||||
public function sole($key = null, $operator = null, $value = null)
|
||||
{
|
||||
$filter = func_num_args() > 1
|
||||
? $this->operatorForWhere(...func_get_args())
|
||||
: $key;
|
||||
|
||||
$items = $this->when($filter)->filter($filter);
|
||||
|
||||
if ($items->isEmpty()) {
|
||||
throw new ItemNotFoundException;
|
||||
}
|
||||
|
||||
if ($items->count() > 1) {
|
||||
throw new MultipleItemsFoundException;
|
||||
}
|
||||
|
||||
return $items->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the first item in the collection but throw an exception if no matching items exist.
|
||||
*
|
||||
* @param mixed $key
|
||||
* @param mixed $operator
|
||||
* @param mixed $value
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \Illuminate\Support\ItemNotFoundException
|
||||
*/
|
||||
public function firstOrFail($key = null, $operator = null, $value = null)
|
||||
{
|
||||
$filter = func_num_args() > 1
|
||||
? $this->operatorForWhere(...func_get_args())
|
||||
: $key;
|
||||
|
||||
$placeholder = new stdClass();
|
||||
|
||||
$item = $this->first($filter, $placeholder);
|
||||
|
||||
if ($item === $placeholder) {
|
||||
throw new ItemNotFoundException;
|
||||
}
|
||||
|
||||
return $item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Chunk the collection into chunks of the given size.
|
||||
*
|
||||
* @param int $size
|
||||
* @return static
|
||||
*/
|
||||
public function chunk($size)
|
||||
{
|
||||
if ($size <= 0) {
|
||||
return new static;
|
||||
}
|
||||
|
||||
$chunks = [];
|
||||
|
||||
foreach (array_chunk($this->items, $size, true) as $chunk) {
|
||||
$chunks[] = new static($chunk);
|
||||
}
|
||||
|
||||
return new static($chunks);
|
||||
}
|
||||
|
||||
/**
|
||||
* Chunk the collection into chunks with a callback.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @return static
|
||||
*/
|
||||
public function chunkWhile(callable $callback)
|
||||
{
|
||||
return new static(
|
||||
$this->lazy()->chunkWhile($callback)->mapInto(static::class)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort through each item with a callback.
|
||||
*
|
||||
* @param callable|int|null $callback
|
||||
* @return static
|
||||
*/
|
||||
public function sort($callback = null)
|
||||
{
|
||||
$items = $this->items;
|
||||
|
||||
$callback && is_callable($callback)
|
||||
? uasort($items, $callback)
|
||||
: asort($items, $callback ?? SORT_REGULAR);
|
||||
|
||||
return new static($items);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort items in descending order.
|
||||
*
|
||||
* @param int $options
|
||||
* @return static
|
||||
*/
|
||||
public function sortDesc($options = SORT_REGULAR)
|
||||
{
|
||||
$items = $this->items;
|
||||
|
||||
arsort($items, $options);
|
||||
|
||||
return new static($items);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort the collection using the given callback.
|
||||
*
|
||||
* @param callable|array|string $callback
|
||||
* @param int $options
|
||||
* @param bool $descending
|
||||
* @return static
|
||||
*/
|
||||
public function sortBy($callback, $options = SORT_REGULAR, $descending = false)
|
||||
{
|
||||
if (is_array($callback) && ! is_callable($callback)) {
|
||||
return $this->sortByMany($callback);
|
||||
}
|
||||
|
||||
$results = [];
|
||||
|
||||
$callback = $this->valueRetriever($callback);
|
||||
|
||||
// First we will loop through the items and get the comparator from a callback
|
||||
// function which we were given. Then, we will sort the returned values and
|
||||
// and grab the corresponding values for the sorted keys from this array.
|
||||
foreach ($this->items as $key => $value) {
|
||||
$results[$key] = $callback($value, $key);
|
||||
}
|
||||
|
||||
$descending ? arsort($results, $options)
|
||||
: asort($results, $options);
|
||||
|
||||
// Once we have sorted all of the keys in the array, we will loop through them
|
||||
// and grab the corresponding model so we can set the underlying items list
|
||||
// to the sorted version. Then we'll just return the collection instance.
|
||||
foreach (array_keys($results) as $key) {
|
||||
$results[$key] = $this->items[$key];
|
||||
}
|
||||
|
||||
return new static($results);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort the collection using multiple comparisons.
|
||||
*
|
||||
* @param array $comparisons
|
||||
* @return static
|
||||
*/
|
||||
protected function sortByMany(array $comparisons = [])
|
||||
{
|
||||
$items = $this->items;
|
||||
|
||||
usort($items, function ($a, $b) use ($comparisons) {
|
||||
foreach ($comparisons as $comparison) {
|
||||
$comparison = Arr::wrap($comparison);
|
||||
|
||||
$prop = $comparison[0];
|
||||
|
||||
$ascending = Arr::get($comparison, 1, true) === true ||
|
||||
Arr::get($comparison, 1, true) === 'asc';
|
||||
|
||||
$result = 0;
|
||||
|
||||
if (is_callable($prop)) {
|
||||
$result = $prop($a, $b);
|
||||
} else {
|
||||
$values = [data_get($a, $prop), data_get($b, $prop)];
|
||||
|
||||
if (! $ascending) {
|
||||
$values = array_reverse($values);
|
||||
}
|
||||
|
||||
$result = $values[0] <=> $values[1];
|
||||
}
|
||||
|
||||
if ($result === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
});
|
||||
|
||||
return new static($items);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort the collection in descending order using the given callback.
|
||||
*
|
||||
* @param callable|string $callback
|
||||
* @param int $options
|
||||
* @return static
|
||||
*/
|
||||
public function sortByDesc($callback, $options = SORT_REGULAR)
|
||||
{
|
||||
return $this->sortBy($callback, $options, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort the collection keys.
|
||||
*
|
||||
* @param int $options
|
||||
* @param bool $descending
|
||||
* @return static
|
||||
*/
|
||||
public function sortKeys($options = SORT_REGULAR, $descending = false)
|
||||
{
|
||||
$items = $this->items;
|
||||
|
||||
$descending ? krsort($items, $options) : ksort($items, $options);
|
||||
|
||||
return new static($items);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort the collection keys in descending order.
|
||||
*
|
||||
* @param int $options
|
||||
* @return static
|
||||
*/
|
||||
public function sortKeysDesc($options = SORT_REGULAR)
|
||||
{
|
||||
return $this->sortKeys($options, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Splice a portion of the underlying collection array.
|
||||
*
|
||||
* @param int $offset
|
||||
* @param int|null $length
|
||||
* @param mixed $replacement
|
||||
* @return static
|
||||
*/
|
||||
public function splice($offset, $length = null, $replacement = [])
|
||||
{
|
||||
if (func_num_args() === 1) {
|
||||
return new static(array_splice($this->items, $offset));
|
||||
}
|
||||
|
||||
return new static(array_splice($this->items, $offset, $length, $replacement));
|
||||
}
|
||||
|
||||
/**
|
||||
* Take the first or last {$limit} items.
|
||||
*
|
||||
* @param int $limit
|
||||
* @return static
|
||||
*/
|
||||
public function take($limit)
|
||||
{
|
||||
if ($limit < 0) {
|
||||
return $this->slice($limit, abs($limit));
|
||||
}
|
||||
|
||||
return $this->slice(0, $limit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Take items in the collection until the given condition is met.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return static
|
||||
*/
|
||||
public function takeUntil($value)
|
||||
{
|
||||
return new static($this->lazy()->takeUntil($value)->all());
|
||||
}
|
||||
|
||||
/**
|
||||
* Take items in the collection while the given condition is met.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return static
|
||||
*/
|
||||
public function takeWhile($value)
|
||||
{
|
||||
return new static($this->lazy()->takeWhile($value)->all());
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform each item in the collection using a callback.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @return $this
|
||||
*/
|
||||
public function transform(callable $callback)
|
||||
{
|
||||
$this->items = $this->map($callback)->all();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the keys on the underlying array.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function values()
|
||||
{
|
||||
return new static(array_values($this->items));
|
||||
}
|
||||
|
||||
/**
|
||||
* Zip the collection together with one or more arrays.
|
||||
*
|
||||
* e.g. new Collection([1, 2, 3])->zip([4, 5, 6]);
|
||||
* => [[1, 4], [2, 5], [3, 6]]
|
||||
*
|
||||
* @param mixed ...$items
|
||||
* @return static
|
||||
*/
|
||||
public function zip($items)
|
||||
{
|
||||
$arrayableItems = array_map(function ($items) {
|
||||
return $this->getArrayableItems($items);
|
||||
}, func_get_args());
|
||||
|
||||
$params = array_merge([function () {
|
||||
return new static(func_get_args());
|
||||
}, $this->items], $arrayableItems);
|
||||
|
||||
return new static(array_map(...$params));
|
||||
}
|
||||
|
||||
/**
|
||||
* Pad collection to the specified length with a value.
|
||||
*
|
||||
* @param int $size
|
||||
* @param mixed $value
|
||||
* @return static
|
||||
*/
|
||||
public function pad($size, $value)
|
||||
{
|
||||
return new static(array_pad($this->items, $size, $value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an iterator for the items.
|
||||
*
|
||||
* @return \ArrayIterator
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function getIterator()
|
||||
{
|
||||
return new ArrayIterator($this->items);
|
||||
}
|
||||
|
||||
/**
|
||||
* Count the number of items in the collection.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function count()
|
||||
{
|
||||
return count($this->items);
|
||||
}
|
||||
|
||||
/**
|
||||
* Count the number of items in the collection by a field or using a callback.
|
||||
*
|
||||
* @param callable|string $countBy
|
||||
* @return static
|
||||
*/
|
||||
public function countBy($countBy = null)
|
||||
{
|
||||
return new static($this->lazy()->countBy($countBy)->all());
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an item to the collection.
|
||||
*
|
||||
* @param mixed $item
|
||||
* @return $this
|
||||
*/
|
||||
public function add($item)
|
||||
{
|
||||
$this->items[] = $item;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a base Support collection instance from this collection.
|
||||
*
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
public function toBase()
|
||||
{
|
||||
return new self($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if an item exists at an offset.
|
||||
*
|
||||
* @param mixed $key
|
||||
* @return bool
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetExists($key)
|
||||
{
|
||||
return isset($this->items[$key]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an item at a given offset.
|
||||
*
|
||||
* @param mixed $key
|
||||
* @return mixed
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetGet($key)
|
||||
{
|
||||
return $this->items[$key];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the item at a given offset.
|
||||
*
|
||||
* @param mixed $key
|
||||
* @param mixed $value
|
||||
* @return void
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetSet($key, $value)
|
||||
{
|
||||
if (is_null($key)) {
|
||||
$this->items[] = $value;
|
||||
} else {
|
||||
$this->items[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unset the item at a given offset.
|
||||
*
|
||||
* @param string $key
|
||||
* @return void
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetUnset($key)
|
||||
{
|
||||
unset($this->items[$key]);
|
||||
}
|
||||
}
|
||||
+1027
@@ -0,0 +1,1027 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Support;
|
||||
|
||||
use Countable;
|
||||
use Illuminate\Contracts\Support\Arrayable;
|
||||
use Illuminate\Contracts\Support\Jsonable;
|
||||
use IteratorAggregate;
|
||||
use JsonSerializable;
|
||||
|
||||
interface Enumerable extends Arrayable, Countable, IteratorAggregate, Jsonable, JsonSerializable
|
||||
{
|
||||
/**
|
||||
* Create a new collection instance if the value isn't one already.
|
||||
*
|
||||
* @param mixed $items
|
||||
* @return static
|
||||
*/
|
||||
public static function make($items = []);
|
||||
|
||||
/**
|
||||
* Create a new instance by invoking the callback a given amount of times.
|
||||
*
|
||||
* @param int $number
|
||||
* @param callable|null $callback
|
||||
* @return static
|
||||
*/
|
||||
public static function times($number, callable $callback = null);
|
||||
|
||||
/**
|
||||
* Create a collection with the given range.
|
||||
*
|
||||
* @param int $from
|
||||
* @param int $to
|
||||
* @return static
|
||||
*/
|
||||
public static function range($from, $to);
|
||||
|
||||
/**
|
||||
* Wrap the given value in a collection if applicable.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return static
|
||||
*/
|
||||
public static function wrap($value);
|
||||
|
||||
/**
|
||||
* Get the underlying items from the given collection if applicable.
|
||||
*
|
||||
* @param array|static $value
|
||||
* @return array
|
||||
*/
|
||||
public static function unwrap($value);
|
||||
|
||||
/**
|
||||
* Create a new instance with no items.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public static function empty();
|
||||
|
||||
/**
|
||||
* Get all items in the enumerable.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function all();
|
||||
|
||||
/**
|
||||
* Alias for the "avg" method.
|
||||
*
|
||||
* @param callable|string|null $callback
|
||||
* @return mixed
|
||||
*/
|
||||
public function average($callback = null);
|
||||
|
||||
/**
|
||||
* Get the median of a given key.
|
||||
*
|
||||
* @param string|array|null $key
|
||||
* @return mixed
|
||||
*/
|
||||
public function median($key = null);
|
||||
|
||||
/**
|
||||
* Get the mode of a given key.
|
||||
*
|
||||
* @param string|array|null $key
|
||||
* @return array|null
|
||||
*/
|
||||
public function mode($key = null);
|
||||
|
||||
/**
|
||||
* Collapse the items into a single enumerable.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function collapse();
|
||||
|
||||
/**
|
||||
* Alias for the "contains" method.
|
||||
*
|
||||
* @param mixed $key
|
||||
* @param mixed $operator
|
||||
* @param mixed $value
|
||||
* @return bool
|
||||
*/
|
||||
public function some($key, $operator = null, $value = null);
|
||||
|
||||
/**
|
||||
* Determine if an item exists, using strict comparison.
|
||||
*
|
||||
* @param mixed $key
|
||||
* @param mixed $value
|
||||
* @return bool
|
||||
*/
|
||||
public function containsStrict($key, $value = null);
|
||||
|
||||
/**
|
||||
* Get the average value of a given key.
|
||||
*
|
||||
* @param callable|string|null $callback
|
||||
* @return mixed
|
||||
*/
|
||||
public function avg($callback = null);
|
||||
|
||||
/**
|
||||
* Determine if an item exists in the enumerable.
|
||||
*
|
||||
* @param mixed $key
|
||||
* @param mixed $operator
|
||||
* @param mixed $value
|
||||
* @return bool
|
||||
*/
|
||||
public function contains($key, $operator = null, $value = null);
|
||||
|
||||
/**
|
||||
* Cross join with the given lists, returning all possible permutations.
|
||||
*
|
||||
* @param mixed ...$lists
|
||||
* @return static
|
||||
*/
|
||||
public function crossJoin(...$lists);
|
||||
|
||||
/**
|
||||
* Dump the collection and end the script.
|
||||
*
|
||||
* @param mixed ...$args
|
||||
* @return void
|
||||
*/
|
||||
public function dd(...$args);
|
||||
|
||||
/**
|
||||
* Dump the collection.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function dump();
|
||||
|
||||
/**
|
||||
* Get the items that are not present in the given items.
|
||||
*
|
||||
* @param mixed $items
|
||||
* @return static
|
||||
*/
|
||||
public function diff($items);
|
||||
|
||||
/**
|
||||
* Get the items that are not present in the given items, using the callback.
|
||||
*
|
||||
* @param mixed $items
|
||||
* @param callable $callback
|
||||
* @return static
|
||||
*/
|
||||
public function diffUsing($items, callable $callback);
|
||||
|
||||
/**
|
||||
* Get the items whose keys and values are not present in the given items.
|
||||
*
|
||||
* @param mixed $items
|
||||
* @return static
|
||||
*/
|
||||
public function diffAssoc($items);
|
||||
|
||||
/**
|
||||
* Get the items whose keys and values are not present in the given items, using the callback.
|
||||
*
|
||||
* @param mixed $items
|
||||
* @param callable $callback
|
||||
* @return static
|
||||
*/
|
||||
public function diffAssocUsing($items, callable $callback);
|
||||
|
||||
/**
|
||||
* Get the items whose keys are not present in the given items.
|
||||
*
|
||||
* @param mixed $items
|
||||
* @return static
|
||||
*/
|
||||
public function diffKeys($items);
|
||||
|
||||
/**
|
||||
* Get the items whose keys are not present in the given items, using the callback.
|
||||
*
|
||||
* @param mixed $items
|
||||
* @param callable $callback
|
||||
* @return static
|
||||
*/
|
||||
public function diffKeysUsing($items, callable $callback);
|
||||
|
||||
/**
|
||||
* Retrieve duplicate items.
|
||||
*
|
||||
* @param callable|string|null $callback
|
||||
* @param bool $strict
|
||||
* @return static
|
||||
*/
|
||||
public function duplicates($callback = null, $strict = false);
|
||||
|
||||
/**
|
||||
* Retrieve duplicate items using strict comparison.
|
||||
*
|
||||
* @param callable|string|null $callback
|
||||
* @return static
|
||||
*/
|
||||
public function duplicatesStrict($callback = null);
|
||||
|
||||
/**
|
||||
* Execute a callback over each item.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @return $this
|
||||
*/
|
||||
public function each(callable $callback);
|
||||
|
||||
/**
|
||||
* Execute a callback over each nested chunk of items.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @return static
|
||||
*/
|
||||
public function eachSpread(callable $callback);
|
||||
|
||||
/**
|
||||
* Determine if all items pass the given truth test.
|
||||
*
|
||||
* @param string|callable $key
|
||||
* @param mixed $operator
|
||||
* @param mixed $value
|
||||
* @return bool
|
||||
*/
|
||||
public function every($key, $operator = null, $value = null);
|
||||
|
||||
/**
|
||||
* Get all items except for those with the specified keys.
|
||||
*
|
||||
* @param mixed $keys
|
||||
* @return static
|
||||
*/
|
||||
public function except($keys);
|
||||
|
||||
/**
|
||||
* Run a filter over each of the items.
|
||||
*
|
||||
* @param callable|null $callback
|
||||
* @return static
|
||||
*/
|
||||
public function filter(callable $callback = null);
|
||||
|
||||
/**
|
||||
* Apply the callback if the value is truthy.
|
||||
*
|
||||
* @param bool $value
|
||||
* @param callable $callback
|
||||
* @param callable|null $default
|
||||
* @return static|mixed
|
||||
*/
|
||||
public function when($value, callable $callback, callable $default = null);
|
||||
|
||||
/**
|
||||
* Apply the callback if the collection is empty.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @param callable|null $default
|
||||
* @return static|mixed
|
||||
*/
|
||||
public function whenEmpty(callable $callback, callable $default = null);
|
||||
|
||||
/**
|
||||
* Apply the callback if the collection is not empty.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @param callable|null $default
|
||||
* @return static|mixed
|
||||
*/
|
||||
public function whenNotEmpty(callable $callback, callable $default = null);
|
||||
|
||||
/**
|
||||
* Apply the callback if the value is falsy.
|
||||
*
|
||||
* @param bool $value
|
||||
* @param callable $callback
|
||||
* @param callable|null $default
|
||||
* @return static|mixed
|
||||
*/
|
||||
public function unless($value, callable $callback, callable $default = null);
|
||||
|
||||
/**
|
||||
* Apply the callback unless the collection is empty.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @param callable|null $default
|
||||
* @return static|mixed
|
||||
*/
|
||||
public function unlessEmpty(callable $callback, callable $default = null);
|
||||
|
||||
/**
|
||||
* Apply the callback unless the collection is not empty.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @param callable|null $default
|
||||
* @return static|mixed
|
||||
*/
|
||||
public function unlessNotEmpty(callable $callback, callable $default = null);
|
||||
|
||||
/**
|
||||
* Filter items by the given key value pair.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $operator
|
||||
* @param mixed $value
|
||||
* @return static
|
||||
*/
|
||||
public function where($key, $operator = null, $value = null);
|
||||
|
||||
/**
|
||||
* Filter items where the value for the given key is null.
|
||||
*
|
||||
* @param string|null $key
|
||||
* @return static
|
||||
*/
|
||||
public function whereNull($key = null);
|
||||
|
||||
/**
|
||||
* Filter items where the value for the given key is not null.
|
||||
*
|
||||
* @param string|null $key
|
||||
* @return static
|
||||
*/
|
||||
public function whereNotNull($key = null);
|
||||
|
||||
/**
|
||||
* Filter items by the given key value pair using strict comparison.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @return static
|
||||
*/
|
||||
public function whereStrict($key, $value);
|
||||
|
||||
/**
|
||||
* Filter items by the given key value pair.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $values
|
||||
* @param bool $strict
|
||||
* @return static
|
||||
*/
|
||||
public function whereIn($key, $values, $strict = false);
|
||||
|
||||
/**
|
||||
* Filter items by the given key value pair using strict comparison.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $values
|
||||
* @return static
|
||||
*/
|
||||
public function whereInStrict($key, $values);
|
||||
|
||||
/**
|
||||
* Filter items such that the value of the given key is between the given values.
|
||||
*
|
||||
* @param string $key
|
||||
* @param array $values
|
||||
* @return static
|
||||
*/
|
||||
public function whereBetween($key, $values);
|
||||
|
||||
/**
|
||||
* Filter items such that the value of the given key is not between the given values.
|
||||
*
|
||||
* @param string $key
|
||||
* @param array $values
|
||||
* @return static
|
||||
*/
|
||||
public function whereNotBetween($key, $values);
|
||||
|
||||
/**
|
||||
* Filter items by the given key value pair.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $values
|
||||
* @param bool $strict
|
||||
* @return static
|
||||
*/
|
||||
public function whereNotIn($key, $values, $strict = false);
|
||||
|
||||
/**
|
||||
* Filter items by the given key value pair using strict comparison.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $values
|
||||
* @return static
|
||||
*/
|
||||
public function whereNotInStrict($key, $values);
|
||||
|
||||
/**
|
||||
* Filter the items, removing any items that don't match the given type(s).
|
||||
*
|
||||
* @param string|string[] $type
|
||||
* @return static
|
||||
*/
|
||||
public function whereInstanceOf($type);
|
||||
|
||||
/**
|
||||
* Get the first item from the enumerable passing the given truth test.
|
||||
*
|
||||
* @param callable|null $callback
|
||||
* @param mixed $default
|
||||
* @return mixed
|
||||
*/
|
||||
public function first(callable $callback = null, $default = null);
|
||||
|
||||
/**
|
||||
* Get the first item by the given key value pair.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $operator
|
||||
* @param mixed $value
|
||||
* @return mixed
|
||||
*/
|
||||
public function firstWhere($key, $operator = null, $value = null);
|
||||
|
||||
/**
|
||||
* Get a flattened array of the items in the collection.
|
||||
*
|
||||
* @param int $depth
|
||||
* @return static
|
||||
*/
|
||||
public function flatten($depth = INF);
|
||||
|
||||
/**
|
||||
* Flip the values with their keys.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function flip();
|
||||
|
||||
/**
|
||||
* Get an item from the collection by key.
|
||||
*
|
||||
* @param mixed $key
|
||||
* @param mixed $default
|
||||
* @return mixed
|
||||
*/
|
||||
public function get($key, $default = null);
|
||||
|
||||
/**
|
||||
* Group an associative array by a field or using a callback.
|
||||
*
|
||||
* @param array|callable|string $groupBy
|
||||
* @param bool $preserveKeys
|
||||
* @return static
|
||||
*/
|
||||
public function groupBy($groupBy, $preserveKeys = false);
|
||||
|
||||
/**
|
||||
* Key an associative array by a field or using a callback.
|
||||
*
|
||||
* @param callable|string $keyBy
|
||||
* @return static
|
||||
*/
|
||||
public function keyBy($keyBy);
|
||||
|
||||
/**
|
||||
* Determine if an item exists in the collection by key.
|
||||
*
|
||||
* @param mixed $key
|
||||
* @return bool
|
||||
*/
|
||||
public function has($key);
|
||||
|
||||
/**
|
||||
* Concatenate values of a given key as a string.
|
||||
*
|
||||
* @param string $value
|
||||
* @param string|null $glue
|
||||
* @return string
|
||||
*/
|
||||
public function implode($value, $glue = null);
|
||||
|
||||
/**
|
||||
* Intersect the collection with the given items.
|
||||
*
|
||||
* @param mixed $items
|
||||
* @return static
|
||||
*/
|
||||
public function intersect($items);
|
||||
|
||||
/**
|
||||
* Intersect the collection with the given items by key.
|
||||
*
|
||||
* @param mixed $items
|
||||
* @return static
|
||||
*/
|
||||
public function intersectByKeys($items);
|
||||
|
||||
/**
|
||||
* Determine if the collection is empty or not.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isEmpty();
|
||||
|
||||
/**
|
||||
* Determine if the collection is not empty.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isNotEmpty();
|
||||
|
||||
/**
|
||||
* Join all items from the collection using a string. The final items can use a separate glue string.
|
||||
*
|
||||
* @param string $glue
|
||||
* @param string $finalGlue
|
||||
* @return string
|
||||
*/
|
||||
public function join($glue, $finalGlue = '');
|
||||
|
||||
/**
|
||||
* Get the keys of the collection items.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function keys();
|
||||
|
||||
/**
|
||||
* Get the last item from the collection.
|
||||
*
|
||||
* @param callable|null $callback
|
||||
* @param mixed $default
|
||||
* @return mixed
|
||||
*/
|
||||
public function last(callable $callback = null, $default = null);
|
||||
|
||||
/**
|
||||
* Run a map over each of the items.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @return static
|
||||
*/
|
||||
public function map(callable $callback);
|
||||
|
||||
/**
|
||||
* Run a map over each nested chunk of items.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @return static
|
||||
*/
|
||||
public function mapSpread(callable $callback);
|
||||
|
||||
/**
|
||||
* Run a dictionary map over the items.
|
||||
*
|
||||
* The callback should return an associative array with a single key/value pair.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @return static
|
||||
*/
|
||||
public function mapToDictionary(callable $callback);
|
||||
|
||||
/**
|
||||
* Run a grouping map over the items.
|
||||
*
|
||||
* The callback should return an associative array with a single key/value pair.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @return static
|
||||
*/
|
||||
public function mapToGroups(callable $callback);
|
||||
|
||||
/**
|
||||
* Run an associative map over each of the items.
|
||||
*
|
||||
* The callback should return an associative array with a single key/value pair.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @return static
|
||||
*/
|
||||
public function mapWithKeys(callable $callback);
|
||||
|
||||
/**
|
||||
* Map a collection and flatten the result by a single level.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @return static
|
||||
*/
|
||||
public function flatMap(callable $callback);
|
||||
|
||||
/**
|
||||
* Map the values into a new class.
|
||||
*
|
||||
* @param string $class
|
||||
* @return static
|
||||
*/
|
||||
public function mapInto($class);
|
||||
|
||||
/**
|
||||
* Merge the collection with the given items.
|
||||
*
|
||||
* @param mixed $items
|
||||
* @return static
|
||||
*/
|
||||
public function merge($items);
|
||||
|
||||
/**
|
||||
* Recursively merge the collection with the given items.
|
||||
*
|
||||
* @param mixed $items
|
||||
* @return static
|
||||
*/
|
||||
public function mergeRecursive($items);
|
||||
|
||||
/**
|
||||
* Create a collection by using this collection for keys and another for its values.
|
||||
*
|
||||
* @param mixed $values
|
||||
* @return static
|
||||
*/
|
||||
public function combine($values);
|
||||
|
||||
/**
|
||||
* Union the collection with the given items.
|
||||
*
|
||||
* @param mixed $items
|
||||
* @return static
|
||||
*/
|
||||
public function union($items);
|
||||
|
||||
/**
|
||||
* Get the min value of a given key.
|
||||
*
|
||||
* @param callable|string|null $callback
|
||||
* @return mixed
|
||||
*/
|
||||
public function min($callback = null);
|
||||
|
||||
/**
|
||||
* Get the max value of a given key.
|
||||
*
|
||||
* @param callable|string|null $callback
|
||||
* @return mixed
|
||||
*/
|
||||
public function max($callback = null);
|
||||
|
||||
/**
|
||||
* Create a new collection consisting of every n-th element.
|
||||
*
|
||||
* @param int $step
|
||||
* @param int $offset
|
||||
* @return static
|
||||
*/
|
||||
public function nth($step, $offset = 0);
|
||||
|
||||
/**
|
||||
* Get the items with the specified keys.
|
||||
*
|
||||
* @param mixed $keys
|
||||
* @return static
|
||||
*/
|
||||
public function only($keys);
|
||||
|
||||
/**
|
||||
* "Paginate" the collection by slicing it into a smaller collection.
|
||||
*
|
||||
* @param int $page
|
||||
* @param int $perPage
|
||||
* @return static
|
||||
*/
|
||||
public function forPage($page, $perPage);
|
||||
|
||||
/**
|
||||
* Partition the collection into two arrays using the given callback or key.
|
||||
*
|
||||
* @param callable|string $key
|
||||
* @param mixed $operator
|
||||
* @param mixed $value
|
||||
* @return static
|
||||
*/
|
||||
public function partition($key, $operator = null, $value = null);
|
||||
|
||||
/**
|
||||
* Push all of the given items onto the collection.
|
||||
*
|
||||
* @param iterable $source
|
||||
* @return static
|
||||
*/
|
||||
public function concat($source);
|
||||
|
||||
/**
|
||||
* Get one or a specified number of items randomly from the collection.
|
||||
*
|
||||
* @param int|null $number
|
||||
* @return static|mixed
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function random($number = null);
|
||||
|
||||
/**
|
||||
* Reduce the collection to a single value.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @param mixed $initial
|
||||
* @return mixed
|
||||
*/
|
||||
public function reduce(callable $callback, $initial = null);
|
||||
|
||||
/**
|
||||
* Replace the collection items with the given items.
|
||||
*
|
||||
* @param mixed $items
|
||||
* @return static
|
||||
*/
|
||||
public function replace($items);
|
||||
|
||||
/**
|
||||
* Recursively replace the collection items with the given items.
|
||||
*
|
||||
* @param mixed $items
|
||||
* @return static
|
||||
*/
|
||||
public function replaceRecursive($items);
|
||||
|
||||
/**
|
||||
* Reverse items order.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function reverse();
|
||||
|
||||
/**
|
||||
* Search the collection for a given value and return the corresponding key if successful.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @param bool $strict
|
||||
* @return mixed
|
||||
*/
|
||||
public function search($value, $strict = false);
|
||||
|
||||
/**
|
||||
* Shuffle the items in the collection.
|
||||
*
|
||||
* @param int|null $seed
|
||||
* @return static
|
||||
*/
|
||||
public function shuffle($seed = null);
|
||||
|
||||
/**
|
||||
* Skip the first {$count} items.
|
||||
*
|
||||
* @param int $count
|
||||
* @return static
|
||||
*/
|
||||
public function skip($count);
|
||||
|
||||
/**
|
||||
* Skip items in the collection until the given condition is met.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return static
|
||||
*/
|
||||
public function skipUntil($value);
|
||||
|
||||
/**
|
||||
* Skip items in the collection while the given condition is met.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return static
|
||||
*/
|
||||
public function skipWhile($value);
|
||||
|
||||
/**
|
||||
* Get a slice of items from the enumerable.
|
||||
*
|
||||
* @param int $offset
|
||||
* @param int|null $length
|
||||
* @return static
|
||||
*/
|
||||
public function slice($offset, $length = null);
|
||||
|
||||
/**
|
||||
* Split a collection into a certain number of groups.
|
||||
*
|
||||
* @param int $numberOfGroups
|
||||
* @return static
|
||||
*/
|
||||
public function split($numberOfGroups);
|
||||
|
||||
/**
|
||||
* Chunk the collection into chunks of the given size.
|
||||
*
|
||||
* @param int $size
|
||||
* @return static
|
||||
*/
|
||||
public function chunk($size);
|
||||
|
||||
/**
|
||||
* Chunk the collection into chunks with a callback.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @return static
|
||||
*/
|
||||
public function chunkWhile(callable $callback);
|
||||
|
||||
/**
|
||||
* Sort through each item with a callback.
|
||||
*
|
||||
* @param callable|null|int $callback
|
||||
* @return static
|
||||
*/
|
||||
public function sort($callback = null);
|
||||
|
||||
/**
|
||||
* Sort items in descending order.
|
||||
*
|
||||
* @param int $options
|
||||
* @return static
|
||||
*/
|
||||
public function sortDesc($options = SORT_REGULAR);
|
||||
|
||||
/**
|
||||
* Sort the collection using the given callback.
|
||||
*
|
||||
* @param callable|string $callback
|
||||
* @param int $options
|
||||
* @param bool $descending
|
||||
* @return static
|
||||
*/
|
||||
public function sortBy($callback, $options = SORT_REGULAR, $descending = false);
|
||||
|
||||
/**
|
||||
* Sort the collection in descending order using the given callback.
|
||||
*
|
||||
* @param callable|string $callback
|
||||
* @param int $options
|
||||
* @return static
|
||||
*/
|
||||
public function sortByDesc($callback, $options = SORT_REGULAR);
|
||||
|
||||
/**
|
||||
* Sort the collection keys.
|
||||
*
|
||||
* @param int $options
|
||||
* @param bool $descending
|
||||
* @return static
|
||||
*/
|
||||
public function sortKeys($options = SORT_REGULAR, $descending = false);
|
||||
|
||||
/**
|
||||
* Sort the collection keys in descending order.
|
||||
*
|
||||
* @param int $options
|
||||
* @return static
|
||||
*/
|
||||
public function sortKeysDesc($options = SORT_REGULAR);
|
||||
|
||||
/**
|
||||
* Get the sum of the given values.
|
||||
*
|
||||
* @param callable|string|null $callback
|
||||
* @return mixed
|
||||
*/
|
||||
public function sum($callback = null);
|
||||
|
||||
/**
|
||||
* Take the first or last {$limit} items.
|
||||
*
|
||||
* @param int $limit
|
||||
* @return static
|
||||
*/
|
||||
public function take($limit);
|
||||
|
||||
/**
|
||||
* Take items in the collection until the given condition is met.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return static
|
||||
*/
|
||||
public function takeUntil($value);
|
||||
|
||||
/**
|
||||
* Take items in the collection while the given condition is met.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return static
|
||||
*/
|
||||
public function takeWhile($value);
|
||||
|
||||
/**
|
||||
* Pass the collection to the given callback and then return it.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @return $this
|
||||
*/
|
||||
public function tap(callable $callback);
|
||||
|
||||
/**
|
||||
* Pass the enumerable to the given callback and return the result.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @return mixed
|
||||
*/
|
||||
public function pipe(callable $callback);
|
||||
|
||||
/**
|
||||
* Get the values of a given key.
|
||||
*
|
||||
* @param string|array $value
|
||||
* @param string|null $key
|
||||
* @return static
|
||||
*/
|
||||
public function pluck($value, $key = null);
|
||||
|
||||
/**
|
||||
* Create a collection of all elements that do not pass a given truth test.
|
||||
*
|
||||
* @param callable|mixed $callback
|
||||
* @return static
|
||||
*/
|
||||
public function reject($callback = true);
|
||||
|
||||
/**
|
||||
* Return only unique items from the collection array.
|
||||
*
|
||||
* @param string|callable|null $key
|
||||
* @param bool $strict
|
||||
* @return static
|
||||
*/
|
||||
public function unique($key = null, $strict = false);
|
||||
|
||||
/**
|
||||
* Return only unique items from the collection array using strict comparison.
|
||||
*
|
||||
* @param string|callable|null $key
|
||||
* @return static
|
||||
*/
|
||||
public function uniqueStrict($key = null);
|
||||
|
||||
/**
|
||||
* Reset the keys on the underlying array.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function values();
|
||||
|
||||
/**
|
||||
* Pad collection to the specified length with a value.
|
||||
*
|
||||
* @param int $size
|
||||
* @param mixed $value
|
||||
* @return static
|
||||
*/
|
||||
public function pad($size, $value);
|
||||
|
||||
/**
|
||||
* Count the number of items in the collection using a given truth test.
|
||||
*
|
||||
* @param callable|null $callback
|
||||
* @return static
|
||||
*/
|
||||
public function countBy($callback = null);
|
||||
|
||||
/**
|
||||
* Zip the collection together with one or more arrays.
|
||||
*
|
||||
* e.g. new Collection([1, 2, 3])->zip([4, 5, 6]);
|
||||
* => [[1, 4], [2, 5], [3, 6]]
|
||||
*
|
||||
* @param mixed ...$items
|
||||
* @return static
|
||||
*/
|
||||
public function zip($items);
|
||||
|
||||
/**
|
||||
* Collect the values into a collection.
|
||||
*
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
public function collect();
|
||||
|
||||
/**
|
||||
* Convert the collection to its string representation.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function __toString();
|
||||
|
||||
/**
|
||||
* Add a method to the list of proxied methods.
|
||||
*
|
||||
* @param string $method
|
||||
* @return void
|
||||
*/
|
||||
public static function proxy($method);
|
||||
|
||||
/**
|
||||
* Dynamically access collection proxies.
|
||||
*
|
||||
* @param string $key
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function __get($key);
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Support;
|
||||
|
||||
/**
|
||||
* @mixin \Illuminate\Support\Enumerable
|
||||
*/
|
||||
class HigherOrderCollectionProxy
|
||||
{
|
||||
/**
|
||||
* The collection being operated on.
|
||||
*
|
||||
* @var \Illuminate\Support\Enumerable
|
||||
*/
|
||||
protected $collection;
|
||||
|
||||
/**
|
||||
* The method being proxied.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $method;
|
||||
|
||||
/**
|
||||
* Create a new proxy instance.
|
||||
*
|
||||
* @param \Illuminate\Support\Enumerable $collection
|
||||
* @param string $method
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Enumerable $collection, $method)
|
||||
{
|
||||
$this->method = $method;
|
||||
$this->collection = $collection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Proxy accessing an attribute onto the collection items.
|
||||
*
|
||||
* @param string $key
|
||||
* @return mixed
|
||||
*/
|
||||
public function __get($key)
|
||||
{
|
||||
return $this->collection->{$this->method}(function ($value) use ($key) {
|
||||
return is_array($value) ? $value[$key] : $value->{$key};
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Proxy a method call onto the collection items.
|
||||
*
|
||||
* @param string $method
|
||||
* @param array $parameters
|
||||
* @return mixed
|
||||
*/
|
||||
public function __call($method, $parameters)
|
||||
{
|
||||
return $this->collection->{$this->method}(function ($value) use ($method, $parameters) {
|
||||
return $value->{$method}(...$parameters);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Support;
|
||||
|
||||
/**
|
||||
* @mixin \Illuminate\Support\Enumerable
|
||||
*/
|
||||
class HigherOrderWhenProxy
|
||||
{
|
||||
/**
|
||||
* The collection being operated on.
|
||||
*
|
||||
* @var \Illuminate\Support\Enumerable
|
||||
*/
|
||||
protected $collection;
|
||||
|
||||
/**
|
||||
* The condition for proxying.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $condition;
|
||||
|
||||
/**
|
||||
* Create a new proxy instance.
|
||||
*
|
||||
* @param \Illuminate\Support\Enumerable $collection
|
||||
* @param bool $condition
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Enumerable $collection, $condition)
|
||||
{
|
||||
$this->condition = $condition;
|
||||
$this->collection = $collection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Proxy accessing an attribute onto the collection.
|
||||
*
|
||||
* @param string $key
|
||||
* @return mixed
|
||||
*/
|
||||
public function __get($key)
|
||||
{
|
||||
return $this->condition
|
||||
? $this->collection->{$key}
|
||||
: $this->collection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Proxy a method call onto the collection.
|
||||
*
|
||||
* @param string $method
|
||||
* @param array $parameters
|
||||
* @return mixed
|
||||
*/
|
||||
public function __call($method, $parameters)
|
||||
{
|
||||
return $this->condition
|
||||
? $this->collection->{$method}(...$parameters)
|
||||
: $this->collection;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Support;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
class ItemNotFoundException extends RuntimeException
|
||||
{
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) Taylor Otwell
|
||||
|
||||
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.
|
||||
+1507
@@ -0,0 +1,1507 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Support;
|
||||
|
||||
use ArrayIterator;
|
||||
use Closure;
|
||||
use DateTimeInterface;
|
||||
use Illuminate\Support\Traits\EnumeratesValues;
|
||||
use Illuminate\Support\Traits\Macroable;
|
||||
use IteratorAggregate;
|
||||
use stdClass;
|
||||
|
||||
class LazyCollection implements Enumerable
|
||||
{
|
||||
use EnumeratesValues, Macroable;
|
||||
|
||||
/**
|
||||
* The source from which to generate items.
|
||||
*
|
||||
* @var callable|static
|
||||
*/
|
||||
public $source;
|
||||
|
||||
/**
|
||||
* Create a new lazy collection instance.
|
||||
*
|
||||
* @param mixed $source
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($source = null)
|
||||
{
|
||||
if ($source instanceof Closure || $source instanceof self) {
|
||||
$this->source = $source;
|
||||
} elseif (is_null($source)) {
|
||||
$this->source = static::empty();
|
||||
} else {
|
||||
$this->source = $this->getArrayableItems($source);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a collection with the given range.
|
||||
*
|
||||
* @param int $from
|
||||
* @param int $to
|
||||
* @return static
|
||||
*/
|
||||
public static function range($from, $to)
|
||||
{
|
||||
return new static(function () use ($from, $to) {
|
||||
if ($from <= $to) {
|
||||
for (; $from <= $to; $from++) {
|
||||
yield $from;
|
||||
}
|
||||
} else {
|
||||
for (; $from >= $to; $from--) {
|
||||
yield $from;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all items in the enumerable.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function all()
|
||||
{
|
||||
if (is_array($this->source)) {
|
||||
return $this->source;
|
||||
}
|
||||
|
||||
return iterator_to_array($this->getIterator());
|
||||
}
|
||||
|
||||
/**
|
||||
* Eager load all items into a new lazy collection backed by an array.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function eager()
|
||||
{
|
||||
return new static($this->all());
|
||||
}
|
||||
|
||||
/**
|
||||
* Cache values as they're enumerated.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function remember()
|
||||
{
|
||||
$iterator = $this->getIterator();
|
||||
|
||||
$iteratorIndex = 0;
|
||||
|
||||
$cache = [];
|
||||
|
||||
return new static(function () use ($iterator, &$iteratorIndex, &$cache) {
|
||||
for ($index = 0; true; $index++) {
|
||||
if (array_key_exists($index, $cache)) {
|
||||
yield $cache[$index][0] => $cache[$index][1];
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($iteratorIndex < $index) {
|
||||
$iterator->next();
|
||||
|
||||
$iteratorIndex++;
|
||||
}
|
||||
|
||||
if (! $iterator->valid()) {
|
||||
break;
|
||||
}
|
||||
|
||||
$cache[$index] = [$iterator->key(), $iterator->current()];
|
||||
|
||||
yield $cache[$index][0] => $cache[$index][1];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the average value of a given key.
|
||||
*
|
||||
* @param callable|string|null $callback
|
||||
* @return mixed
|
||||
*/
|
||||
public function avg($callback = null)
|
||||
{
|
||||
return $this->collect()->avg($callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the median of a given key.
|
||||
*
|
||||
* @param string|array|null $key
|
||||
* @return mixed
|
||||
*/
|
||||
public function median($key = null)
|
||||
{
|
||||
return $this->collect()->median($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mode of a given key.
|
||||
*
|
||||
* @param string|array|null $key
|
||||
* @return array|null
|
||||
*/
|
||||
public function mode($key = null)
|
||||
{
|
||||
return $this->collect()->mode($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Collapse the collection of items into a single array.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function collapse()
|
||||
{
|
||||
return new static(function () {
|
||||
foreach ($this as $values) {
|
||||
if (is_array($values) || $values instanceof Enumerable) {
|
||||
foreach ($values as $value) {
|
||||
yield $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if an item exists in the enumerable.
|
||||
*
|
||||
* @param mixed $key
|
||||
* @param mixed $operator
|
||||
* @param mixed $value
|
||||
* @return bool
|
||||
*/
|
||||
public function contains($key, $operator = null, $value = null)
|
||||
{
|
||||
if (func_num_args() === 1 && $this->useAsCallable($key)) {
|
||||
$placeholder = new stdClass;
|
||||
|
||||
return $this->first($key, $placeholder) !== $placeholder;
|
||||
}
|
||||
|
||||
if (func_num_args() === 1) {
|
||||
$needle = $key;
|
||||
|
||||
foreach ($this as $value) {
|
||||
if ($value == $needle) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->contains($this->operatorForWhere(...func_get_args()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Cross join the given iterables, returning all possible permutations.
|
||||
*
|
||||
* @param array ...$arrays
|
||||
* @return static
|
||||
*/
|
||||
public function crossJoin(...$arrays)
|
||||
{
|
||||
return $this->passthru('crossJoin', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* Count the number of items in the collection by a field or using a callback.
|
||||
*
|
||||
* @param callable|string $countBy
|
||||
* @return static
|
||||
*/
|
||||
public function countBy($countBy = null)
|
||||
{
|
||||
$countBy = is_null($countBy)
|
||||
? $this->identity()
|
||||
: $this->valueRetriever($countBy);
|
||||
|
||||
return new static(function () use ($countBy) {
|
||||
$counts = [];
|
||||
|
||||
foreach ($this as $key => $value) {
|
||||
$group = $countBy($value, $key);
|
||||
|
||||
if (empty($counts[$group])) {
|
||||
$counts[$group] = 0;
|
||||
}
|
||||
|
||||
$counts[$group]++;
|
||||
}
|
||||
|
||||
yield from $counts;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the items that are not present in the given items.
|
||||
*
|
||||
* @param mixed $items
|
||||
* @return static
|
||||
*/
|
||||
public function diff($items)
|
||||
{
|
||||
return $this->passthru('diff', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the items that are not present in the given items, using the callback.
|
||||
*
|
||||
* @param mixed $items
|
||||
* @param callable $callback
|
||||
* @return static
|
||||
*/
|
||||
public function diffUsing($items, callable $callback)
|
||||
{
|
||||
return $this->passthru('diffUsing', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the items whose keys and values are not present in the given items.
|
||||
*
|
||||
* @param mixed $items
|
||||
* @return static
|
||||
*/
|
||||
public function diffAssoc($items)
|
||||
{
|
||||
return $this->passthru('diffAssoc', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the items whose keys and values are not present in the given items, using the callback.
|
||||
*
|
||||
* @param mixed $items
|
||||
* @param callable $callback
|
||||
* @return static
|
||||
*/
|
||||
public function diffAssocUsing($items, callable $callback)
|
||||
{
|
||||
return $this->passthru('diffAssocUsing', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the items whose keys are not present in the given items.
|
||||
*
|
||||
* @param mixed $items
|
||||
* @return static
|
||||
*/
|
||||
public function diffKeys($items)
|
||||
{
|
||||
return $this->passthru('diffKeys', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the items whose keys are not present in the given items, using the callback.
|
||||
*
|
||||
* @param mixed $items
|
||||
* @param callable $callback
|
||||
* @return static
|
||||
*/
|
||||
public function diffKeysUsing($items, callable $callback)
|
||||
{
|
||||
return $this->passthru('diffKeysUsing', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve duplicate items.
|
||||
*
|
||||
* @param callable|string|null $callback
|
||||
* @param bool $strict
|
||||
* @return static
|
||||
*/
|
||||
public function duplicates($callback = null, $strict = false)
|
||||
{
|
||||
return $this->passthru('duplicates', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve duplicate items using strict comparison.
|
||||
*
|
||||
* @param callable|string|null $callback
|
||||
* @return static
|
||||
*/
|
||||
public function duplicatesStrict($callback = null)
|
||||
{
|
||||
return $this->passthru('duplicatesStrict', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all items except for those with the specified keys.
|
||||
*
|
||||
* @param mixed $keys
|
||||
* @return static
|
||||
*/
|
||||
public function except($keys)
|
||||
{
|
||||
return $this->passthru('except', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* Run a filter over each of the items.
|
||||
*
|
||||
* @param callable|null $callback
|
||||
* @return static
|
||||
*/
|
||||
public function filter(callable $callback = null)
|
||||
{
|
||||
if (is_null($callback)) {
|
||||
$callback = function ($value) {
|
||||
return (bool) $value;
|
||||
};
|
||||
}
|
||||
|
||||
return new static(function () use ($callback) {
|
||||
foreach ($this as $key => $value) {
|
||||
if ($callback($value, $key)) {
|
||||
yield $key => $value;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the first item from the enumerable passing the given truth test.
|
||||
*
|
||||
* @param callable|null $callback
|
||||
* @param mixed $default
|
||||
* @return mixed
|
||||
*/
|
||||
public function first(callable $callback = null, $default = null)
|
||||
{
|
||||
$iterator = $this->getIterator();
|
||||
|
||||
if (is_null($callback)) {
|
||||
if (! $iterator->valid()) {
|
||||
return value($default);
|
||||
}
|
||||
|
||||
return $iterator->current();
|
||||
}
|
||||
|
||||
foreach ($iterator as $key => $value) {
|
||||
if ($callback($value, $key)) {
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
||||
return value($default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a flattened list of the items in the collection.
|
||||
*
|
||||
* @param int $depth
|
||||
* @return static
|
||||
*/
|
||||
public function flatten($depth = INF)
|
||||
{
|
||||
$instance = new static(function () use ($depth) {
|
||||
foreach ($this as $item) {
|
||||
if (! is_array($item) && ! $item instanceof Enumerable) {
|
||||
yield $item;
|
||||
} elseif ($depth === 1) {
|
||||
yield from $item;
|
||||
} else {
|
||||
yield from (new static($item))->flatten($depth - 1);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return $instance->values();
|
||||
}
|
||||
|
||||
/**
|
||||
* Flip the items in the collection.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function flip()
|
||||
{
|
||||
return new static(function () {
|
||||
foreach ($this as $key => $value) {
|
||||
yield $value => $key;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an item by key.
|
||||
*
|
||||
* @param mixed $key
|
||||
* @param mixed $default
|
||||
* @return mixed
|
||||
*/
|
||||
public function get($key, $default = null)
|
||||
{
|
||||
if (is_null($key)) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($this as $outerKey => $outerValue) {
|
||||
if ($outerKey == $key) {
|
||||
return $outerValue;
|
||||
}
|
||||
}
|
||||
|
||||
return value($default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Group an associative array by a field or using a callback.
|
||||
*
|
||||
* @param array|callable|string $groupBy
|
||||
* @param bool $preserveKeys
|
||||
* @return static
|
||||
*/
|
||||
public function groupBy($groupBy, $preserveKeys = false)
|
||||
{
|
||||
return $this->passthru('groupBy', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* Key an associative array by a field or using a callback.
|
||||
*
|
||||
* @param callable|string $keyBy
|
||||
* @return static
|
||||
*/
|
||||
public function keyBy($keyBy)
|
||||
{
|
||||
return new static(function () use ($keyBy) {
|
||||
$keyBy = $this->valueRetriever($keyBy);
|
||||
|
||||
foreach ($this as $key => $item) {
|
||||
$resolvedKey = $keyBy($item, $key);
|
||||
|
||||
if (is_object($resolvedKey)) {
|
||||
$resolvedKey = (string) $resolvedKey;
|
||||
}
|
||||
|
||||
yield $resolvedKey => $item;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if an item exists in the collection by key.
|
||||
*
|
||||
* @param mixed $key
|
||||
* @return bool
|
||||
*/
|
||||
public function has($key)
|
||||
{
|
||||
$keys = array_flip(is_array($key) ? $key : func_get_args());
|
||||
$count = count($keys);
|
||||
|
||||
foreach ($this as $key => $value) {
|
||||
if (array_key_exists($key, $keys) && --$count == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Concatenate values of a given key as a string.
|
||||
*
|
||||
* @param string $value
|
||||
* @param string|null $glue
|
||||
* @return string
|
||||
*/
|
||||
public function implode($value, $glue = null)
|
||||
{
|
||||
return $this->collect()->implode(...func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* Intersect the collection with the given items.
|
||||
*
|
||||
* @param mixed $items
|
||||
* @return static
|
||||
*/
|
||||
public function intersect($items)
|
||||
{
|
||||
return $this->passthru('intersect', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* Intersect the collection with the given items by key.
|
||||
*
|
||||
* @param mixed $items
|
||||
* @return static
|
||||
*/
|
||||
public function intersectByKeys($items)
|
||||
{
|
||||
return $this->passthru('intersectByKeys', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the items are empty or not.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isEmpty()
|
||||
{
|
||||
return ! $this->getIterator()->valid();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the collection contains a single item.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function containsOneItem()
|
||||
{
|
||||
return $this->take(2)->count() === 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Join all items from the collection using a string. The final items can use a separate glue string.
|
||||
*
|
||||
* @param string $glue
|
||||
* @param string $finalGlue
|
||||
* @return string
|
||||
*/
|
||||
public function join($glue, $finalGlue = '')
|
||||
{
|
||||
return $this->collect()->join(...func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the keys of the collection items.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function keys()
|
||||
{
|
||||
return new static(function () {
|
||||
foreach ($this as $key => $value) {
|
||||
yield $key;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the last item from the collection.
|
||||
*
|
||||
* @param callable|null $callback
|
||||
* @param mixed $default
|
||||
* @return mixed
|
||||
*/
|
||||
public function last(callable $callback = null, $default = null)
|
||||
{
|
||||
$needle = $placeholder = new stdClass;
|
||||
|
||||
foreach ($this as $key => $value) {
|
||||
if (is_null($callback) || $callback($value, $key)) {
|
||||
$needle = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $needle === $placeholder ? value($default) : $needle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the values of a given key.
|
||||
*
|
||||
* @param string|array $value
|
||||
* @param string|null $key
|
||||
* @return static
|
||||
*/
|
||||
public function pluck($value, $key = null)
|
||||
{
|
||||
return new static(function () use ($value, $key) {
|
||||
[$value, $key] = $this->explodePluckParameters($value, $key);
|
||||
|
||||
foreach ($this as $item) {
|
||||
$itemValue = data_get($item, $value);
|
||||
|
||||
if (is_null($key)) {
|
||||
yield $itemValue;
|
||||
} else {
|
||||
$itemKey = data_get($item, $key);
|
||||
|
||||
if (is_object($itemKey) && method_exists($itemKey, '__toString')) {
|
||||
$itemKey = (string) $itemKey;
|
||||
}
|
||||
|
||||
yield $itemKey => $itemValue;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Run a map over each of the items.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @return static
|
||||
*/
|
||||
public function map(callable $callback)
|
||||
{
|
||||
return new static(function () use ($callback) {
|
||||
foreach ($this as $key => $value) {
|
||||
yield $key => $callback($value, $key);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Run a dictionary map over the items.
|
||||
*
|
||||
* The callback should return an associative array with a single key/value pair.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @return static
|
||||
*/
|
||||
public function mapToDictionary(callable $callback)
|
||||
{
|
||||
return $this->passthru('mapToDictionary', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* Run an associative map over each of the items.
|
||||
*
|
||||
* The callback should return an associative array with a single key/value pair.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @return static
|
||||
*/
|
||||
public function mapWithKeys(callable $callback)
|
||||
{
|
||||
return new static(function () use ($callback) {
|
||||
foreach ($this as $key => $value) {
|
||||
yield from $callback($value, $key);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge the collection with the given items.
|
||||
*
|
||||
* @param mixed $items
|
||||
* @return static
|
||||
*/
|
||||
public function merge($items)
|
||||
{
|
||||
return $this->passthru('merge', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively merge the collection with the given items.
|
||||
*
|
||||
* @param mixed $items
|
||||
* @return static
|
||||
*/
|
||||
public function mergeRecursive($items)
|
||||
{
|
||||
return $this->passthru('mergeRecursive', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a collection by using this collection for keys and another for its values.
|
||||
*
|
||||
* @param mixed $values
|
||||
* @return static
|
||||
*/
|
||||
public function combine($values)
|
||||
{
|
||||
return new static(function () use ($values) {
|
||||
$values = $this->makeIterator($values);
|
||||
|
||||
$errorMessage = 'Both parameters should have an equal number of elements';
|
||||
|
||||
foreach ($this as $key) {
|
||||
if (! $values->valid()) {
|
||||
trigger_error($errorMessage, E_USER_WARNING);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
yield $key => $values->current();
|
||||
|
||||
$values->next();
|
||||
}
|
||||
|
||||
if ($values->valid()) {
|
||||
trigger_error($errorMessage, E_USER_WARNING);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Union the collection with the given items.
|
||||
*
|
||||
* @param mixed $items
|
||||
* @return static
|
||||
*/
|
||||
public function union($items)
|
||||
{
|
||||
return $this->passthru('union', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new collection consisting of every n-th element.
|
||||
*
|
||||
* @param int $step
|
||||
* @param int $offset
|
||||
* @return static
|
||||
*/
|
||||
public function nth($step, $offset = 0)
|
||||
{
|
||||
return new static(function () use ($step, $offset) {
|
||||
$position = 0;
|
||||
|
||||
foreach ($this as $item) {
|
||||
if ($position % $step === $offset) {
|
||||
yield $item;
|
||||
}
|
||||
|
||||
$position++;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the items with the specified keys.
|
||||
*
|
||||
* @param mixed $keys
|
||||
* @return static
|
||||
*/
|
||||
public function only($keys)
|
||||
{
|
||||
if ($keys instanceof Enumerable) {
|
||||
$keys = $keys->all();
|
||||
} elseif (! is_null($keys)) {
|
||||
$keys = is_array($keys) ? $keys : func_get_args();
|
||||
}
|
||||
|
||||
return new static(function () use ($keys) {
|
||||
if (is_null($keys)) {
|
||||
yield from $this;
|
||||
} else {
|
||||
$keys = array_flip($keys);
|
||||
|
||||
foreach ($this as $key => $value) {
|
||||
if (array_key_exists($key, $keys)) {
|
||||
yield $key => $value;
|
||||
|
||||
unset($keys[$key]);
|
||||
|
||||
if (empty($keys)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Push all of the given items onto the collection.
|
||||
*
|
||||
* @param iterable $source
|
||||
* @return static
|
||||
*/
|
||||
public function concat($source)
|
||||
{
|
||||
return (new static(function () use ($source) {
|
||||
yield from $this;
|
||||
yield from $source;
|
||||
}))->values();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get one or a specified number of items randomly from the collection.
|
||||
*
|
||||
* @param int|null $number
|
||||
* @return static|mixed
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function random($number = null)
|
||||
{
|
||||
$result = $this->collect()->random(...func_get_args());
|
||||
|
||||
return is_null($number) ? $result : new static($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the collection items with the given items.
|
||||
*
|
||||
* @param mixed $items
|
||||
* @return static
|
||||
*/
|
||||
public function replace($items)
|
||||
{
|
||||
return new static(function () use ($items) {
|
||||
$items = $this->getArrayableItems($items);
|
||||
|
||||
foreach ($this as $key => $value) {
|
||||
if (array_key_exists($key, $items)) {
|
||||
yield $key => $items[$key];
|
||||
|
||||
unset($items[$key]);
|
||||
} else {
|
||||
yield $key => $value;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($items as $key => $value) {
|
||||
yield $key => $value;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively replace the collection items with the given items.
|
||||
*
|
||||
* @param mixed $items
|
||||
* @return static
|
||||
*/
|
||||
public function replaceRecursive($items)
|
||||
{
|
||||
return $this->passthru('replaceRecursive', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse items order.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function reverse()
|
||||
{
|
||||
return $this->passthru('reverse', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* Search the collection for a given value and return the corresponding key if successful.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @param bool $strict
|
||||
* @return mixed
|
||||
*/
|
||||
public function search($value, $strict = false)
|
||||
{
|
||||
$predicate = $this->useAsCallable($value)
|
||||
? $value
|
||||
: function ($item) use ($value, $strict) {
|
||||
return $strict ? $item === $value : $item == $value;
|
||||
};
|
||||
|
||||
foreach ($this as $key => $item) {
|
||||
if ($predicate($item, $key)) {
|
||||
return $key;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shuffle the items in the collection.
|
||||
*
|
||||
* @param int|null $seed
|
||||
* @return static
|
||||
*/
|
||||
public function shuffle($seed = null)
|
||||
{
|
||||
return $this->passthru('shuffle', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create chunks representing a "sliding window" view of the items in the collection.
|
||||
*
|
||||
* @param int $size
|
||||
* @param int $step
|
||||
* @return static
|
||||
*/
|
||||
public function sliding($size = 2, $step = 1)
|
||||
{
|
||||
return new static(function () use ($size, $step) {
|
||||
$iterator = $this->getIterator();
|
||||
|
||||
$chunk = [];
|
||||
|
||||
while ($iterator->valid()) {
|
||||
$chunk[$iterator->key()] = $iterator->current();
|
||||
|
||||
if (count($chunk) == $size) {
|
||||
yield tap(new static($chunk), function () use (&$chunk, $step) {
|
||||
$chunk = array_slice($chunk, $step, null, true);
|
||||
});
|
||||
|
||||
// If the $step between chunks is bigger than each chunk's $size
|
||||
// we will skip the extra items (which should never be in any
|
||||
// chunk) before we continue to the next chunk in the loop.
|
||||
if ($step > $size) {
|
||||
$skip = $step - $size;
|
||||
|
||||
for ($i = 0; $i < $skip && $iterator->valid(); $i++) {
|
||||
$iterator->next();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$iterator->next();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Skip the first {$count} items.
|
||||
*
|
||||
* @param int $count
|
||||
* @return static
|
||||
*/
|
||||
public function skip($count)
|
||||
{
|
||||
return new static(function () use ($count) {
|
||||
$iterator = $this->getIterator();
|
||||
|
||||
while ($iterator->valid() && $count--) {
|
||||
$iterator->next();
|
||||
}
|
||||
|
||||
while ($iterator->valid()) {
|
||||
yield $iterator->key() => $iterator->current();
|
||||
|
||||
$iterator->next();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Skip items in the collection until the given condition is met.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return static
|
||||
*/
|
||||
public function skipUntil($value)
|
||||
{
|
||||
$callback = $this->useAsCallable($value) ? $value : $this->equality($value);
|
||||
|
||||
return $this->skipWhile($this->negate($callback));
|
||||
}
|
||||
|
||||
/**
|
||||
* Skip items in the collection while the given condition is met.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return static
|
||||
*/
|
||||
public function skipWhile($value)
|
||||
{
|
||||
$callback = $this->useAsCallable($value) ? $value : $this->equality($value);
|
||||
|
||||
return new static(function () use ($callback) {
|
||||
$iterator = $this->getIterator();
|
||||
|
||||
while ($iterator->valid() && $callback($iterator->current(), $iterator->key())) {
|
||||
$iterator->next();
|
||||
}
|
||||
|
||||
while ($iterator->valid()) {
|
||||
yield $iterator->key() => $iterator->current();
|
||||
|
||||
$iterator->next();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a slice of items from the enumerable.
|
||||
*
|
||||
* @param int $offset
|
||||
* @param int|null $length
|
||||
* @return static
|
||||
*/
|
||||
public function slice($offset, $length = null)
|
||||
{
|
||||
if ($offset < 0 || $length < 0) {
|
||||
return $this->passthru('slice', func_get_args());
|
||||
}
|
||||
|
||||
$instance = $this->skip($offset);
|
||||
|
||||
return is_null($length) ? $instance : $instance->take($length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Split a collection into a certain number of groups.
|
||||
*
|
||||
* @param int $numberOfGroups
|
||||
* @return static
|
||||
*/
|
||||
public function split($numberOfGroups)
|
||||
{
|
||||
return $this->passthru('split', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the first item in the collection, but only if exactly one item exists. Otherwise, throw an exception.
|
||||
*
|
||||
* @param mixed $key
|
||||
* @param mixed $operator
|
||||
* @param mixed $value
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \Illuminate\Support\ItemNotFoundException
|
||||
* @throws \Illuminate\Support\MultipleItemsFoundException
|
||||
*/
|
||||
public function sole($key = null, $operator = null, $value = null)
|
||||
{
|
||||
$filter = func_num_args() > 1
|
||||
? $this->operatorForWhere(...func_get_args())
|
||||
: $key;
|
||||
|
||||
return $this
|
||||
->when($filter)
|
||||
->filter($filter)
|
||||
->take(2)
|
||||
->collect()
|
||||
->sole();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the first item in the collection but throw an exception if no matching items exist.
|
||||
*
|
||||
* @param mixed $key
|
||||
* @param mixed $operator
|
||||
* @param mixed $value
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \Illuminate\Support\ItemNotFoundException
|
||||
*/
|
||||
public function firstOrFail($key = null, $operator = null, $value = null)
|
||||
{
|
||||
$filter = func_num_args() > 1
|
||||
? $this->operatorForWhere(...func_get_args())
|
||||
: $key;
|
||||
|
||||
return $this
|
||||
->when($filter)
|
||||
->filter($filter)
|
||||
->take(1)
|
||||
->collect()
|
||||
->firstOrFail();
|
||||
}
|
||||
|
||||
/**
|
||||
* Chunk the collection into chunks of the given size.
|
||||
*
|
||||
* @param int $size
|
||||
* @return static
|
||||
*/
|
||||
public function chunk($size)
|
||||
{
|
||||
if ($size <= 0) {
|
||||
return static::empty();
|
||||
}
|
||||
|
||||
return new static(function () use ($size) {
|
||||
$iterator = $this->getIterator();
|
||||
|
||||
while ($iterator->valid()) {
|
||||
$chunk = [];
|
||||
|
||||
while (true) {
|
||||
$chunk[$iterator->key()] = $iterator->current();
|
||||
|
||||
if (count($chunk) < $size) {
|
||||
$iterator->next();
|
||||
|
||||
if (! $iterator->valid()) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
yield new static($chunk);
|
||||
|
||||
$iterator->next();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Split a collection into a certain number of groups, and fill the first groups completely.
|
||||
*
|
||||
* @param int $numberOfGroups
|
||||
* @return static
|
||||
*/
|
||||
public function splitIn($numberOfGroups)
|
||||
{
|
||||
return $this->chunk(ceil($this->count() / $numberOfGroups));
|
||||
}
|
||||
|
||||
/**
|
||||
* Chunk the collection into chunks with a callback.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @return static
|
||||
*/
|
||||
public function chunkWhile(callable $callback)
|
||||
{
|
||||
return new static(function () use ($callback) {
|
||||
$iterator = $this->getIterator();
|
||||
|
||||
$chunk = new Collection;
|
||||
|
||||
if ($iterator->valid()) {
|
||||
$chunk[$iterator->key()] = $iterator->current();
|
||||
|
||||
$iterator->next();
|
||||
}
|
||||
|
||||
while ($iterator->valid()) {
|
||||
if (! $callback($iterator->current(), $iterator->key(), $chunk)) {
|
||||
yield new static($chunk);
|
||||
|
||||
$chunk = new Collection;
|
||||
}
|
||||
|
||||
$chunk[$iterator->key()] = $iterator->current();
|
||||
|
||||
$iterator->next();
|
||||
}
|
||||
|
||||
if ($chunk->isNotEmpty()) {
|
||||
yield new static($chunk);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort through each item with a callback.
|
||||
*
|
||||
* @param callable|null|int $callback
|
||||
* @return static
|
||||
*/
|
||||
public function sort($callback = null)
|
||||
{
|
||||
return $this->passthru('sort', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort items in descending order.
|
||||
*
|
||||
* @param int $options
|
||||
* @return static
|
||||
*/
|
||||
public function sortDesc($options = SORT_REGULAR)
|
||||
{
|
||||
return $this->passthru('sortDesc', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort the collection using the given callback.
|
||||
*
|
||||
* @param callable|string $callback
|
||||
* @param int $options
|
||||
* @param bool $descending
|
||||
* @return static
|
||||
*/
|
||||
public function sortBy($callback, $options = SORT_REGULAR, $descending = false)
|
||||
{
|
||||
return $this->passthru('sortBy', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort the collection in descending order using the given callback.
|
||||
*
|
||||
* @param callable|string $callback
|
||||
* @param int $options
|
||||
* @return static
|
||||
*/
|
||||
public function sortByDesc($callback, $options = SORT_REGULAR)
|
||||
{
|
||||
return $this->passthru('sortByDesc', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort the collection keys.
|
||||
*
|
||||
* @param int $options
|
||||
* @param bool $descending
|
||||
* @return static
|
||||
*/
|
||||
public function sortKeys($options = SORT_REGULAR, $descending = false)
|
||||
{
|
||||
return $this->passthru('sortKeys', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort the collection keys in descending order.
|
||||
*
|
||||
* @param int $options
|
||||
* @return static
|
||||
*/
|
||||
public function sortKeysDesc($options = SORT_REGULAR)
|
||||
{
|
||||
return $this->passthru('sortKeysDesc', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* Take the first or last {$limit} items.
|
||||
*
|
||||
* @param int $limit
|
||||
* @return static
|
||||
*/
|
||||
public function take($limit)
|
||||
{
|
||||
if ($limit < 0) {
|
||||
return $this->passthru('take', func_get_args());
|
||||
}
|
||||
|
||||
return new static(function () use ($limit) {
|
||||
$iterator = $this->getIterator();
|
||||
|
||||
while ($limit--) {
|
||||
if (! $iterator->valid()) {
|
||||
break;
|
||||
}
|
||||
|
||||
yield $iterator->key() => $iterator->current();
|
||||
|
||||
if ($limit) {
|
||||
$iterator->next();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Take items in the collection until the given condition is met.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return static
|
||||
*/
|
||||
public function takeUntil($value)
|
||||
{
|
||||
$callback = $this->useAsCallable($value) ? $value : $this->equality($value);
|
||||
|
||||
return new static(function () use ($callback) {
|
||||
foreach ($this as $key => $item) {
|
||||
if ($callback($item, $key)) {
|
||||
break;
|
||||
}
|
||||
|
||||
yield $key => $item;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Take items in the collection until a given point in time.
|
||||
*
|
||||
* @param \DateTimeInterface $timeout
|
||||
* @return static
|
||||
*/
|
||||
public function takeUntilTimeout(DateTimeInterface $timeout)
|
||||
{
|
||||
$timeout = $timeout->getTimestamp();
|
||||
|
||||
return $this->takeWhile(function () use ($timeout) {
|
||||
return $this->now() < $timeout;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Take items in the collection while the given condition is met.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return static
|
||||
*/
|
||||
public function takeWhile($value)
|
||||
{
|
||||
$callback = $this->useAsCallable($value) ? $value : $this->equality($value);
|
||||
|
||||
return $this->takeUntil(function ($item, $key) use ($callback) {
|
||||
return ! $callback($item, $key);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Pass each item in the collection to the given callback, lazily.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @return static
|
||||
*/
|
||||
public function tapEach(callable $callback)
|
||||
{
|
||||
return new static(function () use ($callback) {
|
||||
foreach ($this as $key => $value) {
|
||||
$callback($value, $key);
|
||||
|
||||
yield $key => $value;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the keys on the underlying array.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function values()
|
||||
{
|
||||
return new static(function () {
|
||||
foreach ($this as $item) {
|
||||
yield $item;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Zip the collection together with one or more arrays.
|
||||
*
|
||||
* e.g. new LazyCollection([1, 2, 3])->zip([4, 5, 6]);
|
||||
* => [[1, 4], [2, 5], [3, 6]]
|
||||
*
|
||||
* @param mixed ...$items
|
||||
* @return static
|
||||
*/
|
||||
public function zip($items)
|
||||
{
|
||||
$iterables = func_get_args();
|
||||
|
||||
return new static(function () use ($iterables) {
|
||||
$iterators = Collection::make($iterables)->map(function ($iterable) {
|
||||
return $this->makeIterator($iterable);
|
||||
})->prepend($this->getIterator());
|
||||
|
||||
while ($iterators->contains->valid()) {
|
||||
yield new static($iterators->map->current());
|
||||
|
||||
$iterators->each->next();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Pad collection to the specified length with a value.
|
||||
*
|
||||
* @param int $size
|
||||
* @param mixed $value
|
||||
* @return static
|
||||
*/
|
||||
public function pad($size, $value)
|
||||
{
|
||||
if ($size < 0) {
|
||||
return $this->passthru('pad', func_get_args());
|
||||
}
|
||||
|
||||
return new static(function () use ($size, $value) {
|
||||
$yielded = 0;
|
||||
|
||||
foreach ($this as $index => $item) {
|
||||
yield $index => $item;
|
||||
|
||||
$yielded++;
|
||||
}
|
||||
|
||||
while ($yielded++ < $size) {
|
||||
yield $value;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the values iterator.
|
||||
*
|
||||
* @return \Traversable
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function getIterator()
|
||||
{
|
||||
return $this->makeIterator($this->source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Count the number of items in the collection.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function count()
|
||||
{
|
||||
if (is_array($this->source)) {
|
||||
return count($this->source);
|
||||
}
|
||||
|
||||
return iterator_count($this->getIterator());
|
||||
}
|
||||
|
||||
/**
|
||||
* Make an iterator from the given source.
|
||||
*
|
||||
* @param mixed $source
|
||||
* @return \Traversable
|
||||
*/
|
||||
protected function makeIterator($source)
|
||||
{
|
||||
if ($source instanceof IteratorAggregate) {
|
||||
return $source->getIterator();
|
||||
}
|
||||
|
||||
if (is_array($source)) {
|
||||
return new ArrayIterator($source);
|
||||
}
|
||||
|
||||
return $source();
|
||||
}
|
||||
|
||||
/**
|
||||
* Explode the "value" and "key" arguments passed to "pluck".
|
||||
*
|
||||
* @param string|array $value
|
||||
* @param string|array|null $key
|
||||
* @return array
|
||||
*/
|
||||
protected function explodePluckParameters($value, $key)
|
||||
{
|
||||
$value = is_string($value) ? explode('.', $value) : $value;
|
||||
|
||||
$key = is_null($key) || is_array($key) ? $key : explode('.', $key);
|
||||
|
||||
return [$value, $key];
|
||||
}
|
||||
|
||||
/**
|
||||
* Pass this lazy collection through a method on the collection class.
|
||||
*
|
||||
* @param string $method
|
||||
* @param array $params
|
||||
* @return static
|
||||
*/
|
||||
protected function passthru($method, array $params)
|
||||
{
|
||||
return new static(function () use ($method, $params) {
|
||||
yield from $this->collect()->$method(...$params);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current time.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
protected function now()
|
||||
{
|
||||
return time();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Support;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
class MultipleItemsFoundException extends RuntimeException
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,1051 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Support\Traits;
|
||||
|
||||
use CachingIterator;
|
||||
use Closure;
|
||||
use Exception;
|
||||
use Illuminate\Contracts\Support\Arrayable;
|
||||
use Illuminate\Contracts\Support\Jsonable;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Enumerable;
|
||||
use Illuminate\Support\HigherOrderCollectionProxy;
|
||||
use Illuminate\Support\HigherOrderWhenProxy;
|
||||
use JsonSerializable;
|
||||
use Symfony\Component\VarDumper\VarDumper;
|
||||
use Traversable;
|
||||
|
||||
/**
|
||||
* @property-read HigherOrderCollectionProxy $average
|
||||
* @property-read HigherOrderCollectionProxy $avg
|
||||
* @property-read HigherOrderCollectionProxy $contains
|
||||
* @property-read HigherOrderCollectionProxy $each
|
||||
* @property-read HigherOrderCollectionProxy $every
|
||||
* @property-read HigherOrderCollectionProxy $filter
|
||||
* @property-read HigherOrderCollectionProxy $first
|
||||
* @property-read HigherOrderCollectionProxy $flatMap
|
||||
* @property-read HigherOrderCollectionProxy $groupBy
|
||||
* @property-read HigherOrderCollectionProxy $keyBy
|
||||
* @property-read HigherOrderCollectionProxy $map
|
||||
* @property-read HigherOrderCollectionProxy $max
|
||||
* @property-read HigherOrderCollectionProxy $min
|
||||
* @property-read HigherOrderCollectionProxy $partition
|
||||
* @property-read HigherOrderCollectionProxy $reject
|
||||
* @property-read HigherOrderCollectionProxy $some
|
||||
* @property-read HigherOrderCollectionProxy $sortBy
|
||||
* @property-read HigherOrderCollectionProxy $sortByDesc
|
||||
* @property-read HigherOrderCollectionProxy $skipUntil
|
||||
* @property-read HigherOrderCollectionProxy $skipWhile
|
||||
* @property-read HigherOrderCollectionProxy $sum
|
||||
* @property-read HigherOrderCollectionProxy $takeUntil
|
||||
* @property-read HigherOrderCollectionProxy $takeWhile
|
||||
* @property-read HigherOrderCollectionProxy $unique
|
||||
* @property-read HigherOrderCollectionProxy $until
|
||||
*/
|
||||
trait EnumeratesValues
|
||||
{
|
||||
/**
|
||||
* The methods that can be proxied.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected static $proxies = [
|
||||
'average',
|
||||
'avg',
|
||||
'contains',
|
||||
'each',
|
||||
'every',
|
||||
'filter',
|
||||
'first',
|
||||
'flatMap',
|
||||
'groupBy',
|
||||
'keyBy',
|
||||
'map',
|
||||
'max',
|
||||
'min',
|
||||
'partition',
|
||||
'reject',
|
||||
'skipUntil',
|
||||
'skipWhile',
|
||||
'some',
|
||||
'sortBy',
|
||||
'sortByDesc',
|
||||
'sum',
|
||||
'takeUntil',
|
||||
'takeWhile',
|
||||
'unique',
|
||||
'until',
|
||||
];
|
||||
|
||||
/**
|
||||
* Create a new collection instance if the value isn't one already.
|
||||
*
|
||||
* @param mixed $items
|
||||
* @return static
|
||||
*/
|
||||
public static function make($items = [])
|
||||
{
|
||||
return new static($items);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap the given value in a collection if applicable.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return static
|
||||
*/
|
||||
public static function wrap($value)
|
||||
{
|
||||
return $value instanceof Enumerable
|
||||
? new static($value)
|
||||
: new static(Arr::wrap($value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the underlying items from the given collection if applicable.
|
||||
*
|
||||
* @param array|static $value
|
||||
* @return array
|
||||
*/
|
||||
public static function unwrap($value)
|
||||
{
|
||||
return $value instanceof Enumerable ? $value->all() : $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance with no items.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public static function empty()
|
||||
{
|
||||
return new static([]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new collection by invoking the callback a given amount of times.
|
||||
*
|
||||
* @param int $number
|
||||
* @param callable|null $callback
|
||||
* @return static
|
||||
*/
|
||||
public static function times($number, callable $callback = null)
|
||||
{
|
||||
if ($number < 1) {
|
||||
return new static;
|
||||
}
|
||||
|
||||
return static::range(1, $number)
|
||||
->when($callback)
|
||||
->map($callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias for the "avg" method.
|
||||
*
|
||||
* @param callable|string|null $callback
|
||||
* @return mixed
|
||||
*/
|
||||
public function average($callback = null)
|
||||
{
|
||||
return $this->avg($callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias for the "contains" method.
|
||||
*
|
||||
* @param mixed $key
|
||||
* @param mixed $operator
|
||||
* @param mixed $value
|
||||
* @return bool
|
||||
*/
|
||||
public function some($key, $operator = null, $value = null)
|
||||
{
|
||||
return $this->contains(...func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if an item exists, using strict comparison.
|
||||
*
|
||||
* @param mixed $key
|
||||
* @param mixed $value
|
||||
* @return bool
|
||||
*/
|
||||
public function containsStrict($key, $value = null)
|
||||
{
|
||||
if (func_num_args() === 2) {
|
||||
return $this->contains(function ($item) use ($key, $value) {
|
||||
return data_get($item, $key) === $value;
|
||||
});
|
||||
}
|
||||
|
||||
if ($this->useAsCallable($key)) {
|
||||
return ! is_null($this->first($key));
|
||||
}
|
||||
|
||||
foreach ($this as $item) {
|
||||
if ($item === $key) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump the items and end the script.
|
||||
*
|
||||
* @param mixed ...$args
|
||||
* @return void
|
||||
*/
|
||||
public function dd(...$args)
|
||||
{
|
||||
$this->dump(...$args);
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump the items.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function dump()
|
||||
{
|
||||
(new Collection(func_get_args()))
|
||||
->push($this->all())
|
||||
->each(function ($item) {
|
||||
VarDumper::dump($item);
|
||||
});
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a callback over each item.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @return $this
|
||||
*/
|
||||
public function each(callable $callback)
|
||||
{
|
||||
foreach ($this as $key => $item) {
|
||||
if ($callback($item, $key) === false) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a callback over each nested chunk of items.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @return static
|
||||
*/
|
||||
public function eachSpread(callable $callback)
|
||||
{
|
||||
return $this->each(function ($chunk, $key) use ($callback) {
|
||||
$chunk[] = $key;
|
||||
|
||||
return $callback(...$chunk);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if all items pass the given truth test.
|
||||
*
|
||||
* @param string|callable $key
|
||||
* @param mixed $operator
|
||||
* @param mixed $value
|
||||
* @return bool
|
||||
*/
|
||||
public function every($key, $operator = null, $value = null)
|
||||
{
|
||||
if (func_num_args() === 1) {
|
||||
$callback = $this->valueRetriever($key);
|
||||
|
||||
foreach ($this as $k => $v) {
|
||||
if (! $callback($v, $k)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return $this->every($this->operatorForWhere(...func_get_args()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the first item by the given key value pair.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $operator
|
||||
* @param mixed $value
|
||||
* @return mixed
|
||||
*/
|
||||
public function firstWhere($key, $operator = null, $value = null)
|
||||
{
|
||||
return $this->first($this->operatorForWhere(...func_get_args()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the collection is not empty.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isNotEmpty()
|
||||
{
|
||||
return ! $this->isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Run a map over each nested chunk of items.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @return static
|
||||
*/
|
||||
public function mapSpread(callable $callback)
|
||||
{
|
||||
return $this->map(function ($chunk, $key) use ($callback) {
|
||||
$chunk[] = $key;
|
||||
|
||||
return $callback(...$chunk);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Run a grouping map over the items.
|
||||
*
|
||||
* The callback should return an associative array with a single key/value pair.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @return static
|
||||
*/
|
||||
public function mapToGroups(callable $callback)
|
||||
{
|
||||
$groups = $this->mapToDictionary($callback);
|
||||
|
||||
return $groups->map([$this, 'make']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Map a collection and flatten the result by a single level.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @return static
|
||||
*/
|
||||
public function flatMap(callable $callback)
|
||||
{
|
||||
return $this->map($callback)->collapse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Map the values into a new class.
|
||||
*
|
||||
* @param string $class
|
||||
* @return static
|
||||
*/
|
||||
public function mapInto($class)
|
||||
{
|
||||
return $this->map(function ($value, $key) use ($class) {
|
||||
return new $class($value, $key);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the min value of a given key.
|
||||
*
|
||||
* @param callable|string|null $callback
|
||||
* @return mixed
|
||||
*/
|
||||
public function min($callback = null)
|
||||
{
|
||||
$callback = $this->valueRetriever($callback);
|
||||
|
||||
return $this->map(function ($value) use ($callback) {
|
||||
return $callback($value);
|
||||
})->filter(function ($value) {
|
||||
return ! is_null($value);
|
||||
})->reduce(function ($result, $value) {
|
||||
return is_null($result) || $value < $result ? $value : $result;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the max value of a given key.
|
||||
*
|
||||
* @param callable|string|null $callback
|
||||
* @return mixed
|
||||
*/
|
||||
public function max($callback = null)
|
||||
{
|
||||
$callback = $this->valueRetriever($callback);
|
||||
|
||||
return $this->filter(function ($value) {
|
||||
return ! is_null($value);
|
||||
})->reduce(function ($result, $item) use ($callback) {
|
||||
$value = $callback($item);
|
||||
|
||||
return is_null($result) || $value > $result ? $value : $result;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* "Paginate" the collection by slicing it into a smaller collection.
|
||||
*
|
||||
* @param int $page
|
||||
* @param int $perPage
|
||||
* @return static
|
||||
*/
|
||||
public function forPage($page, $perPage)
|
||||
{
|
||||
$offset = max(0, ($page - 1) * $perPage);
|
||||
|
||||
return $this->slice($offset, $perPage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Partition the collection into two arrays using the given callback or key.
|
||||
*
|
||||
* @param callable|string $key
|
||||
* @param mixed $operator
|
||||
* @param mixed $value
|
||||
* @return static
|
||||
*/
|
||||
public function partition($key, $operator = null, $value = null)
|
||||
{
|
||||
$passed = [];
|
||||
$failed = [];
|
||||
|
||||
$callback = func_num_args() === 1
|
||||
? $this->valueRetriever($key)
|
||||
: $this->operatorForWhere(...func_get_args());
|
||||
|
||||
foreach ($this as $key => $item) {
|
||||
if ($callback($item, $key)) {
|
||||
$passed[$key] = $item;
|
||||
} else {
|
||||
$failed[$key] = $item;
|
||||
}
|
||||
}
|
||||
|
||||
return new static([new static($passed), new static($failed)]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the sum of the given values.
|
||||
*
|
||||
* @param callable|string|null $callback
|
||||
* @return mixed
|
||||
*/
|
||||
public function sum($callback = null)
|
||||
{
|
||||
$callback = is_null($callback)
|
||||
? $this->identity()
|
||||
: $this->valueRetriever($callback);
|
||||
|
||||
return $this->reduce(function ($result, $item) use ($callback) {
|
||||
return $result + $callback($item);
|
||||
}, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the callback if the value is truthy.
|
||||
*
|
||||
* @param bool|mixed $value
|
||||
* @param callable|null $callback
|
||||
* @param callable|null $default
|
||||
* @return static|mixed
|
||||
*/
|
||||
public function when($value, callable $callback = null, callable $default = null)
|
||||
{
|
||||
if (! $callback) {
|
||||
return new HigherOrderWhenProxy($this, $value);
|
||||
}
|
||||
|
||||
if ($value) {
|
||||
return $callback($this, $value);
|
||||
} elseif ($default) {
|
||||
return $default($this, $value);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the callback if the collection is empty.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @param callable|null $default
|
||||
* @return static|mixed
|
||||
*/
|
||||
public function whenEmpty(callable $callback, callable $default = null)
|
||||
{
|
||||
return $this->when($this->isEmpty(), $callback, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the callback if the collection is not empty.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @param callable|null $default
|
||||
* @return static|mixed
|
||||
*/
|
||||
public function whenNotEmpty(callable $callback, callable $default = null)
|
||||
{
|
||||
return $this->when($this->isNotEmpty(), $callback, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the callback if the value is falsy.
|
||||
*
|
||||
* @param bool $value
|
||||
* @param callable $callback
|
||||
* @param callable|null $default
|
||||
* @return static|mixed
|
||||
*/
|
||||
public function unless($value, callable $callback, callable $default = null)
|
||||
{
|
||||
return $this->when(! $value, $callback, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the callback unless the collection is empty.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @param callable|null $default
|
||||
* @return static|mixed
|
||||
*/
|
||||
public function unlessEmpty(callable $callback, callable $default = null)
|
||||
{
|
||||
return $this->whenNotEmpty($callback, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the callback unless the collection is not empty.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @param callable|null $default
|
||||
* @return static|mixed
|
||||
*/
|
||||
public function unlessNotEmpty(callable $callback, callable $default = null)
|
||||
{
|
||||
return $this->whenEmpty($callback, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter items by the given key value pair.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $operator
|
||||
* @param mixed $value
|
||||
* @return static
|
||||
*/
|
||||
public function where($key, $operator = null, $value = null)
|
||||
{
|
||||
return $this->filter($this->operatorForWhere(...func_get_args()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter items where the value for the given key is null.
|
||||
*
|
||||
* @param string|null $key
|
||||
* @return static
|
||||
*/
|
||||
public function whereNull($key = null)
|
||||
{
|
||||
return $this->whereStrict($key, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter items where the value for the given key is not null.
|
||||
*
|
||||
* @param string|null $key
|
||||
* @return static
|
||||
*/
|
||||
public function whereNotNull($key = null)
|
||||
{
|
||||
return $this->where($key, '!==', null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter items by the given key value pair using strict comparison.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @return static
|
||||
*/
|
||||
public function whereStrict($key, $value)
|
||||
{
|
||||
return $this->where($key, '===', $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter items by the given key value pair.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $values
|
||||
* @param bool $strict
|
||||
* @return static
|
||||
*/
|
||||
public function whereIn($key, $values, $strict = false)
|
||||
{
|
||||
$values = $this->getArrayableItems($values);
|
||||
|
||||
return $this->filter(function ($item) use ($key, $values, $strict) {
|
||||
return in_array(data_get($item, $key), $values, $strict);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter items by the given key value pair using strict comparison.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $values
|
||||
* @return static
|
||||
*/
|
||||
public function whereInStrict($key, $values)
|
||||
{
|
||||
return $this->whereIn($key, $values, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter items such that the value of the given key is between the given values.
|
||||
*
|
||||
* @param string $key
|
||||
* @param array $values
|
||||
* @return static
|
||||
*/
|
||||
public function whereBetween($key, $values)
|
||||
{
|
||||
return $this->where($key, '>=', reset($values))->where($key, '<=', end($values));
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter items such that the value of the given key is not between the given values.
|
||||
*
|
||||
* @param string $key
|
||||
* @param array $values
|
||||
* @return static
|
||||
*/
|
||||
public function whereNotBetween($key, $values)
|
||||
{
|
||||
return $this->filter(function ($item) use ($key, $values) {
|
||||
return data_get($item, $key) < reset($values) || data_get($item, $key) > end($values);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter items by the given key value pair.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $values
|
||||
* @param bool $strict
|
||||
* @return static
|
||||
*/
|
||||
public function whereNotIn($key, $values, $strict = false)
|
||||
{
|
||||
$values = $this->getArrayableItems($values);
|
||||
|
||||
return $this->reject(function ($item) use ($key, $values, $strict) {
|
||||
return in_array(data_get($item, $key), $values, $strict);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter items by the given key value pair using strict comparison.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $values
|
||||
* @return static
|
||||
*/
|
||||
public function whereNotInStrict($key, $values)
|
||||
{
|
||||
return $this->whereNotIn($key, $values, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the items, removing any items that don't match the given type(s).
|
||||
*
|
||||
* @param string|string[] $type
|
||||
* @return static
|
||||
*/
|
||||
public function whereInstanceOf($type)
|
||||
{
|
||||
return $this->filter(function ($value) use ($type) {
|
||||
if (is_array($type)) {
|
||||
foreach ($type as $classType) {
|
||||
if ($value instanceof $classType) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return $value instanceof $type;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Pass the collection to the given callback and return the result.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @return mixed
|
||||
*/
|
||||
public function pipe(callable $callback)
|
||||
{
|
||||
return $callback($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pass the collection into a new class.
|
||||
*
|
||||
* @param string $class
|
||||
* @return mixed
|
||||
*/
|
||||
public function pipeInto($class)
|
||||
{
|
||||
return new $class($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pass the collection to the given callback and then return it.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @return $this
|
||||
*/
|
||||
public function tap(callable $callback)
|
||||
{
|
||||
$callback(clone $this);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reduce the collection to a single value.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @param mixed $initial
|
||||
* @return mixed
|
||||
*/
|
||||
public function reduce(callable $callback, $initial = null)
|
||||
{
|
||||
$result = $initial;
|
||||
|
||||
foreach ($this as $key => $value) {
|
||||
$result = $callback($result, $value, $key);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reduce an associative collection to a single value.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @param mixed $initial
|
||||
* @return mixed
|
||||
*/
|
||||
public function reduceWithKeys(callable $callback, $initial = null)
|
||||
{
|
||||
return $this->reduce($callback, $initial);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a collection of all elements that do not pass a given truth test.
|
||||
*
|
||||
* @param callable|mixed $callback
|
||||
* @return static
|
||||
*/
|
||||
public function reject($callback = true)
|
||||
{
|
||||
$useAsCallable = $this->useAsCallable($callback);
|
||||
|
||||
return $this->filter(function ($value, $key) use ($callback, $useAsCallable) {
|
||||
return $useAsCallable
|
||||
? ! $callback($value, $key)
|
||||
: $value != $callback;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Return only unique items from the collection array.
|
||||
*
|
||||
* @param string|callable|null $key
|
||||
* @param bool $strict
|
||||
* @return static
|
||||
*/
|
||||
public function unique($key = null, $strict = false)
|
||||
{
|
||||
$callback = $this->valueRetriever($key);
|
||||
|
||||
$exists = [];
|
||||
|
||||
return $this->reject(function ($item, $key) use ($callback, $strict, &$exists) {
|
||||
if (in_array($id = $callback($item, $key), $exists, $strict)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$exists[] = $id;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Return only unique items from the collection array using strict comparison.
|
||||
*
|
||||
* @param string|callable|null $key
|
||||
* @return static
|
||||
*/
|
||||
public function uniqueStrict($key = null)
|
||||
{
|
||||
return $this->unique($key, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Collect the values into a collection.
|
||||
*
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
public function collect()
|
||||
{
|
||||
return new Collection($this->all());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the collection of items as a plain array.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function toArray()
|
||||
{
|
||||
return $this->map(function ($value) {
|
||||
return $value instanceof Arrayable ? $value->toArray() : $value;
|
||||
})->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the object into something JSON serializable.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function jsonSerialize()
|
||||
{
|
||||
return array_map(function ($value) {
|
||||
if ($value instanceof JsonSerializable) {
|
||||
return $value->jsonSerialize();
|
||||
} elseif ($value instanceof Jsonable) {
|
||||
return json_decode($value->toJson(), true);
|
||||
} elseif ($value instanceof Arrayable) {
|
||||
return $value->toArray();
|
||||
}
|
||||
|
||||
return $value;
|
||||
}, $this->all());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the collection of items as JSON.
|
||||
*
|
||||
* @param int $options
|
||||
* @return string
|
||||
*/
|
||||
public function toJson($options = 0)
|
||||
{
|
||||
return json_encode($this->jsonSerialize(), $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a CachingIterator instance.
|
||||
*
|
||||
* @param int $flags
|
||||
* @return \CachingIterator
|
||||
*/
|
||||
public function getCachingIterator($flags = CachingIterator::CALL_TOSTRING)
|
||||
{
|
||||
return new CachingIterator($this->getIterator(), $flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the collection to its string representation.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return $this->toJson();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a method to the list of proxied methods.
|
||||
*
|
||||
* @param string $method
|
||||
* @return void
|
||||
*/
|
||||
public static function proxy($method)
|
||||
{
|
||||
static::$proxies[] = $method;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dynamically access collection proxies.
|
||||
*
|
||||
* @param string $key
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function __get($key)
|
||||
{
|
||||
if (! in_array($key, static::$proxies)) {
|
||||
throw new Exception("Property [{$key}] does not exist on this collection instance.");
|
||||
}
|
||||
|
||||
return new HigherOrderCollectionProxy($this, $key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Results array of items from Collection or Arrayable.
|
||||
*
|
||||
* @param mixed $items
|
||||
* @return array
|
||||
*/
|
||||
protected function getArrayableItems($items)
|
||||
{
|
||||
if (is_array($items)) {
|
||||
return $items;
|
||||
} elseif ($items instanceof Enumerable) {
|
||||
return $items->all();
|
||||
} elseif ($items instanceof Arrayable) {
|
||||
return $items->toArray();
|
||||
} elseif ($items instanceof Jsonable) {
|
||||
return json_decode($items->toJson(), true);
|
||||
} elseif ($items instanceof JsonSerializable) {
|
||||
return (array) $items->jsonSerialize();
|
||||
} elseif ($items instanceof Traversable) {
|
||||
return iterator_to_array($items);
|
||||
}
|
||||
|
||||
return (array) $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an operator checker callback.
|
||||
*
|
||||
* @param string $key
|
||||
* @param string|null $operator
|
||||
* @param mixed $value
|
||||
* @return \Closure
|
||||
*/
|
||||
protected function operatorForWhere($key, $operator = null, $value = null)
|
||||
{
|
||||
if (func_num_args() === 1) {
|
||||
$value = true;
|
||||
|
||||
$operator = '=';
|
||||
}
|
||||
|
||||
if (func_num_args() === 2) {
|
||||
$value = $operator;
|
||||
|
||||
$operator = '=';
|
||||
}
|
||||
|
||||
return function ($item) use ($key, $operator, $value) {
|
||||
$retrieved = data_get($item, $key);
|
||||
|
||||
$strings = array_filter([$retrieved, $value], function ($value) {
|
||||
return is_string($value) || (is_object($value) && method_exists($value, '__toString'));
|
||||
});
|
||||
|
||||
if (count($strings) < 2 && count(array_filter([$retrieved, $value], 'is_object')) == 1) {
|
||||
return in_array($operator, ['!=', '<>', '!==']);
|
||||
}
|
||||
|
||||
switch ($operator) {
|
||||
default:
|
||||
case '=':
|
||||
case '==': return $retrieved == $value;
|
||||
case '!=':
|
||||
case '<>': return $retrieved != $value;
|
||||
case '<': return $retrieved < $value;
|
||||
case '>': return $retrieved > $value;
|
||||
case '<=': return $retrieved <= $value;
|
||||
case '>=': return $retrieved >= $value;
|
||||
case '===': return $retrieved === $value;
|
||||
case '!==': return $retrieved !== $value;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given value is callable, but not a string.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return bool
|
||||
*/
|
||||
protected function useAsCallable($value)
|
||||
{
|
||||
return ! is_string($value) && is_callable($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a value retrieving callback.
|
||||
*
|
||||
* @param callable|string|null $value
|
||||
* @return callable
|
||||
*/
|
||||
protected function valueRetriever($value)
|
||||
{
|
||||
if ($this->useAsCallable($value)) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
return function ($item) use ($value) {
|
||||
return data_get($item, $value);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a function to check an item's equality.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return \Closure
|
||||
*/
|
||||
protected function equality($value)
|
||||
{
|
||||
return function ($item) use ($value) {
|
||||
return $item === $value;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a function using another function, by negating its result.
|
||||
*
|
||||
* @param \Closure $callback
|
||||
* @return \Closure
|
||||
*/
|
||||
protected function negate(Closure $callback)
|
||||
{
|
||||
return function (...$params) use ($callback) {
|
||||
return ! $callback(...$params);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a function that returns what's passed to it.
|
||||
*
|
||||
* @return \Closure
|
||||
*/
|
||||
protected function identity()
|
||||
{
|
||||
return function ($value) {
|
||||
return $value;
|
||||
};
|
||||
}
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"name": "illuminate/collections",
|
||||
"description": "The Illuminate Collections package.",
|
||||
"license": "MIT",
|
||||
"homepage": "https://laravel.com",
|
||||
"support": {
|
||||
"issues": "https://github.com/laravel/framework/issues",
|
||||
"source": "https://github.com/laravel/framework"
|
||||
},
|
||||
"authors": [
|
||||
{
|
||||
"name": "Taylor Otwell",
|
||||
"email": "taylor@laravel.com"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": "^7.3|^8.0",
|
||||
"illuminate/contracts": "^8.0",
|
||||
"illuminate/macroable": "^8.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Illuminate\\Support\\": ""
|
||||
},
|
||||
"files": [
|
||||
"helpers.php"
|
||||
]
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "8.x-dev"
|
||||
}
|
||||
},
|
||||
"suggest": {
|
||||
"symfony/var-dumper": "Required to use the dump method (^5.1.4)."
|
||||
},
|
||||
"config": {
|
||||
"sort-packages": true
|
||||
},
|
||||
"minimum-stability": "dev"
|
||||
}
|
||||
+186
@@ -0,0 +1,186 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
if (! function_exists('collect')) {
|
||||
/**
|
||||
* Create a collection from the given value.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
function collect($value = null)
|
||||
{
|
||||
return new Collection($value);
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('data_fill')) {
|
||||
/**
|
||||
* Fill in data where it's missing.
|
||||
*
|
||||
* @param mixed $target
|
||||
* @param string|array $key
|
||||
* @param mixed $value
|
||||
* @return mixed
|
||||
*/
|
||||
function data_fill(&$target, $key, $value)
|
||||
{
|
||||
return data_set($target, $key, $value, false);
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('data_get')) {
|
||||
/**
|
||||
* Get an item from an array or object using "dot" notation.
|
||||
*
|
||||
* @param mixed $target
|
||||
* @param string|array|int|null $key
|
||||
* @param mixed $default
|
||||
* @return mixed
|
||||
*/
|
||||
function data_get($target, $key, $default = null)
|
||||
{
|
||||
if (is_null($key)) {
|
||||
return $target;
|
||||
}
|
||||
|
||||
$key = is_array($key) ? $key : explode('.', $key);
|
||||
|
||||
foreach ($key as $i => $segment) {
|
||||
unset($key[$i]);
|
||||
|
||||
if (is_null($segment)) {
|
||||
return $target;
|
||||
}
|
||||
|
||||
if ($segment === '*') {
|
||||
if ($target instanceof Collection) {
|
||||
$target = $target->all();
|
||||
} elseif (! is_array($target)) {
|
||||
return value($default);
|
||||
}
|
||||
|
||||
$result = [];
|
||||
|
||||
foreach ($target as $item) {
|
||||
$result[] = data_get($item, $key);
|
||||
}
|
||||
|
||||
return in_array('*', $key) ? Arr::collapse($result) : $result;
|
||||
}
|
||||
|
||||
if (Arr::accessible($target) && Arr::exists($target, $segment)) {
|
||||
$target = $target[$segment];
|
||||
} elseif (is_object($target) && isset($target->{$segment})) {
|
||||
$target = $target->{$segment};
|
||||
} else {
|
||||
return value($default);
|
||||
}
|
||||
}
|
||||
|
||||
return $target;
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('data_set')) {
|
||||
/**
|
||||
* Set an item on an array or object using dot notation.
|
||||
*
|
||||
* @param mixed $target
|
||||
* @param string|array $key
|
||||
* @param mixed $value
|
||||
* @param bool $overwrite
|
||||
* @return mixed
|
||||
*/
|
||||
function data_set(&$target, $key, $value, $overwrite = true)
|
||||
{
|
||||
$segments = is_array($key) ? $key : explode('.', $key);
|
||||
|
||||
if (($segment = array_shift($segments)) === '*') {
|
||||
if (! Arr::accessible($target)) {
|
||||
$target = [];
|
||||
}
|
||||
|
||||
if ($segments) {
|
||||
foreach ($target as &$inner) {
|
||||
data_set($inner, $segments, $value, $overwrite);
|
||||
}
|
||||
} elseif ($overwrite) {
|
||||
foreach ($target as &$inner) {
|
||||
$inner = $value;
|
||||
}
|
||||
}
|
||||
} elseif (Arr::accessible($target)) {
|
||||
if ($segments) {
|
||||
if (! Arr::exists($target, $segment)) {
|
||||
$target[$segment] = [];
|
||||
}
|
||||
|
||||
data_set($target[$segment], $segments, $value, $overwrite);
|
||||
} elseif ($overwrite || ! Arr::exists($target, $segment)) {
|
||||
$target[$segment] = $value;
|
||||
}
|
||||
} elseif (is_object($target)) {
|
||||
if ($segments) {
|
||||
if (! isset($target->{$segment})) {
|
||||
$target->{$segment} = [];
|
||||
}
|
||||
|
||||
data_set($target->{$segment}, $segments, $value, $overwrite);
|
||||
} elseif ($overwrite || ! isset($target->{$segment})) {
|
||||
$target->{$segment} = $value;
|
||||
}
|
||||
} else {
|
||||
$target = [];
|
||||
|
||||
if ($segments) {
|
||||
data_set($target[$segment], $segments, $value, $overwrite);
|
||||
} elseif ($overwrite) {
|
||||
$target[$segment] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $target;
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('head')) {
|
||||
/**
|
||||
* Get the first element of an array. Useful for method chaining.
|
||||
*
|
||||
* @param array $array
|
||||
* @return mixed
|
||||
*/
|
||||
function head($array)
|
||||
{
|
||||
return reset($array);
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('last')) {
|
||||
/**
|
||||
* Get the last element from an array.
|
||||
*
|
||||
* @param array $array
|
||||
* @return mixed
|
||||
*/
|
||||
function last($array)
|
||||
{
|
||||
return end($array);
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('value')) {
|
||||
/**
|
||||
* Return the default value of the given value.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return mixed
|
||||
*/
|
||||
function value($value, ...$args)
|
||||
{
|
||||
return $value instanceof Closure ? $value(...$args) : $value;
|
||||
}
|
||||
}
|
||||
+196
@@ -0,0 +1,196 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Container;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Contracts\Container\BindingResolutionException;
|
||||
use InvalidArgumentException;
|
||||
use ReflectionFunction;
|
||||
use ReflectionMethod;
|
||||
|
||||
class BoundMethod
|
||||
{
|
||||
/**
|
||||
* Call the given Closure / class@method and inject its dependencies.
|
||||
*
|
||||
* @param \Illuminate\Container\Container $container
|
||||
* @param callable|string $callback
|
||||
* @param array $parameters
|
||||
* @param string|null $defaultMethod
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \ReflectionException
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public static function call($container, $callback, array $parameters = [], $defaultMethod = null)
|
||||
{
|
||||
if (is_string($callback) && ! $defaultMethod && method_exists($callback, '__invoke')) {
|
||||
$defaultMethod = '__invoke';
|
||||
}
|
||||
|
||||
if (static::isCallableWithAtSign($callback) || $defaultMethod) {
|
||||
return static::callClass($container, $callback, $parameters, $defaultMethod);
|
||||
}
|
||||
|
||||
return static::callBoundMethod($container, $callback, function () use ($container, $callback, $parameters) {
|
||||
return $callback(...array_values(static::getMethodDependencies($container, $callback, $parameters)));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Call a string reference to a class using Class@method syntax.
|
||||
*
|
||||
* @param \Illuminate\Container\Container $container
|
||||
* @param string $target
|
||||
* @param array $parameters
|
||||
* @param string|null $defaultMethod
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
protected static function callClass($container, $target, array $parameters = [], $defaultMethod = null)
|
||||
{
|
||||
$segments = explode('@', $target);
|
||||
|
||||
// We will assume an @ sign is used to delimit the class name from the method
|
||||
// name. We will split on this @ sign and then build a callable array that
|
||||
// we can pass right back into the "call" method for dependency binding.
|
||||
$method = count($segments) === 2
|
||||
? $segments[1] : $defaultMethod;
|
||||
|
||||
if (is_null($method)) {
|
||||
throw new InvalidArgumentException('Method not provided.');
|
||||
}
|
||||
|
||||
return static::call(
|
||||
$container, [$container->make($segments[0]), $method], $parameters
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call a method that has been bound to the container.
|
||||
*
|
||||
* @param \Illuminate\Container\Container $container
|
||||
* @param callable $callback
|
||||
* @param mixed $default
|
||||
* @return mixed
|
||||
*/
|
||||
protected static function callBoundMethod($container, $callback, $default)
|
||||
{
|
||||
if (! is_array($callback)) {
|
||||
return Util::unwrapIfClosure($default);
|
||||
}
|
||||
|
||||
// Here we need to turn the array callable into a Class@method string we can use to
|
||||
// examine the container and see if there are any method bindings for this given
|
||||
// method. If there are, we can call this method binding callback immediately.
|
||||
$method = static::normalizeMethod($callback);
|
||||
|
||||
if ($container->hasMethodBinding($method)) {
|
||||
return $container->callMethodBinding($method, $callback[0]);
|
||||
}
|
||||
|
||||
return Util::unwrapIfClosure($default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize the given callback into a Class@method string.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @return string
|
||||
*/
|
||||
protected static function normalizeMethod($callback)
|
||||
{
|
||||
$class = is_string($callback[0]) ? $callback[0] : get_class($callback[0]);
|
||||
|
||||
return "{$class}@{$callback[1]}";
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all dependencies for a given method.
|
||||
*
|
||||
* @param \Illuminate\Container\Container $container
|
||||
* @param callable|string $callback
|
||||
* @param array $parameters
|
||||
* @return array
|
||||
*
|
||||
* @throws \ReflectionException
|
||||
*/
|
||||
protected static function getMethodDependencies($container, $callback, array $parameters = [])
|
||||
{
|
||||
$dependencies = [];
|
||||
|
||||
foreach (static::getCallReflector($callback)->getParameters() as $parameter) {
|
||||
static::addDependencyForCallParameter($container, $parameter, $parameters, $dependencies);
|
||||
}
|
||||
|
||||
return array_merge($dependencies, array_values($parameters));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the proper reflection instance for the given callback.
|
||||
*
|
||||
* @param callable|string $callback
|
||||
* @return \ReflectionFunctionAbstract
|
||||
*
|
||||
* @throws \ReflectionException
|
||||
*/
|
||||
protected static function getCallReflector($callback)
|
||||
{
|
||||
if (is_string($callback) && strpos($callback, '::') !== false) {
|
||||
$callback = explode('::', $callback);
|
||||
} elseif (is_object($callback) && ! $callback instanceof Closure) {
|
||||
$callback = [$callback, '__invoke'];
|
||||
}
|
||||
|
||||
return is_array($callback)
|
||||
? new ReflectionMethod($callback[0], $callback[1])
|
||||
: new ReflectionFunction($callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the dependency for the given call parameter.
|
||||
*
|
||||
* @param \Illuminate\Container\Container $container
|
||||
* @param \ReflectionParameter $parameter
|
||||
* @param array $parameters
|
||||
* @param array $dependencies
|
||||
* @return void
|
||||
*
|
||||
* @throws \Illuminate\Contracts\Container\BindingResolutionException
|
||||
*/
|
||||
protected static function addDependencyForCallParameter($container, $parameter,
|
||||
array &$parameters, &$dependencies)
|
||||
{
|
||||
if (array_key_exists($paramName = $parameter->getName(), $parameters)) {
|
||||
$dependencies[] = $parameters[$paramName];
|
||||
|
||||
unset($parameters[$paramName]);
|
||||
} elseif (! is_null($className = Util::getParameterClassName($parameter))) {
|
||||
if (array_key_exists($className, $parameters)) {
|
||||
$dependencies[] = $parameters[$className];
|
||||
|
||||
unset($parameters[$className]);
|
||||
} else {
|
||||
$dependencies[] = $container->make($className);
|
||||
}
|
||||
} elseif ($parameter->isDefaultValueAvailable()) {
|
||||
$dependencies[] = $parameter->getDefaultValue();
|
||||
} elseif (! $parameter->isOptional() && ! array_key_exists($paramName, $parameters)) {
|
||||
$message = "Unable to resolve dependency [{$parameter}] in class {$parameter->getDeclaringClass()->getName()}";
|
||||
|
||||
throw new BindingResolutionException($message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given string is in Class@method syntax.
|
||||
*
|
||||
* @param mixed $callback
|
||||
* @return bool
|
||||
*/
|
||||
protected static function isCallableWithAtSign($callback)
|
||||
{
|
||||
return is_string($callback) && strpos($callback, '@') !== false;
|
||||
}
|
||||
}
|
||||
+1471
@@ -0,0 +1,1471 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Container;
|
||||
|
||||
use ArrayAccess;
|
||||
use Closure;
|
||||
use Exception;
|
||||
use Illuminate\Contracts\Container\BindingResolutionException;
|
||||
use Illuminate\Contracts\Container\CircularDependencyException;
|
||||
use Illuminate\Contracts\Container\Container as ContainerContract;
|
||||
use LogicException;
|
||||
use ReflectionClass;
|
||||
use ReflectionException;
|
||||
use ReflectionParameter;
|
||||
use TypeError;
|
||||
|
||||
class Container implements ArrayAccess, ContainerContract
|
||||
{
|
||||
/**
|
||||
* The current globally available container (if any).
|
||||
*
|
||||
* @var static
|
||||
*/
|
||||
protected static $instance;
|
||||
|
||||
/**
|
||||
* An array of the types that have been resolved.
|
||||
*
|
||||
* @var bool[]
|
||||
*/
|
||||
protected $resolved = [];
|
||||
|
||||
/**
|
||||
* The container's bindings.
|
||||
*
|
||||
* @var array[]
|
||||
*/
|
||||
protected $bindings = [];
|
||||
|
||||
/**
|
||||
* The container's method bindings.
|
||||
*
|
||||
* @var \Closure[]
|
||||
*/
|
||||
protected $methodBindings = [];
|
||||
|
||||
/**
|
||||
* The container's shared instances.
|
||||
*
|
||||
* @var object[]
|
||||
*/
|
||||
protected $instances = [];
|
||||
|
||||
/**
|
||||
* The container's scoped instances.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $scopedInstances = [];
|
||||
|
||||
/**
|
||||
* The registered type aliases.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $aliases = [];
|
||||
|
||||
/**
|
||||
* The registered aliases keyed by the abstract name.
|
||||
*
|
||||
* @var array[]
|
||||
*/
|
||||
protected $abstractAliases = [];
|
||||
|
||||
/**
|
||||
* The extension closures for services.
|
||||
*
|
||||
* @var array[]
|
||||
*/
|
||||
protected $extenders = [];
|
||||
|
||||
/**
|
||||
* All of the registered tags.
|
||||
*
|
||||
* @var array[]
|
||||
*/
|
||||
protected $tags = [];
|
||||
|
||||
/**
|
||||
* The stack of concretions currently being built.
|
||||
*
|
||||
* @var array[]
|
||||
*/
|
||||
protected $buildStack = [];
|
||||
|
||||
/**
|
||||
* The parameter override stack.
|
||||
*
|
||||
* @var array[]
|
||||
*/
|
||||
protected $with = [];
|
||||
|
||||
/**
|
||||
* The contextual binding map.
|
||||
*
|
||||
* @var array[]
|
||||
*/
|
||||
public $contextual = [];
|
||||
|
||||
/**
|
||||
* All of the registered rebound callbacks.
|
||||
*
|
||||
* @var array[]
|
||||
*/
|
||||
protected $reboundCallbacks = [];
|
||||
|
||||
/**
|
||||
* All of the global before resolving callbacks.
|
||||
*
|
||||
* @var \Closure[]
|
||||
*/
|
||||
protected $globalBeforeResolvingCallbacks = [];
|
||||
|
||||
/**
|
||||
* All of the global resolving callbacks.
|
||||
*
|
||||
* @var \Closure[]
|
||||
*/
|
||||
protected $globalResolvingCallbacks = [];
|
||||
|
||||
/**
|
||||
* All of the global after resolving callbacks.
|
||||
*
|
||||
* @var \Closure[]
|
||||
*/
|
||||
protected $globalAfterResolvingCallbacks = [];
|
||||
|
||||
/**
|
||||
* All of the before resolving callbacks by class type.
|
||||
*
|
||||
* @var array[]
|
||||
*/
|
||||
protected $beforeResolvingCallbacks = [];
|
||||
|
||||
/**
|
||||
* All of the resolving callbacks by class type.
|
||||
*
|
||||
* @var array[]
|
||||
*/
|
||||
protected $resolvingCallbacks = [];
|
||||
|
||||
/**
|
||||
* All of the after resolving callbacks by class type.
|
||||
*
|
||||
* @var array[]
|
||||
*/
|
||||
protected $afterResolvingCallbacks = [];
|
||||
|
||||
/**
|
||||
* Define a contextual binding.
|
||||
*
|
||||
* @param array|string $concrete
|
||||
* @return \Illuminate\Contracts\Container\ContextualBindingBuilder
|
||||
*/
|
||||
public function when($concrete)
|
||||
{
|
||||
$aliases = [];
|
||||
|
||||
foreach (Util::arrayWrap($concrete) as $c) {
|
||||
$aliases[] = $this->getAlias($c);
|
||||
}
|
||||
|
||||
return new ContextualBindingBuilder($this, $aliases);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given abstract type has been bound.
|
||||
*
|
||||
* @param string $abstract
|
||||
* @return bool
|
||||
*/
|
||||
public function bound($abstract)
|
||||
{
|
||||
return isset($this->bindings[$abstract]) ||
|
||||
isset($this->instances[$abstract]) ||
|
||||
$this->isAlias($abstract);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function has($id)
|
||||
{
|
||||
return $this->bound($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given abstract type has been resolved.
|
||||
*
|
||||
* @param string $abstract
|
||||
* @return bool
|
||||
*/
|
||||
public function resolved($abstract)
|
||||
{
|
||||
if ($this->isAlias($abstract)) {
|
||||
$abstract = $this->getAlias($abstract);
|
||||
}
|
||||
|
||||
return isset($this->resolved[$abstract]) ||
|
||||
isset($this->instances[$abstract]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a given type is shared.
|
||||
*
|
||||
* @param string $abstract
|
||||
* @return bool
|
||||
*/
|
||||
public function isShared($abstract)
|
||||
{
|
||||
return isset($this->instances[$abstract]) ||
|
||||
(isset($this->bindings[$abstract]['shared']) &&
|
||||
$this->bindings[$abstract]['shared'] === true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a given string is an alias.
|
||||
*
|
||||
* @param string $name
|
||||
* @return bool
|
||||
*/
|
||||
public function isAlias($name)
|
||||
{
|
||||
return isset($this->aliases[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a binding with the container.
|
||||
*
|
||||
* @param string $abstract
|
||||
* @param \Closure|string|null $concrete
|
||||
* @param bool $shared
|
||||
* @return void
|
||||
*
|
||||
* @throws \TypeError
|
||||
*/
|
||||
public function bind($abstract, $concrete = null, $shared = false)
|
||||
{
|
||||
$this->dropStaleInstances($abstract);
|
||||
|
||||
// If no concrete type was given, we will simply set the concrete type to the
|
||||
// abstract type. After that, the concrete type to be registered as shared
|
||||
// without being forced to state their classes in both of the parameters.
|
||||
if (is_null($concrete)) {
|
||||
$concrete = $abstract;
|
||||
}
|
||||
|
||||
// If the factory is not a Closure, it means it is just a class name which is
|
||||
// bound into this container to the abstract type and we will just wrap it
|
||||
// up inside its own Closure to give us more convenience when extending.
|
||||
if (! $concrete instanceof Closure) {
|
||||
if (! is_string($concrete)) {
|
||||
throw new TypeError(self::class.'::bind(): Argument #2 ($concrete) must be of type Closure|string|null');
|
||||
}
|
||||
|
||||
$concrete = $this->getClosure($abstract, $concrete);
|
||||
}
|
||||
|
||||
$this->bindings[$abstract] = compact('concrete', 'shared');
|
||||
|
||||
// If the abstract type was already resolved in this container we'll fire the
|
||||
// rebound listener so that any objects which have already gotten resolved
|
||||
// can have their copy of the object updated via the listener callbacks.
|
||||
if ($this->resolved($abstract)) {
|
||||
$this->rebound($abstract);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Closure to be used when building a type.
|
||||
*
|
||||
* @param string $abstract
|
||||
* @param string $concrete
|
||||
* @return \Closure
|
||||
*/
|
||||
protected function getClosure($abstract, $concrete)
|
||||
{
|
||||
return function ($container, $parameters = []) use ($abstract, $concrete) {
|
||||
if ($abstract == $concrete) {
|
||||
return $container->build($concrete);
|
||||
}
|
||||
|
||||
return $container->resolve(
|
||||
$concrete, $parameters, $raiseEvents = false
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the container has a method binding.
|
||||
*
|
||||
* @param string $method
|
||||
* @return bool
|
||||
*/
|
||||
public function hasMethodBinding($method)
|
||||
{
|
||||
return isset($this->methodBindings[$method]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind a callback to resolve with Container::call.
|
||||
*
|
||||
* @param array|string $method
|
||||
* @param \Closure $callback
|
||||
* @return void
|
||||
*/
|
||||
public function bindMethod($method, $callback)
|
||||
{
|
||||
$this->methodBindings[$this->parseBindMethod($method)] = $callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the method to be bound in class@method format.
|
||||
*
|
||||
* @param array|string $method
|
||||
* @return string
|
||||
*/
|
||||
protected function parseBindMethod($method)
|
||||
{
|
||||
if (is_array($method)) {
|
||||
return $method[0].'@'.$method[1];
|
||||
}
|
||||
|
||||
return $method;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the method binding for the given method.
|
||||
*
|
||||
* @param string $method
|
||||
* @param mixed $instance
|
||||
* @return mixed
|
||||
*/
|
||||
public function callMethodBinding($method, $instance)
|
||||
{
|
||||
return call_user_func($this->methodBindings[$method], $instance, $this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a contextual binding to the container.
|
||||
*
|
||||
* @param string $concrete
|
||||
* @param string $abstract
|
||||
* @param \Closure|string $implementation
|
||||
* @return void
|
||||
*/
|
||||
public function addContextualBinding($concrete, $abstract, $implementation)
|
||||
{
|
||||
$this->contextual[$concrete][$this->getAlias($abstract)] = $implementation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a binding if it hasn't already been registered.
|
||||
*
|
||||
* @param string $abstract
|
||||
* @param \Closure|string|null $concrete
|
||||
* @param bool $shared
|
||||
* @return void
|
||||
*/
|
||||
public function bindIf($abstract, $concrete = null, $shared = false)
|
||||
{
|
||||
if (! $this->bound($abstract)) {
|
||||
$this->bind($abstract, $concrete, $shared);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a shared binding in the container.
|
||||
*
|
||||
* @param string $abstract
|
||||
* @param \Closure|string|null $concrete
|
||||
* @return void
|
||||
*/
|
||||
public function singleton($abstract, $concrete = null)
|
||||
{
|
||||
$this->bind($abstract, $concrete, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a shared binding if it hasn't already been registered.
|
||||
*
|
||||
* @param string $abstract
|
||||
* @param \Closure|string|null $concrete
|
||||
* @return void
|
||||
*/
|
||||
public function singletonIf($abstract, $concrete = null)
|
||||
{
|
||||
if (! $this->bound($abstract)) {
|
||||
$this->singleton($abstract, $concrete);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a scoped binding in the container.
|
||||
*
|
||||
* @param string $abstract
|
||||
* @param \Closure|string|null $concrete
|
||||
* @return void
|
||||
*/
|
||||
public function scoped($abstract, $concrete = null)
|
||||
{
|
||||
$this->scopedInstances[] = $abstract;
|
||||
|
||||
$this->singleton($abstract, $concrete);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a scoped binding if it hasn't already been registered.
|
||||
*
|
||||
* @param string $abstract
|
||||
* @param \Closure|string|null $concrete
|
||||
* @return void
|
||||
*/
|
||||
public function scopedIf($abstract, $concrete = null)
|
||||
{
|
||||
if (! $this->bound($abstract)) {
|
||||
$this->scopedInstances[] = $abstract;
|
||||
|
||||
$this->singleton($abstract, $concrete);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* "Extend" an abstract type in the container.
|
||||
*
|
||||
* @param string $abstract
|
||||
* @param \Closure $closure
|
||||
* @return void
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function extend($abstract, Closure $closure)
|
||||
{
|
||||
$abstract = $this->getAlias($abstract);
|
||||
|
||||
if (isset($this->instances[$abstract])) {
|
||||
$this->instances[$abstract] = $closure($this->instances[$abstract], $this);
|
||||
|
||||
$this->rebound($abstract);
|
||||
} else {
|
||||
$this->extenders[$abstract][] = $closure;
|
||||
|
||||
if ($this->resolved($abstract)) {
|
||||
$this->rebound($abstract);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register an existing instance as shared in the container.
|
||||
*
|
||||
* @param string $abstract
|
||||
* @param mixed $instance
|
||||
* @return mixed
|
||||
*/
|
||||
public function instance($abstract, $instance)
|
||||
{
|
||||
$this->removeAbstractAlias($abstract);
|
||||
|
||||
$isBound = $this->bound($abstract);
|
||||
|
||||
unset($this->aliases[$abstract]);
|
||||
|
||||
// We'll check to determine if this type has been bound before, and if it has
|
||||
// we will fire the rebound callbacks registered with the container and it
|
||||
// can be updated with consuming classes that have gotten resolved here.
|
||||
$this->instances[$abstract] = $instance;
|
||||
|
||||
if ($isBound) {
|
||||
$this->rebound($abstract);
|
||||
}
|
||||
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an alias from the contextual binding alias cache.
|
||||
*
|
||||
* @param string $searched
|
||||
* @return void
|
||||
*/
|
||||
protected function removeAbstractAlias($searched)
|
||||
{
|
||||
if (! isset($this->aliases[$searched])) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($this->abstractAliases as $abstract => $aliases) {
|
||||
foreach ($aliases as $index => $alias) {
|
||||
if ($alias == $searched) {
|
||||
unset($this->abstractAliases[$abstract][$index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign a set of tags to a given binding.
|
||||
*
|
||||
* @param array|string $abstracts
|
||||
* @param array|mixed ...$tags
|
||||
* @return void
|
||||
*/
|
||||
public function tag($abstracts, $tags)
|
||||
{
|
||||
$tags = is_array($tags) ? $tags : array_slice(func_get_args(), 1);
|
||||
|
||||
foreach ($tags as $tag) {
|
||||
if (! isset($this->tags[$tag])) {
|
||||
$this->tags[$tag] = [];
|
||||
}
|
||||
|
||||
foreach ((array) $abstracts as $abstract) {
|
||||
$this->tags[$tag][] = $abstract;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve all of the bindings for a given tag.
|
||||
*
|
||||
* @param string $tag
|
||||
* @return iterable
|
||||
*/
|
||||
public function tagged($tag)
|
||||
{
|
||||
if (! isset($this->tags[$tag])) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return new RewindableGenerator(function () use ($tag) {
|
||||
foreach ($this->tags[$tag] as $abstract) {
|
||||
yield $this->make($abstract);
|
||||
}
|
||||
}, count($this->tags[$tag]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias a type to a different name.
|
||||
*
|
||||
* @param string $abstract
|
||||
* @param string $alias
|
||||
* @return void
|
||||
*
|
||||
* @throws \LogicException
|
||||
*/
|
||||
public function alias($abstract, $alias)
|
||||
{
|
||||
if ($alias === $abstract) {
|
||||
throw new LogicException("[{$abstract}] is aliased to itself.");
|
||||
}
|
||||
|
||||
$this->aliases[$alias] = $abstract;
|
||||
|
||||
$this->abstractAliases[$abstract][] = $alias;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind a new callback to an abstract's rebind event.
|
||||
*
|
||||
* @param string $abstract
|
||||
* @param \Closure $callback
|
||||
* @return mixed
|
||||
*/
|
||||
public function rebinding($abstract, Closure $callback)
|
||||
{
|
||||
$this->reboundCallbacks[$abstract = $this->getAlias($abstract)][] = $callback;
|
||||
|
||||
if ($this->bound($abstract)) {
|
||||
return $this->make($abstract);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh an instance on the given target and method.
|
||||
*
|
||||
* @param string $abstract
|
||||
* @param mixed $target
|
||||
* @param string $method
|
||||
* @return mixed
|
||||
*/
|
||||
public function refresh($abstract, $target, $method)
|
||||
{
|
||||
return $this->rebinding($abstract, function ($app, $instance) use ($target, $method) {
|
||||
$target->{$method}($instance);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Fire the "rebound" callbacks for the given abstract type.
|
||||
*
|
||||
* @param string $abstract
|
||||
* @return void
|
||||
*/
|
||||
protected function rebound($abstract)
|
||||
{
|
||||
$instance = $this->make($abstract);
|
||||
|
||||
foreach ($this->getReboundCallbacks($abstract) as $callback) {
|
||||
call_user_func($callback, $this, $instance);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the rebound callbacks for a given type.
|
||||
*
|
||||
* @param string $abstract
|
||||
* @return array
|
||||
*/
|
||||
protected function getReboundCallbacks($abstract)
|
||||
{
|
||||
return $this->reboundCallbacks[$abstract] ?? [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap the given closure such that its dependencies will be injected when executed.
|
||||
*
|
||||
* @param \Closure $callback
|
||||
* @param array $parameters
|
||||
* @return \Closure
|
||||
*/
|
||||
public function wrap(Closure $callback, array $parameters = [])
|
||||
{
|
||||
return function () use ($callback, $parameters) {
|
||||
return $this->call($callback, $parameters);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Call the given Closure / class@method and inject its dependencies.
|
||||
*
|
||||
* @param callable|string $callback
|
||||
* @param array<string, mixed> $parameters
|
||||
* @param string|null $defaultMethod
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function call($callback, array $parameters = [], $defaultMethod = null)
|
||||
{
|
||||
return BoundMethod::call($this, $callback, $parameters, $defaultMethod);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a closure to resolve the given type from the container.
|
||||
*
|
||||
* @param string $abstract
|
||||
* @return \Closure
|
||||
*/
|
||||
public function factory($abstract)
|
||||
{
|
||||
return function () use ($abstract) {
|
||||
return $this->make($abstract);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* An alias function name for make().
|
||||
*
|
||||
* @param string|callable $abstract
|
||||
* @param array $parameters
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \Illuminate\Contracts\Container\BindingResolutionException
|
||||
*/
|
||||
public function makeWith($abstract, array $parameters = [])
|
||||
{
|
||||
return $this->make($abstract, $parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the given type from the container.
|
||||
*
|
||||
* @param string|callable $abstract
|
||||
* @param array $parameters
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \Illuminate\Contracts\Container\BindingResolutionException
|
||||
*/
|
||||
public function make($abstract, array $parameters = [])
|
||||
{
|
||||
return $this->resolve($abstract, $parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function get($id)
|
||||
{
|
||||
try {
|
||||
return $this->resolve($id);
|
||||
} catch (Exception $e) {
|
||||
if ($this->has($id) || $e instanceof CircularDependencyException) {
|
||||
throw $e;
|
||||
}
|
||||
|
||||
throw new EntryNotFoundException($id, $e->getCode(), $e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the given type from the container.
|
||||
*
|
||||
* @param string|callable $abstract
|
||||
* @param array $parameters
|
||||
* @param bool $raiseEvents
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \Illuminate\Contracts\Container\BindingResolutionException
|
||||
* @throws \Illuminate\Contracts\Container\CircularDependencyException
|
||||
*/
|
||||
protected function resolve($abstract, $parameters = [], $raiseEvents = true)
|
||||
{
|
||||
$abstract = $this->getAlias($abstract);
|
||||
|
||||
// First we'll fire any event handlers which handle the "before" resolving of
|
||||
// specific types. This gives some hooks the chance to add various extends
|
||||
// calls to change the resolution of objects that they're interested in.
|
||||
if ($raiseEvents) {
|
||||
$this->fireBeforeResolvingCallbacks($abstract, $parameters);
|
||||
}
|
||||
|
||||
$concrete = $this->getContextualConcrete($abstract);
|
||||
|
||||
$needsContextualBuild = ! empty($parameters) || ! is_null($concrete);
|
||||
|
||||
// If an instance of the type is currently being managed as a singleton we'll
|
||||
// just return an existing instance instead of instantiating new instances
|
||||
// so the developer can keep using the same objects instance every time.
|
||||
if (isset($this->instances[$abstract]) && ! $needsContextualBuild) {
|
||||
return $this->instances[$abstract];
|
||||
}
|
||||
|
||||
$this->with[] = $parameters;
|
||||
|
||||
if (is_null($concrete)) {
|
||||
$concrete = $this->getConcrete($abstract);
|
||||
}
|
||||
|
||||
// We're ready to instantiate an instance of the concrete type registered for
|
||||
// the binding. This will instantiate the types, as well as resolve any of
|
||||
// its "nested" dependencies recursively until all have gotten resolved.
|
||||
if ($this->isBuildable($concrete, $abstract)) {
|
||||
$object = $this->build($concrete);
|
||||
} else {
|
||||
$object = $this->make($concrete);
|
||||
}
|
||||
|
||||
// If we defined any extenders for this type, we'll need to spin through them
|
||||
// and apply them to the object being built. This allows for the extension
|
||||
// of services, such as changing configuration or decorating the object.
|
||||
foreach ($this->getExtenders($abstract) as $extender) {
|
||||
$object = $extender($object, $this);
|
||||
}
|
||||
|
||||
// If the requested type is registered as a singleton we'll want to cache off
|
||||
// the instances in "memory" so we can return it later without creating an
|
||||
// entirely new instance of an object on each subsequent request for it.
|
||||
if ($this->isShared($abstract) && ! $needsContextualBuild) {
|
||||
$this->instances[$abstract] = $object;
|
||||
}
|
||||
|
||||
if ($raiseEvents) {
|
||||
$this->fireResolvingCallbacks($abstract, $object);
|
||||
}
|
||||
|
||||
// Before returning, we will also set the resolved flag to "true" and pop off
|
||||
// the parameter overrides for this build. After those two things are done
|
||||
// we will be ready to return back the fully constructed class instance.
|
||||
$this->resolved[$abstract] = true;
|
||||
|
||||
array_pop($this->with);
|
||||
|
||||
return $object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the concrete type for a given abstract.
|
||||
*
|
||||
* @param string|callable $abstract
|
||||
* @return mixed
|
||||
*/
|
||||
protected function getConcrete($abstract)
|
||||
{
|
||||
// If we don't have a registered resolver or concrete for the type, we'll just
|
||||
// assume each type is a concrete name and will attempt to resolve it as is
|
||||
// since the container should be able to resolve concretes automatically.
|
||||
if (isset($this->bindings[$abstract])) {
|
||||
return $this->bindings[$abstract]['concrete'];
|
||||
}
|
||||
|
||||
return $abstract;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the contextual concrete binding for the given abstract.
|
||||
*
|
||||
* @param string|callable $abstract
|
||||
* @return \Closure|string|array|null
|
||||
*/
|
||||
protected function getContextualConcrete($abstract)
|
||||
{
|
||||
if (! is_null($binding = $this->findInContextualBindings($abstract))) {
|
||||
return $binding;
|
||||
}
|
||||
|
||||
// Next we need to see if a contextual binding might be bound under an alias of the
|
||||
// given abstract type. So, we will need to check if any aliases exist with this
|
||||
// type and then spin through them and check for contextual bindings on these.
|
||||
if (empty($this->abstractAliases[$abstract])) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($this->abstractAliases[$abstract] as $alias) {
|
||||
if (! is_null($binding = $this->findInContextualBindings($alias))) {
|
||||
return $binding;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the concrete binding for the given abstract in the contextual binding array.
|
||||
*
|
||||
* @param string|callable $abstract
|
||||
* @return \Closure|string|null
|
||||
*/
|
||||
protected function findInContextualBindings($abstract)
|
||||
{
|
||||
return $this->contextual[end($this->buildStack)][$abstract] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given concrete is buildable.
|
||||
*
|
||||
* @param mixed $concrete
|
||||
* @param string $abstract
|
||||
* @return bool
|
||||
*/
|
||||
protected function isBuildable($concrete, $abstract)
|
||||
{
|
||||
return $concrete === $abstract || $concrete instanceof Closure;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate a concrete instance of the given type.
|
||||
*
|
||||
* @param \Closure|string $concrete
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \Illuminate\Contracts\Container\BindingResolutionException
|
||||
* @throws \Illuminate\Contracts\Container\CircularDependencyException
|
||||
*/
|
||||
public function build($concrete)
|
||||
{
|
||||
// If the concrete type is actually a Closure, we will just execute it and
|
||||
// hand back the results of the functions, which allows functions to be
|
||||
// used as resolvers for more fine-tuned resolution of these objects.
|
||||
if ($concrete instanceof Closure) {
|
||||
return $concrete($this, $this->getLastParameterOverride());
|
||||
}
|
||||
|
||||
try {
|
||||
$reflector = new ReflectionClass($concrete);
|
||||
} catch (ReflectionException $e) {
|
||||
throw new BindingResolutionException("Target class [$concrete] does not exist.", 0, $e);
|
||||
}
|
||||
|
||||
// If the type is not instantiable, the developer is attempting to resolve
|
||||
// an abstract type such as an Interface or Abstract Class and there is
|
||||
// no binding registered for the abstractions so we need to bail out.
|
||||
if (! $reflector->isInstantiable()) {
|
||||
return $this->notInstantiable($concrete);
|
||||
}
|
||||
|
||||
// if (in_array($concrete, $this->buildStack)) {
|
||||
// throw new CircularDependencyException("Circular dependency detected while resolving [{$concrete}].");
|
||||
// }
|
||||
|
||||
$this->buildStack[] = $concrete;
|
||||
|
||||
$constructor = $reflector->getConstructor();
|
||||
|
||||
// If there are no constructors, that means there are no dependencies then
|
||||
// we can just resolve the instances of the objects right away, without
|
||||
// resolving any other types or dependencies out of these containers.
|
||||
if (is_null($constructor)) {
|
||||
array_pop($this->buildStack);
|
||||
|
||||
return new $concrete;
|
||||
}
|
||||
|
||||
$dependencies = $constructor->getParameters();
|
||||
|
||||
// Once we have all the constructor's parameters we can create each of the
|
||||
// dependency instances and then use the reflection instances to make a
|
||||
// new instance of this class, injecting the created dependencies in.
|
||||
try {
|
||||
$instances = $this->resolveDependencies($dependencies);
|
||||
} catch (BindingResolutionException $e) {
|
||||
array_pop($this->buildStack);
|
||||
|
||||
throw $e;
|
||||
}
|
||||
|
||||
array_pop($this->buildStack);
|
||||
|
||||
return $reflector->newInstanceArgs($instances);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve all of the dependencies from the ReflectionParameters.
|
||||
*
|
||||
* @param \ReflectionParameter[] $dependencies
|
||||
* @return array
|
||||
*
|
||||
* @throws \Illuminate\Contracts\Container\BindingResolutionException
|
||||
*/
|
||||
protected function resolveDependencies(array $dependencies)
|
||||
{
|
||||
$results = [];
|
||||
|
||||
foreach ($dependencies as $dependency) {
|
||||
// If the dependency has an override for this particular build we will use
|
||||
// that instead as the value. Otherwise, we will continue with this run
|
||||
// of resolutions and let reflection attempt to determine the result.
|
||||
if ($this->hasParameterOverride($dependency)) {
|
||||
$results[] = $this->getParameterOverride($dependency);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// If the class is null, it means the dependency is a string or some other
|
||||
// primitive type which we can not resolve since it is not a class and
|
||||
// we will just bomb out with an error since we have no-where to go.
|
||||
$result = is_null(Util::getParameterClassName($dependency))
|
||||
? $this->resolvePrimitive($dependency)
|
||||
: $this->resolveClass($dependency);
|
||||
|
||||
if ($dependency->isVariadic()) {
|
||||
$results = array_merge($results, $result);
|
||||
} else {
|
||||
$results[] = $result;
|
||||
}
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given dependency has a parameter override.
|
||||
*
|
||||
* @param \ReflectionParameter $dependency
|
||||
* @return bool
|
||||
*/
|
||||
protected function hasParameterOverride($dependency)
|
||||
{
|
||||
return array_key_exists(
|
||||
$dependency->name, $this->getLastParameterOverride()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a parameter override for a dependency.
|
||||
*
|
||||
* @param \ReflectionParameter $dependency
|
||||
* @return mixed
|
||||
*/
|
||||
protected function getParameterOverride($dependency)
|
||||
{
|
||||
return $this->getLastParameterOverride()[$dependency->name];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the last parameter override.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getLastParameterOverride()
|
||||
{
|
||||
return count($this->with) ? end($this->with) : [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve a non-class hinted primitive dependency.
|
||||
*
|
||||
* @param \ReflectionParameter $parameter
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \Illuminate\Contracts\Container\BindingResolutionException
|
||||
*/
|
||||
protected function resolvePrimitive(ReflectionParameter $parameter)
|
||||
{
|
||||
if (! is_null($concrete = $this->getContextualConcrete('$'.$parameter->getName()))) {
|
||||
return $concrete instanceof Closure ? $concrete($this) : $concrete;
|
||||
}
|
||||
|
||||
if ($parameter->isDefaultValueAvailable()) {
|
||||
return $parameter->getDefaultValue();
|
||||
}
|
||||
|
||||
$this->unresolvablePrimitive($parameter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve a class based dependency from the container.
|
||||
*
|
||||
* @param \ReflectionParameter $parameter
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \Illuminate\Contracts\Container\BindingResolutionException
|
||||
*/
|
||||
protected function resolveClass(ReflectionParameter $parameter)
|
||||
{
|
||||
try {
|
||||
return $parameter->isVariadic()
|
||||
? $this->resolveVariadicClass($parameter)
|
||||
: $this->make(Util::getParameterClassName($parameter));
|
||||
}
|
||||
|
||||
// If we can not resolve the class instance, we will check to see if the value
|
||||
// is optional, and if it is we will return the optional parameter value as
|
||||
// the value of the dependency, similarly to how we do this with scalars.
|
||||
catch (BindingResolutionException $e) {
|
||||
if ($parameter->isDefaultValueAvailable()) {
|
||||
array_pop($this->with);
|
||||
|
||||
return $parameter->getDefaultValue();
|
||||
}
|
||||
|
||||
if ($parameter->isVariadic()) {
|
||||
array_pop($this->with);
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve a class based variadic dependency from the container.
|
||||
*
|
||||
* @param \ReflectionParameter $parameter
|
||||
* @return mixed
|
||||
*/
|
||||
protected function resolveVariadicClass(ReflectionParameter $parameter)
|
||||
{
|
||||
$className = Util::getParameterClassName($parameter);
|
||||
|
||||
$abstract = $this->getAlias($className);
|
||||
|
||||
if (! is_array($concrete = $this->getContextualConcrete($abstract))) {
|
||||
return $this->make($className);
|
||||
}
|
||||
|
||||
return array_map(function ($abstract) {
|
||||
return $this->resolve($abstract);
|
||||
}, $concrete);
|
||||
}
|
||||
|
||||
/**
|
||||
* Throw an exception that the concrete is not instantiable.
|
||||
*
|
||||
* @param string $concrete
|
||||
* @return void
|
||||
*
|
||||
* @throws \Illuminate\Contracts\Container\BindingResolutionException
|
||||
*/
|
||||
protected function notInstantiable($concrete)
|
||||
{
|
||||
if (! empty($this->buildStack)) {
|
||||
$previous = implode(', ', $this->buildStack);
|
||||
|
||||
$message = "Target [$concrete] is not instantiable while building [$previous].";
|
||||
} else {
|
||||
$message = "Target [$concrete] is not instantiable.";
|
||||
}
|
||||
|
||||
throw new BindingResolutionException($message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Throw an exception for an unresolvable primitive.
|
||||
*
|
||||
* @param \ReflectionParameter $parameter
|
||||
* @return void
|
||||
*
|
||||
* @throws \Illuminate\Contracts\Container\BindingResolutionException
|
||||
*/
|
||||
protected function unresolvablePrimitive(ReflectionParameter $parameter)
|
||||
{
|
||||
$message = "Unresolvable dependency resolving [$parameter] in class {$parameter->getDeclaringClass()->getName()}";
|
||||
|
||||
throw new BindingResolutionException($message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a new before resolving callback for all types.
|
||||
*
|
||||
* @param \Closure|string $abstract
|
||||
* @param \Closure|null $callback
|
||||
* @return void
|
||||
*/
|
||||
public function beforeResolving($abstract, Closure $callback = null)
|
||||
{
|
||||
if (is_string($abstract)) {
|
||||
$abstract = $this->getAlias($abstract);
|
||||
}
|
||||
|
||||
if ($abstract instanceof Closure && is_null($callback)) {
|
||||
$this->globalBeforeResolvingCallbacks[] = $abstract;
|
||||
} else {
|
||||
$this->beforeResolvingCallbacks[$abstract][] = $callback;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a new resolving callback.
|
||||
*
|
||||
* @param \Closure|string $abstract
|
||||
* @param \Closure|null $callback
|
||||
* @return void
|
||||
*/
|
||||
public function resolving($abstract, Closure $callback = null)
|
||||
{
|
||||
if (is_string($abstract)) {
|
||||
$abstract = $this->getAlias($abstract);
|
||||
}
|
||||
|
||||
if (is_null($callback) && $abstract instanceof Closure) {
|
||||
$this->globalResolvingCallbacks[] = $abstract;
|
||||
} else {
|
||||
$this->resolvingCallbacks[$abstract][] = $callback;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a new after resolving callback for all types.
|
||||
*
|
||||
* @param \Closure|string $abstract
|
||||
* @param \Closure|null $callback
|
||||
* @return void
|
||||
*/
|
||||
public function afterResolving($abstract, Closure $callback = null)
|
||||
{
|
||||
if (is_string($abstract)) {
|
||||
$abstract = $this->getAlias($abstract);
|
||||
}
|
||||
|
||||
if ($abstract instanceof Closure && is_null($callback)) {
|
||||
$this->globalAfterResolvingCallbacks[] = $abstract;
|
||||
} else {
|
||||
$this->afterResolvingCallbacks[$abstract][] = $callback;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fire all of the before resolving callbacks.
|
||||
*
|
||||
* @param string $abstract
|
||||
* @param array $parameters
|
||||
* @return void
|
||||
*/
|
||||
protected function fireBeforeResolvingCallbacks($abstract, $parameters = [])
|
||||
{
|
||||
$this->fireBeforeCallbackArray($abstract, $parameters, $this->globalBeforeResolvingCallbacks);
|
||||
|
||||
foreach ($this->beforeResolvingCallbacks as $type => $callbacks) {
|
||||
if ($type === $abstract || is_subclass_of($abstract, $type)) {
|
||||
$this->fireBeforeCallbackArray($abstract, $parameters, $callbacks);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fire an array of callbacks with an object.
|
||||
*
|
||||
* @param string $abstract
|
||||
* @param array $parameters
|
||||
* @param array $callbacks
|
||||
* @return void
|
||||
*/
|
||||
protected function fireBeforeCallbackArray($abstract, $parameters, array $callbacks)
|
||||
{
|
||||
foreach ($callbacks as $callback) {
|
||||
$callback($abstract, $parameters, $this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fire all of the resolving callbacks.
|
||||
*
|
||||
* @param string $abstract
|
||||
* @param mixed $object
|
||||
* @return void
|
||||
*/
|
||||
protected function fireResolvingCallbacks($abstract, $object)
|
||||
{
|
||||
$this->fireCallbackArray($object, $this->globalResolvingCallbacks);
|
||||
|
||||
$this->fireCallbackArray(
|
||||
$object, $this->getCallbacksForType($abstract, $object, $this->resolvingCallbacks)
|
||||
);
|
||||
|
||||
$this->fireAfterResolvingCallbacks($abstract, $object);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fire all of the after resolving callbacks.
|
||||
*
|
||||
* @param string $abstract
|
||||
* @param mixed $object
|
||||
* @return void
|
||||
*/
|
||||
protected function fireAfterResolvingCallbacks($abstract, $object)
|
||||
{
|
||||
$this->fireCallbackArray($object, $this->globalAfterResolvingCallbacks);
|
||||
|
||||
$this->fireCallbackArray(
|
||||
$object, $this->getCallbacksForType($abstract, $object, $this->afterResolvingCallbacks)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all callbacks for a given type.
|
||||
*
|
||||
* @param string $abstract
|
||||
* @param object $object
|
||||
* @param array $callbacksPerType
|
||||
* @return array
|
||||
*/
|
||||
protected function getCallbacksForType($abstract, $object, array $callbacksPerType)
|
||||
{
|
||||
$results = [];
|
||||
|
||||
foreach ($callbacksPerType as $type => $callbacks) {
|
||||
if ($type === $abstract || $object instanceof $type) {
|
||||
$results = array_merge($results, $callbacks);
|
||||
}
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fire an array of callbacks with an object.
|
||||
*
|
||||
* @param mixed $object
|
||||
* @param array $callbacks
|
||||
* @return void
|
||||
*/
|
||||
protected function fireCallbackArray($object, array $callbacks)
|
||||
{
|
||||
foreach ($callbacks as $callback) {
|
||||
$callback($object, $this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the container's bindings.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getBindings()
|
||||
{
|
||||
return $this->bindings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the alias for an abstract if available.
|
||||
*
|
||||
* @param string $abstract
|
||||
* @return string
|
||||
*/
|
||||
public function getAlias($abstract)
|
||||
{
|
||||
return isset($this->aliases[$abstract])
|
||||
? $this->getAlias($this->aliases[$abstract])
|
||||
: $abstract;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the extender callbacks for a given type.
|
||||
*
|
||||
* @param string $abstract
|
||||
* @return array
|
||||
*/
|
||||
protected function getExtenders($abstract)
|
||||
{
|
||||
return $this->extenders[$this->getAlias($abstract)] ?? [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all of the extender callbacks for a given type.
|
||||
*
|
||||
* @param string $abstract
|
||||
* @return void
|
||||
*/
|
||||
public function forgetExtenders($abstract)
|
||||
{
|
||||
unset($this->extenders[$this->getAlias($abstract)]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop all of the stale instances and aliases.
|
||||
*
|
||||
* @param string $abstract
|
||||
* @return void
|
||||
*/
|
||||
protected function dropStaleInstances($abstract)
|
||||
{
|
||||
unset($this->instances[$abstract], $this->aliases[$abstract]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a resolved instance from the instance cache.
|
||||
*
|
||||
* @param string $abstract
|
||||
* @return void
|
||||
*/
|
||||
public function forgetInstance($abstract)
|
||||
{
|
||||
unset($this->instances[$abstract]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all of the instances from the container.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function forgetInstances()
|
||||
{
|
||||
$this->instances = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all of the scoped instances from the container.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function forgetScopedInstances()
|
||||
{
|
||||
foreach ($this->scopedInstances as $scoped) {
|
||||
unset($this->instances[$scoped]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush the container of all bindings and resolved instances.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function flush()
|
||||
{
|
||||
$this->aliases = [];
|
||||
$this->resolved = [];
|
||||
$this->bindings = [];
|
||||
$this->instances = [];
|
||||
$this->abstractAliases = [];
|
||||
$this->scopedInstances = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the globally available instance of the container.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public static function getInstance()
|
||||
{
|
||||
if (is_null(static::$instance)) {
|
||||
static::$instance = new static;
|
||||
}
|
||||
|
||||
return static::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the shared instance of the container.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Container\Container|null $container
|
||||
* @return \Illuminate\Contracts\Container\Container|static
|
||||
*/
|
||||
public static function setInstance(ContainerContract $container = null)
|
||||
{
|
||||
return static::$instance = $container;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a given offset exists.
|
||||
*
|
||||
* @param string $key
|
||||
* @return bool
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetExists($key)
|
||||
{
|
||||
return $this->bound($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value at a given offset.
|
||||
*
|
||||
* @param string $key
|
||||
* @return mixed
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetGet($key)
|
||||
{
|
||||
return $this->make($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value at a given offset.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @return void
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetSet($key, $value)
|
||||
{
|
||||
$this->bind($key, $value instanceof Closure ? $value : function () use ($value) {
|
||||
return $value;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Unset the value at a given offset.
|
||||
*
|
||||
* @param string $key
|
||||
* @return void
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetUnset($key)
|
||||
{
|
||||
unset($this->bindings[$key], $this->instances[$key], $this->resolved[$key]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dynamically access container services.
|
||||
*
|
||||
* @param string $key
|
||||
* @return mixed
|
||||
*/
|
||||
public function __get($key)
|
||||
{
|
||||
return $this[$key];
|
||||
}
|
||||
|
||||
/**
|
||||
* Dynamically set container services.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @return void
|
||||
*/
|
||||
public function __set($key, $value)
|
||||
{
|
||||
$this[$key] = $value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Container;
|
||||
|
||||
use Illuminate\Contracts\Container\Container;
|
||||
use Illuminate\Contracts\Container\ContextualBindingBuilder as ContextualBindingBuilderContract;
|
||||
|
||||
class ContextualBindingBuilder implements ContextualBindingBuilderContract
|
||||
{
|
||||
/**
|
||||
* The underlying container instance.
|
||||
*
|
||||
* @var \Illuminate\Contracts\Container\Container
|
||||
*/
|
||||
protected $container;
|
||||
|
||||
/**
|
||||
* The concrete instance.
|
||||
*
|
||||
* @var string|array
|
||||
*/
|
||||
protected $concrete;
|
||||
|
||||
/**
|
||||
* The abstract target.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $needs;
|
||||
|
||||
/**
|
||||
* Create a new contextual binding builder.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Container\Container $container
|
||||
* @param string|array $concrete
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Container $container, $concrete)
|
||||
{
|
||||
$this->concrete = $concrete;
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define the abstract target that depends on the context.
|
||||
*
|
||||
* @param string $abstract
|
||||
* @return $this
|
||||
*/
|
||||
public function needs($abstract)
|
||||
{
|
||||
$this->needs = $abstract;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define the implementation for the contextual binding.
|
||||
*
|
||||
* @param \Closure|string|array $implementation
|
||||
* @return void
|
||||
*/
|
||||
public function give($implementation)
|
||||
{
|
||||
foreach (Util::arrayWrap($this->concrete) as $concrete) {
|
||||
$this->container->addContextualBinding($concrete, $this->needs, $implementation);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Define tagged services to be used as the implementation for the contextual binding.
|
||||
*
|
||||
* @param string $tag
|
||||
* @return void
|
||||
*/
|
||||
public function giveTagged($tag)
|
||||
{
|
||||
$this->give(function ($container) use ($tag) {
|
||||
$taggedServices = $container->tagged($tag);
|
||||
|
||||
return is_array($taggedServices) ? $taggedServices : iterator_to_array($taggedServices);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the configuration item to bind as a primitive.
|
||||
*
|
||||
* @param string $key
|
||||
* @param ?string $default
|
||||
* @return void
|
||||
*/
|
||||
public function giveConfig($key, $default = null)
|
||||
{
|
||||
$this->give(function ($container) use ($key, $default) {
|
||||
return $container->get('config')->get($key, $default);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Container;
|
||||
|
||||
use Exception;
|
||||
use Psr\Container\NotFoundExceptionInterface;
|
||||
|
||||
class EntryNotFoundException extends Exception implements NotFoundExceptionInterface
|
||||
{
|
||||
//
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) Taylor Otwell
|
||||
|
||||
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.
|
||||
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Container;
|
||||
|
||||
use Countable;
|
||||
use IteratorAggregate;
|
||||
|
||||
class RewindableGenerator implements Countable, IteratorAggregate
|
||||
{
|
||||
/**
|
||||
* The generator callback.
|
||||
*
|
||||
* @var callable
|
||||
*/
|
||||
protected $generator;
|
||||
|
||||
/**
|
||||
* The number of tagged services.
|
||||
*
|
||||
* @var callable|int
|
||||
*/
|
||||
protected $count;
|
||||
|
||||
/**
|
||||
* Create a new generator instance.
|
||||
*
|
||||
* @param callable $generator
|
||||
* @param callable|int $count
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(callable $generator, $count)
|
||||
{
|
||||
$this->count = $count;
|
||||
$this->generator = $generator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an iterator from the generator.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function getIterator()
|
||||
{
|
||||
return ($this->generator)();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the total number of tagged services.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function count()
|
||||
{
|
||||
if (is_callable($count = $this->count)) {
|
||||
$this->count = $count();
|
||||
}
|
||||
|
||||
return $this->count;
|
||||
}
|
||||
}
|
||||
Vendored
+73
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Container;
|
||||
|
||||
use Closure;
|
||||
use ReflectionNamedType;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
class Util
|
||||
{
|
||||
/**
|
||||
* If the given value is not an array and not null, wrap it in one.
|
||||
*
|
||||
* From Arr::wrap() in Illuminate\Support.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return array
|
||||
*/
|
||||
public static function arrayWrap($value)
|
||||
{
|
||||
if (is_null($value)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return is_array($value) ? $value : [$value];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the default value of the given value.
|
||||
*
|
||||
* From global value() helper in Illuminate\Support.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return mixed
|
||||
*/
|
||||
public static function unwrapIfClosure($value)
|
||||
{
|
||||
return $value instanceof Closure ? $value() : $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the class name of the given parameter's type, if possible.
|
||||
*
|
||||
* From Reflector::getParameterClassName() in Illuminate\Support.
|
||||
*
|
||||
* @param \ReflectionParameter $parameter
|
||||
* @return string|null
|
||||
*/
|
||||
public static function getParameterClassName($parameter)
|
||||
{
|
||||
$type = $parameter->getType();
|
||||
|
||||
if (! $type instanceof ReflectionNamedType || $type->isBuiltin()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$name = $type->getName();
|
||||
|
||||
if (! is_null($class = $parameter->getDeclaringClass())) {
|
||||
if ($name === 'self') {
|
||||
return $class->getName();
|
||||
}
|
||||
|
||||
if ($name === 'parent' && $parent = $class->getParentClass()) {
|
||||
return $parent->getName();
|
||||
}
|
||||
}
|
||||
|
||||
return $name;
|
||||
}
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"name": "illuminate/container",
|
||||
"description": "The Illuminate Container package.",
|
||||
"license": "MIT",
|
||||
"homepage": "https://laravel.com",
|
||||
"support": {
|
||||
"issues": "https://github.com/laravel/framework/issues",
|
||||
"source": "https://github.com/laravel/framework"
|
||||
},
|
||||
"authors": [
|
||||
{
|
||||
"name": "Taylor Otwell",
|
||||
"email": "taylor@laravel.com"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": "^7.3|^8.0",
|
||||
"illuminate/contracts": "^8.0",
|
||||
"psr/container": "^1.0"
|
||||
},
|
||||
"provide": {
|
||||
"psr/container-implementation": "1.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Illuminate\\Container\\": ""
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "8.x-dev"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"sort-packages": true
|
||||
},
|
||||
"minimum-stability": "dev"
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user