diff --git a/README.md b/README.md
index 65ea6de..37ec4ae 100644
--- a/README.md
+++ b/README.md
@@ -83,7 +83,7 @@ $r->addRoute('POST', '/test', 'handler');
$r->addRoute(['GET', 'POST'], '/test', 'handler');
```
-By default the `$routePattern` uses a syntax where `{foo}` specifies a placeholder with name `foo`
+By default, the `$routePattern` uses a syntax where `{foo}` specifies a placeholder with name `foo`
and matching the regex `[^/]+`. To adjust the pattern the placeholder matches, you can specify
a custom pattern by writing `{bar:[0-9]+}`. Some examples:
@@ -102,7 +102,7 @@ Custom patterns for route placeholders cannot use capturing groups. For example
is not a valid placeholder, because `()` is a capturing group. Instead you can use either
`{lang:en|de}` or `{lang:(?:en|de)}`.
-Furthermore parts of the route enclosed in `[...]` are considered optional, so that `/foo[bar]`
+Furthermore, parts of the route enclosed in `[...]` are considered optional, so that `/foo[bar]`
will match both `/foo` and `/foobar`. Optional parts are only supported in a trailing position,
not in the middle of a route.
@@ -142,7 +142,7 @@ $r->addRoute('POST', '/post-route', 'post_handler');
#### Route Groups
-Additionally, you can specify routes inside of a group. All routes defined inside a group will have a common prefix.
+Additionally, you can specify routes inside a group. All routes defined inside a group will have a common prefix.
For example, defining your routes as:
@@ -178,13 +178,15 @@ $dispatcher = FastRoute\cachedDispatcher(function(FastRoute\RouteCollector $r) {
$r->addRoute('GET', '/user/{id:[0-9]+}', 'handler1');
$r->addRoute('GET', '/user/{name}', 'handler2');
}, [
- 'cacheFile' => __DIR__ . '/route.cache', /* required */
+ 'cacheKey' => __DIR__ . '/route.cache', /* required */
+ // 'cacheFile' => __DIR__ . '/route.cache', /* will still work for v1 compatibility */
'cacheDisabled' => IS_DEBUG_ENABLED, /* optional, enabled by default */
+ 'cacheDriver' => FastRoute\Cache\FileCache::class, /* optional, class name or instance of the cache driver - defaults to file cache */
]);
```
The second parameter to the function is an options array, which can be used to specify the cache
-file location, among other things.
+key (e.g. file location when using files for caching), caching driver, among other things.
### Dispatching a URI
@@ -237,7 +239,7 @@ interface Dispatcher {
```
The route parser takes a route pattern string and converts it into an array of route infos, where
-each route info is again an array of it's parts. The structure is best understood using an example:
+each route info is again an array of its parts. The structure is best understood using an example:
/* The route /user/{id:\d+}[/{name}] converts to the following array: */
[
diff --git a/composer.json b/composer.json
index 81ee506..e7beb37 100644
--- a/composer.json
+++ b/composer.json
@@ -13,7 +13,8 @@
}
],
"require": {
- "php": ">=8.1.0"
+ "php": ">=8.1.0",
+ "psr/simple-cache": "^2.0 || ^3.0"
},
"require-dev": {
"lcobucci/coding-standard": "^11.0",
@@ -25,9 +26,6 @@
"phpstan/phpstan-strict-rules": "^1.5",
"phpunit/phpunit": "^10.3"
},
- "suggest": {
- "ext-apcu": "To be able to use APCu cache driver"
- },
"autoload": {
"psr-4": {
"FastRoute\\": "src/"
diff --git a/composer.lock b/composer.lock
index 1edb455..fcb4329 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,8 +4,60 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "15caf1db569069edcb6962bf2579bf95",
- "packages": [],
+ "content-hash": "33ff31143ee093ff78a64d215f60180e",
+ "packages": [
+ {
+ "name": "psr/simple-cache",
+ "version": "3.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/simple-cache.git",
+ "reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/764e0b3939f5ca87cb904f570ef9be2d78a07865",
+ "reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.0.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\SimpleCache\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://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/3.0.0"
+ },
+ "time": "2021-10-29T13:26:27+00:00"
+ }
+ ],
"packages-dev": [
{
"name": "dealerdirect/phpcodesniffer-composer-installer",
@@ -404,25 +456,27 @@
},
{
"name": "nikic/php-parser",
- "version": "v4.17.1",
+ "version": "v5.0.0",
"source": {
"type": "git",
"url": "https://github.com/nikic/PHP-Parser.git",
- "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d"
+ "reference": "4a21235f7e56e713259a6f76bf4b5ea08502b9dc"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d",
- "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d",
+ "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/4a21235f7e56e713259a6f76bf4b5ea08502b9dc",
+ "reference": "4a21235f7e56e713259a6f76bf4b5ea08502b9dc",
"shasum": ""
},
"require": {
+ "ext-ctype": "*",
+ "ext-json": "*",
"ext-tokenizer": "*",
- "php": ">=7.0"
+ "php": ">=7.4"
},
"require-dev": {
"ircmaxell/php-yacc": "^0.0.7",
- "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0"
+ "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0"
},
"bin": [
"bin/php-parse"
@@ -430,7 +484,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "4.9-dev"
+ "dev-master": "5.0-dev"
}
},
"autoload": {
@@ -454,9 +508,9 @@
],
"support": {
"issues": "https://github.com/nikic/PHP-Parser/issues",
- "source": "https://github.com/nikic/PHP-Parser/tree/v4.17.1"
+ "source": "https://github.com/nikic/PHP-Parser/tree/v5.0.0"
},
- "time": "2023-08-13T19:53:39+00:00"
+ "time": "2024-01-07T17:17:35+00:00"
},
{
"name": "phar-io/manifest",
@@ -571,21 +625,21 @@
},
{
"name": "phpbench/container",
- "version": "2.2.1",
+ "version": "2.2.2",
"source": {
"type": "git",
"url": "https://github.com/phpbench/container.git",
- "reference": "6d555ff7174fca13f9b1ec0b4a089ed41d0ab392"
+ "reference": "a59b929e00b87b532ca6d0edd8eca0967655af33"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpbench/container/zipball/6d555ff7174fca13f9b1ec0b4a089ed41d0ab392",
- "reference": "6d555ff7174fca13f9b1ec0b4a089ed41d0ab392",
+ "url": "https://api.github.com/repos/phpbench/container/zipball/a59b929e00b87b532ca6d0edd8eca0967655af33",
+ "reference": "a59b929e00b87b532ca6d0edd8eca0967655af33",
"shasum": ""
},
"require": {
"psr/container": "^1.0|^2.0",
- "symfony/options-resolver": "^4.2 || ^5.0 || ^6.0"
+ "symfony/options-resolver": "^4.2 || ^5.0 || ^6.0 || ^7.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^2.16",
@@ -616,9 +670,9 @@
"description": "Simple, configurable, service container.",
"support": {
"issues": "https://github.com/phpbench/container/issues",
- "source": "https://github.com/phpbench/container/tree/2.2.1"
+ "source": "https://github.com/phpbench/container/tree/2.2.2"
},
- "time": "2022-01-25T10:17:35+00:00"
+ "time": "2023-10-30T13:38:26+00:00"
},
{
"name": "phpbench/dom",
@@ -673,49 +727,50 @@
},
{
"name": "phpbench/phpbench",
- "version": "1.2.14",
+ "version": "1.2.15",
"source": {
"type": "git",
"url": "https://github.com/phpbench/phpbench.git",
- "reference": "edbd1b7ecf704eb01f7a2bcd1b8aa8c189f9fa4e"
+ "reference": "f7000319695cfad04a57fc64bf7ef7abdf4c437c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpbench/phpbench/zipball/edbd1b7ecf704eb01f7a2bcd1b8aa8c189f9fa4e",
- "reference": "edbd1b7ecf704eb01f7a2bcd1b8aa8c189f9fa4e",
+ "url": "https://api.github.com/repos/phpbench/phpbench/zipball/f7000319695cfad04a57fc64bf7ef7abdf4c437c",
+ "reference": "f7000319695cfad04a57fc64bf7ef7abdf4c437c",
"shasum": ""
},
"require": {
- "doctrine/annotations": "^1.13 || ^2.0",
+ "doctrine/annotations": "^2.0",
"ext-dom": "*",
"ext-json": "*",
"ext-pcre": "*",
"ext-reflection": "*",
"ext-spl": "*",
"ext-tokenizer": "*",
- "php": "^7.4 || ^8.0",
+ "php": "^8.1",
"phpbench/container": "^2.1",
"phpbench/dom": "~0.3.3",
"psr/log": "^1.1 || ^2.0 || ^3.0",
"seld/jsonlint": "^1.1",
- "symfony/console": "^4.2 || ^5.0 || ^6.0",
- "symfony/filesystem": "^4.2 || ^5.0 || ^6.0",
- "symfony/finder": "^4.2 || ^5.0 || ^6.0",
- "symfony/options-resolver": "^4.2 || ^5.0 || ^6.0",
- "symfony/process": "^4.2 || ^5.0 || ^6.0",
+ "symfony/console": "^4.2 || ^5.0 || ^6.0 || ^7.0",
+ "symfony/filesystem": "^4.2 || ^5.0 || ^6.0 || ^7.0",
+ "symfony/finder": "^4.2 || ^5.0 || ^6.0 || ^7.0",
+ "symfony/options-resolver": "^4.2 || ^5.0 || ^6.0 || ^7.0",
+ "symfony/process": "^4.2 || ^5.0 || ^6.0 || ^7.0",
"webmozart/glob": "^4.6"
},
"require-dev": {
"dantleech/invoke": "^2.0",
"friendsofphp/php-cs-fixer": "^3.0",
"jangregor/phpstan-prophecy": "^1.0",
- "phpspec/prophecy": "^1.12",
+ "phpspec/prophecy": "dev-master",
"phpstan/extension-installer": "^1.1",
"phpstan/phpstan": "^1.0",
"phpstan/phpstan-phpunit": "^1.0",
- "phpunit/phpunit": "^9.0",
- "symfony/error-handler": "^5.2 || ^6.0",
- "symfony/var-dumper": "^4.0 || ^5.0 || ^6.0"
+ "phpunit/phpunit": "^10.0",
+ "rector/rector": "^0.18.10",
+ "symfony/error-handler": "^5.2 || ^6.0 || ^7.0",
+ "symfony/var-dumper": "^4.0 || ^5.0 || ^6.0 || ^7.0"
},
"suggest": {
"ext-xdebug": "For Xdebug profiling extension."
@@ -749,9 +804,16 @@
}
],
"description": "PHP Benchmarking Framework",
+ "keywords": [
+ "benchmarking",
+ "optimization",
+ "performance",
+ "profiling",
+ "testing"
+ ],
"support": {
"issues": "https://github.com/phpbench/phpbench/issues",
- "source": "https://github.com/phpbench/phpbench/tree/1.2.14"
+ "source": "https://github.com/phpbench/phpbench/tree/1.2.15"
},
"funding": [
{
@@ -759,7 +821,7 @@
"type": "github"
}
],
- "time": "2023-07-09T09:16:08+00:00"
+ "time": "2023-11-29T12:21:11+00:00"
},
{
"name": "phpstan/extension-installer",
@@ -807,16 +869,16 @@
},
{
"name": "phpstan/phpdoc-parser",
- "version": "1.24.1",
+ "version": "1.25.0",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpdoc-parser.git",
- "reference": "9f854d275c2dbf84915a5c0ec9a2d17d2cd86b01"
+ "reference": "bd84b629c8de41aa2ae82c067c955e06f1b00240"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/9f854d275c2dbf84915a5c0ec9a2d17d2cd86b01",
- "reference": "9f854d275c2dbf84915a5c0ec9a2d17d2cd86b01",
+ "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/bd84b629c8de41aa2ae82c067c955e06f1b00240",
+ "reference": "bd84b629c8de41aa2ae82c067c955e06f1b00240",
"shasum": ""
},
"require": {
@@ -848,22 +910,22 @@
"description": "PHPDoc parser with support for nullable, intersection and generic types",
"support": {
"issues": "https://github.com/phpstan/phpdoc-parser/issues",
- "source": "https://github.com/phpstan/phpdoc-parser/tree/1.24.1"
+ "source": "https://github.com/phpstan/phpdoc-parser/tree/1.25.0"
},
- "time": "2023-09-18T12:18:02+00:00"
+ "time": "2024-01-04T17:06:16+00:00"
},
{
"name": "phpstan/phpstan",
- "version": "1.10.35",
+ "version": "1.10.57",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan.git",
- "reference": "e730e5facb75ffe09dfb229795e8c01a459f26c3"
+ "reference": "1627b1d03446904aaa77593f370c5201d2ecc34e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpstan/phpstan/zipball/e730e5facb75ffe09dfb229795e8c01a459f26c3",
- "reference": "e730e5facb75ffe09dfb229795e8c01a459f26c3",
+ "url": "https://api.github.com/repos/phpstan/phpstan/zipball/1627b1d03446904aaa77593f370c5201d2ecc34e",
+ "reference": "1627b1d03446904aaa77593f370c5201d2ecc34e",
"shasum": ""
},
"require": {
@@ -912,7 +974,7 @@
"type": "tidelift"
}
],
- "time": "2023-09-19T15:27:56+00:00"
+ "time": "2024-01-24T11:51:34+00:00"
},
{
"name": "phpstan/phpstan-deprecation-rules",
@@ -964,16 +1026,16 @@
},
{
"name": "phpstan/phpstan-phpunit",
- "version": "1.3.14",
+ "version": "1.3.15",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan-phpunit.git",
- "reference": "614acc10c522e319639bf38b0698a4a566665f04"
+ "reference": "70ecacc64fe8090d8d2a33db5a51fe8e88acd93a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/614acc10c522e319639bf38b0698a4a566665f04",
- "reference": "614acc10c522e319639bf38b0698a4a566665f04",
+ "url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/70ecacc64fe8090d8d2a33db5a51fe8e88acd93a",
+ "reference": "70ecacc64fe8090d8d2a33db5a51fe8e88acd93a",
"shasum": ""
},
"require": {
@@ -1010,27 +1072,27 @@
"description": "PHPUnit extensions and rules for PHPStan",
"support": {
"issues": "https://github.com/phpstan/phpstan-phpunit/issues",
- "source": "https://github.com/phpstan/phpstan-phpunit/tree/1.3.14"
+ "source": "https://github.com/phpstan/phpstan-phpunit/tree/1.3.15"
},
- "time": "2023-08-25T09:46:39+00:00"
+ "time": "2023-10-09T18:58:39+00:00"
},
{
"name": "phpstan/phpstan-strict-rules",
- "version": "1.5.1",
+ "version": "1.5.2",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan-strict-rules.git",
- "reference": "b21c03d4f6f3a446e4311155f4be9d65048218e6"
+ "reference": "7a50e9662ee9f3942e4aaaf3d603653f60282542"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/b21c03d4f6f3a446e4311155f4be9d65048218e6",
- "reference": "b21c03d4f6f3a446e4311155f4be9d65048218e6",
+ "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/7a50e9662ee9f3942e4aaaf3d603653f60282542",
+ "reference": "7a50e9662ee9f3942e4aaaf3d603653f60282542",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0",
- "phpstan/phpstan": "^1.10"
+ "phpstan/phpstan": "^1.10.34"
},
"require-dev": {
"nikic/php-parser": "^4.13.0",
@@ -1059,29 +1121,29 @@
"description": "Extra strict and opinionated rules for PHPStan",
"support": {
"issues": "https://github.com/phpstan/phpstan-strict-rules/issues",
- "source": "https://github.com/phpstan/phpstan-strict-rules/tree/1.5.1"
+ "source": "https://github.com/phpstan/phpstan-strict-rules/tree/1.5.2"
},
- "time": "2023-03-29T14:47:40+00:00"
+ "time": "2023-10-30T14:35:06+00:00"
},
{
"name": "phpunit/php-code-coverage",
- "version": "10.1.6",
+ "version": "10.1.11",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
- "reference": "56f33548fe522c8d82da7ff3824b42829d324364"
+ "reference": "78c3b7625965c2513ee96569a4dbb62601784145"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/56f33548fe522c8d82da7ff3824b42829d324364",
- "reference": "56f33548fe522c8d82da7ff3824b42829d324364",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/78c3b7625965c2513ee96569a4dbb62601784145",
+ "reference": "78c3b7625965c2513ee96569a4dbb62601784145",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-libxml": "*",
"ext-xmlwriter": "*",
- "nikic/php-parser": "^4.15",
+ "nikic/php-parser": "^4.18 || ^5.0",
"php": ">=8.1",
"phpunit/php-file-iterator": "^4.0",
"phpunit/php-text-template": "^3.0",
@@ -1131,7 +1193,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
"security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy",
- "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.6"
+ "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.11"
},
"funding": [
{
@@ -1139,7 +1201,7 @@
"type": "github"
}
],
- "time": "2023-09-19T04:59:03+00:00"
+ "time": "2023-12-21T15:38:30+00:00"
},
{
"name": "phpunit/php-file-iterator",
@@ -1386,16 +1448,16 @@
},
{
"name": "phpunit/phpunit",
- "version": "10.3.5",
+ "version": "10.5.9",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
- "reference": "747c3b2038f1139e3dcd9886a3f5a948648b7503"
+ "reference": "0bd663704f0165c9e76fe4f06ffa6a1ca727fdbe"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/747c3b2038f1139e3dcd9886a3f5a948648b7503",
- "reference": "747c3b2038f1139e3dcd9886a3f5a948648b7503",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/0bd663704f0165c9e76fe4f06ffa6a1ca727fdbe",
+ "reference": "0bd663704f0165c9e76fe4f06ffa6a1ca727fdbe",
"shasum": ""
},
"require": {
@@ -1435,7 +1497,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "10.3-dev"
+ "dev-main": "10.5-dev"
}
},
"autoload": {
@@ -1467,7 +1529,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
- "source": "https://github.com/sebastianbergmann/phpunit/tree/10.3.5"
+ "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.9"
},
"funding": [
{
@@ -1483,7 +1545,7 @@
"type": "tidelift"
}
],
- "time": "2023-09-19T05:42:37+00:00"
+ "time": "2024-01-22T14:35:40+00:00"
},
{
"name": "psr/cache",
@@ -1883,20 +1945,20 @@
},
{
"name": "sebastian/complexity",
- "version": "3.0.1",
+ "version": "3.2.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/complexity.git",
- "reference": "c70b73893e10757af9c6a48929fa6a333b56a97a"
+ "reference": "68ff824baeae169ec9f2137158ee529584553799"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/c70b73893e10757af9c6a48929fa6a333b56a97a",
- "reference": "c70b73893e10757af9c6a48929fa6a333b56a97a",
+ "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/68ff824baeae169ec9f2137158ee529584553799",
+ "reference": "68ff824baeae169ec9f2137158ee529584553799",
"shasum": ""
},
"require": {
- "nikic/php-parser": "^4.10",
+ "nikic/php-parser": "^4.18 || ^5.0",
"php": ">=8.1"
},
"require-dev": {
@@ -1905,7 +1967,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "3.0-dev"
+ "dev-main": "3.2-dev"
}
},
"autoload": {
@@ -1929,7 +1991,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/complexity/issues",
"security": "https://github.com/sebastianbergmann/complexity/security/policy",
- "source": "https://github.com/sebastianbergmann/complexity/tree/3.0.1"
+ "source": "https://github.com/sebastianbergmann/complexity/tree/3.2.0"
},
"funding": [
{
@@ -1937,20 +1999,20 @@
"type": "github"
}
],
- "time": "2023-08-31T09:55:53+00:00"
+ "time": "2023-12-21T08:37:17+00:00"
},
{
"name": "sebastian/diff",
- "version": "5.0.3",
+ "version": "5.1.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/diff.git",
- "reference": "912dc2fbe3e3c1e7873313cc801b100b6c68c87b"
+ "reference": "fbf413a49e54f6b9b17e12d900ac7f6101591b7f"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/912dc2fbe3e3c1e7873313cc801b100b6c68c87b",
- "reference": "912dc2fbe3e3c1e7873313cc801b100b6c68c87b",
+ "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/fbf413a49e54f6b9b17e12d900ac7f6101591b7f",
+ "reference": "fbf413a49e54f6b9b17e12d900ac7f6101591b7f",
"shasum": ""
},
"require": {
@@ -1963,7 +2025,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "5.0-dev"
+ "dev-main": "5.1-dev"
}
},
"autoload": {
@@ -1996,7 +2058,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/diff/issues",
"security": "https://github.com/sebastianbergmann/diff/security/policy",
- "source": "https://github.com/sebastianbergmann/diff/tree/5.0.3"
+ "source": "https://github.com/sebastianbergmann/diff/tree/5.1.0"
},
"funding": [
{
@@ -2004,7 +2066,7 @@
"type": "github"
}
],
- "time": "2023-05-01T07:48:21+00:00"
+ "time": "2023-12-22T10:55:06+00:00"
},
{
"name": "sebastian/environment",
@@ -2072,16 +2134,16 @@
},
{
"name": "sebastian/exporter",
- "version": "5.1.0",
+ "version": "5.1.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/exporter.git",
- "reference": "c3fa8483f9539b190f7cd4bfc4a07631dd1df344"
+ "reference": "64f51654862e0f5e318db7e9dcc2292c63cdbddc"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/c3fa8483f9539b190f7cd4bfc4a07631dd1df344",
- "reference": "c3fa8483f9539b190f7cd4bfc4a07631dd1df344",
+ "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/64f51654862e0f5e318db7e9dcc2292c63cdbddc",
+ "reference": "64f51654862e0f5e318db7e9dcc2292c63cdbddc",
"shasum": ""
},
"require": {
@@ -2095,7 +2157,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "5.0-dev"
+ "dev-main": "5.1-dev"
}
},
"autoload": {
@@ -2138,7 +2200,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/exporter/issues",
"security": "https://github.com/sebastianbergmann/exporter/security/policy",
- "source": "https://github.com/sebastianbergmann/exporter/tree/5.1.0"
+ "source": "https://github.com/sebastianbergmann/exporter/tree/5.1.1"
},
"funding": [
{
@@ -2146,7 +2208,7 @@
"type": "github"
}
],
- "time": "2023-09-18T07:15:37+00:00"
+ "time": "2023-09-24T13:22:09+00:00"
},
{
"name": "sebastian/global-state",
@@ -2212,20 +2274,20 @@
},
{
"name": "sebastian/lines-of-code",
- "version": "2.0.1",
+ "version": "2.0.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/lines-of-code.git",
- "reference": "649e40d279e243d985aa8fb6e74dd5bb28dc185d"
+ "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/649e40d279e243d985aa8fb6e74dd5bb28dc185d",
- "reference": "649e40d279e243d985aa8fb6e74dd5bb28dc185d",
+ "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/856e7f6a75a84e339195d48c556f23be2ebf75d0",
+ "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0",
"shasum": ""
},
"require": {
- "nikic/php-parser": "^4.10",
+ "nikic/php-parser": "^4.18 || ^5.0",
"php": ">=8.1"
},
"require-dev": {
@@ -2258,7 +2320,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/lines-of-code/issues",
"security": "https://github.com/sebastianbergmann/lines-of-code/security/policy",
- "source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0.1"
+ "source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0.2"
},
"funding": [
{
@@ -2266,7 +2328,7 @@
"type": "github"
}
],
- "time": "2023-08-31T09:25:50+00:00"
+ "time": "2023-12-21T08:38:20+00:00"
},
{
"name": "sebastian/object-enumerator",
@@ -2554,16 +2616,16 @@
},
{
"name": "seld/jsonlint",
- "version": "1.10.0",
+ "version": "1.10.1",
"source": {
"type": "git",
"url": "https://github.com/Seldaek/jsonlint.git",
- "reference": "594fd6462aad8ecee0b45ca5045acea4776667f1"
+ "reference": "76d449a358ece77d6f1d6331c68453e657172202"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/594fd6462aad8ecee0b45ca5045acea4776667f1",
- "reference": "594fd6462aad8ecee0b45ca5045acea4776667f1",
+ "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/76d449a358ece77d6f1d6331c68453e657172202",
+ "reference": "76d449a358ece77d6f1d6331c68453e657172202",
"shasum": ""
},
"require": {
@@ -2590,7 +2652,7 @@
{
"name": "Jordi Boggiano",
"email": "j.boggiano@seld.be",
- "homepage": "http://seld.be"
+ "homepage": "https://seld.be"
}
],
"description": "JSON Linter",
@@ -2602,7 +2664,7 @@
],
"support": {
"issues": "https://github.com/Seldaek/jsonlint/issues",
- "source": "https://github.com/Seldaek/jsonlint/tree/1.10.0"
+ "source": "https://github.com/Seldaek/jsonlint/tree/1.10.1"
},
"funding": [
{
@@ -2614,36 +2676,36 @@
"type": "tidelift"
}
],
- "time": "2023-05-11T13:16:46+00:00"
+ "time": "2023-12-18T13:03:25+00:00"
},
{
"name": "slevomat/coding-standard",
- "version": "8.13.4",
+ "version": "8.14.1",
"source": {
"type": "git",
"url": "https://github.com/slevomat/coding-standard.git",
- "reference": "4b2af2fb17773656d02fbfb5d18024ebd19fe322"
+ "reference": "fea1fd6f137cc84f9cba0ae30d549615dbc6a926"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/4b2af2fb17773656d02fbfb5d18024ebd19fe322",
- "reference": "4b2af2fb17773656d02fbfb5d18024ebd19fe322",
+ "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/fea1fd6f137cc84f9cba0ae30d549615dbc6a926",
+ "reference": "fea1fd6f137cc84f9cba0ae30d549615dbc6a926",
"shasum": ""
},
"require": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7 || ^1.0",
"php": "^7.2 || ^8.0",
- "phpstan/phpdoc-parser": "^1.23.0",
+ "phpstan/phpdoc-parser": "^1.23.1",
"squizlabs/php_codesniffer": "^3.7.1"
},
"require-dev": {
"phing/phing": "2.17.4",
"php-parallel-lint/php-parallel-lint": "1.3.2",
- "phpstan/phpstan": "1.10.26",
- "phpstan/phpstan-deprecation-rules": "1.1.3",
- "phpstan/phpstan-phpunit": "1.3.13",
+ "phpstan/phpstan": "1.10.37",
+ "phpstan/phpstan-deprecation-rules": "1.1.4",
+ "phpstan/phpstan-phpunit": "1.3.14",
"phpstan/phpstan-strict-rules": "1.5.1",
- "phpunit/phpunit": "7.5.20|8.5.21|9.6.8|10.2.6"
+ "phpunit/phpunit": "8.5.21|9.6.8|10.3.5"
},
"type": "phpcodesniffer-standard",
"extra": {
@@ -2667,7 +2729,7 @@
],
"support": {
"issues": "https://github.com/slevomat/coding-standard/issues",
- "source": "https://github.com/slevomat/coding-standard/tree/8.13.4"
+ "source": "https://github.com/slevomat/coding-standard/tree/8.14.1"
},
"funding": [
{
@@ -2679,20 +2741,20 @@
"type": "tidelift"
}
],
- "time": "2023-07-25T10:28:55+00:00"
+ "time": "2023-10-08T07:28:08+00:00"
},
{
"name": "squizlabs/php_codesniffer",
- "version": "3.7.2",
+ "version": "3.8.1",
"source": {
"type": "git",
- "url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
- "reference": "ed8e00df0a83aa96acf703f8c2979ff33341f879"
+ "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git",
+ "reference": "14f5fff1e64118595db5408e946f3a22c75807f7"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/ed8e00df0a83aa96acf703f8c2979ff33341f879",
- "reference": "ed8e00df0a83aa96acf703f8c2979ff33341f879",
+ "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/14f5fff1e64118595db5408e946f3a22c75807f7",
+ "reference": "14f5fff1e64118595db5408e946f3a22c75807f7",
"shasum": ""
},
"require": {
@@ -2702,11 +2764,11 @@
"php": ">=5.4.0"
},
"require-dev": {
- "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0"
+ "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.3.4"
},
"bin": [
- "bin/phpcs",
- "bin/phpcbf"
+ "bin/phpcbf",
+ "bin/phpcs"
],
"type": "library",
"extra": {
@@ -2721,35 +2783,58 @@
"authors": [
{
"name": "Greg Sherwood",
- "role": "lead"
+ "role": "Former lead"
+ },
+ {
+ "name": "Juliette Reinders Folmer",
+ "role": "Current lead"
+ },
+ {
+ "name": "Contributors",
+ "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer/graphs/contributors"
}
],
"description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.",
- "homepage": "https://github.com/squizlabs/PHP_CodeSniffer",
+ "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer",
"keywords": [
"phpcs",
"standards",
"static analysis"
],
"support": {
- "issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues",
- "source": "https://github.com/squizlabs/PHP_CodeSniffer",
- "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki"
+ "issues": "https://github.com/PHPCSStandards/PHP_CodeSniffer/issues",
+ "security": "https://github.com/PHPCSStandards/PHP_CodeSniffer/security/policy",
+ "source": "https://github.com/PHPCSStandards/PHP_CodeSniffer",
+ "wiki": "https://github.com/PHPCSStandards/PHP_CodeSniffer/wiki"
},
- "time": "2023-02-22T23:07:41+00:00"
+ "funding": [
+ {
+ "url": "https://github.com/PHPCSStandards",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/jrfnl",
+ "type": "github"
+ },
+ {
+ "url": "https://opencollective.com/php_codesniffer",
+ "type": "open_collective"
+ }
+ ],
+ "time": "2024-01-11T20:47:48+00:00"
},
{
"name": "symfony/console",
- "version": "v6.3.4",
+ "version": "v6.4.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
- "reference": "eca495f2ee845130855ddf1cf18460c38966c8b6"
+ "reference": "0254811a143e6bc6c8deea08b589a7e68a37f625"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/console/zipball/eca495f2ee845130855ddf1cf18460c38966c8b6",
- "reference": "eca495f2ee845130855ddf1cf18460c38966c8b6",
+ "url": "https://api.github.com/repos/symfony/console/zipball/0254811a143e6bc6c8deea08b589a7e68a37f625",
+ "reference": "0254811a143e6bc6c8deea08b589a7e68a37f625",
"shasum": ""
},
"require": {
@@ -2757,7 +2842,7 @@
"symfony/deprecation-contracts": "^2.5|^3",
"symfony/polyfill-mbstring": "~1.0",
"symfony/service-contracts": "^2.5|^3",
- "symfony/string": "^5.4|^6.0"
+ "symfony/string": "^5.4|^6.0|^7.0"
},
"conflict": {
"symfony/dependency-injection": "<5.4",
@@ -2771,12 +2856,16 @@
},
"require-dev": {
"psr/log": "^1|^2|^3",
- "symfony/config": "^5.4|^6.0",
- "symfony/dependency-injection": "^5.4|^6.0",
- "symfony/event-dispatcher": "^5.4|^6.0",
- "symfony/lock": "^5.4|^6.0",
- "symfony/process": "^5.4|^6.0",
- "symfony/var-dumper": "^5.4|^6.0"
+ "symfony/config": "^5.4|^6.0|^7.0",
+ "symfony/dependency-injection": "^5.4|^6.0|^7.0",
+ "symfony/event-dispatcher": "^5.4|^6.0|^7.0",
+ "symfony/http-foundation": "^6.4|^7.0",
+ "symfony/http-kernel": "^6.4|^7.0",
+ "symfony/lock": "^5.4|^6.0|^7.0",
+ "symfony/messenger": "^5.4|^6.0|^7.0",
+ "symfony/process": "^5.4|^6.0|^7.0",
+ "symfony/stopwatch": "^5.4|^6.0|^7.0",
+ "symfony/var-dumper": "^5.4|^6.0|^7.0"
},
"type": "library",
"autoload": {
@@ -2810,7 +2899,7 @@
"terminal"
],
"support": {
- "source": "https://github.com/symfony/console/tree/v6.3.4"
+ "source": "https://github.com/symfony/console/tree/v6.4.2"
},
"funding": [
{
@@ -2826,11 +2915,11 @@
"type": "tidelift"
}
],
- "time": "2023-08-16T10:10:12+00:00"
+ "time": "2023-12-10T16:15:48+00:00"
},
{
"name": "symfony/deprecation-contracts",
- "version": "v3.3.0",
+ "version": "v3.4.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/deprecation-contracts.git",
@@ -2877,7 +2966,7 @@
"description": "A generic function and convention to trigger deprecation notices",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/deprecation-contracts/tree/v3.3.0"
+ "source": "https://github.com/symfony/deprecation-contracts/tree/v3.4.0"
},
"funding": [
{
@@ -2897,16 +2986,16 @@
},
{
"name": "symfony/filesystem",
- "version": "v6.3.1",
+ "version": "v6.4.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
- "reference": "edd36776956f2a6fcf577edb5b05eb0e3bdc52ae"
+ "reference": "952a8cb588c3bc6ce76f6023000fb932f16a6e59"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/filesystem/zipball/edd36776956f2a6fcf577edb5b05eb0e3bdc52ae",
- "reference": "edd36776956f2a6fcf577edb5b05eb0e3bdc52ae",
+ "url": "https://api.github.com/repos/symfony/filesystem/zipball/952a8cb588c3bc6ce76f6023000fb932f16a6e59",
+ "reference": "952a8cb588c3bc6ce76f6023000fb932f16a6e59",
"shasum": ""
},
"require": {
@@ -2940,7 +3029,7 @@
"description": "Provides basic utilities for the filesystem",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/filesystem/tree/v6.3.1"
+ "source": "https://github.com/symfony/filesystem/tree/v6.4.0"
},
"funding": [
{
@@ -2956,27 +3045,27 @@
"type": "tidelift"
}
],
- "time": "2023-06-01T08:30:39+00:00"
+ "time": "2023-07-26T17:27:13+00:00"
},
{
"name": "symfony/finder",
- "version": "v6.3.3",
+ "version": "v6.4.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
- "reference": "9915db259f67d21eefee768c1abcf1cc61b1fc9e"
+ "reference": "11d736e97f116ac375a81f96e662911a34cd50ce"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/finder/zipball/9915db259f67d21eefee768c1abcf1cc61b1fc9e",
- "reference": "9915db259f67d21eefee768c1abcf1cc61b1fc9e",
+ "url": "https://api.github.com/repos/symfony/finder/zipball/11d736e97f116ac375a81f96e662911a34cd50ce",
+ "reference": "11d736e97f116ac375a81f96e662911a34cd50ce",
"shasum": ""
},
"require": {
"php": ">=8.1"
},
"require-dev": {
- "symfony/filesystem": "^6.0"
+ "symfony/filesystem": "^6.0|^7.0"
},
"type": "library",
"autoload": {
@@ -3004,7 +3093,7 @@
"description": "Finds files and directories via an intuitive fluent interface",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/finder/tree/v6.3.3"
+ "source": "https://github.com/symfony/finder/tree/v6.4.0"
},
"funding": [
{
@@ -3020,20 +3109,20 @@
"type": "tidelift"
}
],
- "time": "2023-07-31T08:31:44+00:00"
+ "time": "2023-10-31T17:30:12+00:00"
},
{
"name": "symfony/options-resolver",
- "version": "v6.3.0",
+ "version": "v6.4.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/options-resolver.git",
- "reference": "a10f19f5198d589d5c33333cffe98dc9820332dd"
+ "reference": "22301f0e7fdeaacc14318928612dee79be99860e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/options-resolver/zipball/a10f19f5198d589d5c33333cffe98dc9820332dd",
- "reference": "a10f19f5198d589d5c33333cffe98dc9820332dd",
+ "url": "https://api.github.com/repos/symfony/options-resolver/zipball/22301f0e7fdeaacc14318928612dee79be99860e",
+ "reference": "22301f0e7fdeaacc14318928612dee79be99860e",
"shasum": ""
},
"require": {
@@ -3071,7 +3160,7 @@
"options"
],
"support": {
- "source": "https://github.com/symfony/options-resolver/tree/v6.3.0"
+ "source": "https://github.com/symfony/options-resolver/tree/v6.4.0"
},
"funding": [
{
@@ -3087,7 +3176,7 @@
"type": "tidelift"
}
],
- "time": "2023-05-12T14:21:09+00:00"
+ "time": "2023-08-08T10:16:24+00:00"
},
{
"name": "symfony/polyfill-ctype",
@@ -3421,16 +3510,16 @@
},
{
"name": "symfony/process",
- "version": "v6.3.4",
+ "version": "v6.4.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
- "reference": "0b5c29118f2e980d455d2e34a5659f4579847c54"
+ "reference": "c4b1ef0bc80533d87a2e969806172f1c2a980241"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/process/zipball/0b5c29118f2e980d455d2e34a5659f4579847c54",
- "reference": "0b5c29118f2e980d455d2e34a5659f4579847c54",
+ "url": "https://api.github.com/repos/symfony/process/zipball/c4b1ef0bc80533d87a2e969806172f1c2a980241",
+ "reference": "c4b1ef0bc80533d87a2e969806172f1c2a980241",
"shasum": ""
},
"require": {
@@ -3462,7 +3551,7 @@
"description": "Executes commands in sub-processes",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/process/tree/v6.3.4"
+ "source": "https://github.com/symfony/process/tree/v6.4.2"
},
"funding": [
{
@@ -3478,25 +3567,25 @@
"type": "tidelift"
}
],
- "time": "2023-08-07T10:39:22+00:00"
+ "time": "2023-12-22T16:42:54+00:00"
},
{
"name": "symfony/service-contracts",
- "version": "v3.3.0",
+ "version": "v3.4.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/service-contracts.git",
- "reference": "40da9cc13ec349d9e4966ce18b5fbcd724ab10a4"
+ "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/service-contracts/zipball/40da9cc13ec349d9e4966ce18b5fbcd724ab10a4",
- "reference": "40da9cc13ec349d9e4966ce18b5fbcd724ab10a4",
+ "url": "https://api.github.com/repos/symfony/service-contracts/zipball/fe07cbc8d837f60caf7018068e350cc5163681a0",
+ "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0",
"shasum": ""
},
"require": {
"php": ">=8.1",
- "psr/container": "^2.0"
+ "psr/container": "^1.1|^2.0"
},
"conflict": {
"ext-psr": "<1.1|>=2"
@@ -3544,7 +3633,7 @@
"standards"
],
"support": {
- "source": "https://github.com/symfony/service-contracts/tree/v3.3.0"
+ "source": "https://github.com/symfony/service-contracts/tree/v3.4.1"
},
"funding": [
{
@@ -3560,20 +3649,20 @@
"type": "tidelift"
}
],
- "time": "2023-05-23T14:45:45+00:00"
+ "time": "2023-12-26T14:02:43+00:00"
},
{
"name": "symfony/string",
- "version": "v6.3.2",
+ "version": "v6.4.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/string.git",
- "reference": "53d1a83225002635bca3482fcbf963001313fb68"
+ "reference": "7cb80bc10bfcdf6b5492741c0b9357dac66940bc"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/string/zipball/53d1a83225002635bca3482fcbf963001313fb68",
- "reference": "53d1a83225002635bca3482fcbf963001313fb68",
+ "url": "https://api.github.com/repos/symfony/string/zipball/7cb80bc10bfcdf6b5492741c0b9357dac66940bc",
+ "reference": "7cb80bc10bfcdf6b5492741c0b9357dac66940bc",
"shasum": ""
},
"require": {
@@ -3587,11 +3676,11 @@
"symfony/translation-contracts": "<2.5"
},
"require-dev": {
- "symfony/error-handler": "^5.4|^6.0",
- "symfony/http-client": "^5.4|^6.0",
- "symfony/intl": "^6.2",
+ "symfony/error-handler": "^5.4|^6.0|^7.0",
+ "symfony/http-client": "^5.4|^6.0|^7.0",
+ "symfony/intl": "^6.2|^7.0",
"symfony/translation-contracts": "^2.5|^3.0",
- "symfony/var-exporter": "^5.4|^6.0"
+ "symfony/var-exporter": "^5.4|^6.0|^7.0"
},
"type": "library",
"autoload": {
@@ -3630,7 +3719,7 @@
"utf8"
],
"support": {
- "source": "https://github.com/symfony/string/tree/v6.3.2"
+ "source": "https://github.com/symfony/string/tree/v6.4.2"
},
"funding": [
{
@@ -3646,20 +3735,20 @@
"type": "tidelift"
}
],
- "time": "2023-07-05T08:41:27+00:00"
+ "time": "2023-12-10T16:15:48+00:00"
},
{
"name": "theseer/tokenizer",
- "version": "1.2.1",
+ "version": "1.2.2",
"source": {
"type": "git",
"url": "https://github.com/theseer/tokenizer.git",
- "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e"
+ "reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e",
- "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e",
+ "url": "https://api.github.com/repos/theseer/tokenizer/zipball/b2ad5003ca10d4ee50a12da31de12a5774ba6b96",
+ "reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96",
"shasum": ""
},
"require": {
@@ -3688,7 +3777,7 @@
"description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
"support": {
"issues": "https://github.com/theseer/tokenizer/issues",
- "source": "https://github.com/theseer/tokenizer/tree/1.2.1"
+ "source": "https://github.com/theseer/tokenizer/tree/1.2.2"
},
"funding": [
{
@@ -3696,7 +3785,7 @@
"type": "github"
}
],
- "time": "2021-07-28T10:34:58+00:00"
+ "time": "2023-11-20T00:12:19+00:00"
},
{
"name": "webmozart/glob",
@@ -3757,5 +3846,5 @@
"php": ">=8.1.0"
},
"platform-dev": [],
- "plugin-api-version": "2.3.0"
+ "plugin-api-version": "2.6.0"
}
diff --git a/phpcs.xml.dist b/phpcs.xml.dist
index 96f56b1..8450d0a 100644
--- a/phpcs.xml.dist
+++ b/phpcs.xml.dist
@@ -23,6 +23,7 @@
src/Dispatcher/Result/*
+ test/FastRouteTest.php
diff --git a/phpstan.neon.dist b/phpstan.neon.dist
index 93fc433..4778302 100644
--- a/phpstan.neon.dist
+++ b/phpstan.neon.dist
@@ -4,3 +4,7 @@ parameters:
- benchmark
- src
- test
+
+ ignoreErrors:
+ # We're marking this as deprecated, there's no point in alerting ourselves here...
+ - '#Call to deprecated function FastRoute\\(cached|simple)Dispatcher.*#'
diff --git a/src/Cache/ApcuCache.php b/src/Cache/Psr16Cache.php
similarity index 50%
rename from src/Cache/ApcuCache.php
rename to src/Cache/Psr16Cache.php
index 3bdc36f..5e2cad7 100644
--- a/src/Cache/ApcuCache.php
+++ b/src/Cache/Psr16Cache.php
@@ -4,25 +4,30 @@
namespace FastRoute\Cache;
use FastRoute\Cache;
+use FastRoute\DataGenerator;
+use Psr\SimpleCache\CacheInterface;
-use function apcu_add;
-use function apcu_fetch;
use function is_array;
-final class ApcuCache implements Cache
+/** @phpstan-import-type RouteData from DataGenerator */
+final class Psr16Cache implements Cache
{
- /** @inheritdoc */
+ public function __construct(private readonly CacheInterface $cache)
+ {
+ }
+
+ /** @inheritDoc */
public function get(string $key, callable $loader): array
{
- $result = apcu_fetch($key, $itemFetched);
+ $result = $this->cache->get($key);
- if ($itemFetched && is_array($result)) {
+ if (is_array($result)) {
// @phpstan-ignore-next-line because we won´t be able to validate the array shape in a performant way
return $result;
}
$data = $loader();
- apcu_add($key, $data);
+ $this->cache->set($key, $data);
return $data;
}
diff --git a/src/DataGenerator/RegexBasedAbstract.php b/src/DataGenerator/RegexBasedAbstract.php
index dbf0c3a..8e0c21b 100644
--- a/src/DataGenerator/RegexBasedAbstract.php
+++ b/src/DataGenerator/RegexBasedAbstract.php
@@ -112,7 +112,7 @@ private function addStaticRoute(string $httpMethod, array $routeData, mixed $han
/** @param array $routeData */
private function addVariableRoute(string $httpMethod, array $routeData, mixed $handler): void
{
- $route = Route::fromParsedRoute($httpMethod, $routeData, $handler);
+ $route = new Route($httpMethod, $routeData, $handler);
$regex = $route->regex;
if (isset($this->methodToRegexToRoutesMap[$httpMethod][$regex])) {
diff --git a/src/Dispatcher.php b/src/Dispatcher.php
index 0d90122..6a62c3a 100644
--- a/src/Dispatcher.php
+++ b/src/Dispatcher.php
@@ -16,7 +16,7 @@ interface Dispatcher
/**
* Dispatches against the provided HTTP method verb and URI.
*
- * Returns array with one of the following formats:
+ * Returns an object that also has an array shape with one of the following formats:
*
* [self::NOT_FOUND]
* [self::METHOD_NOT_ALLOWED, ['GET', 'OTHER_ALLOWED_METHODS']]
diff --git a/src/FastRoute.php b/src/FastRoute.php
new file mode 100644
index 0000000..6048e17
--- /dev/null
+++ b/src/FastRoute.php
@@ -0,0 +1,128 @@
+ $routeParser
+ * @param class-string $dataGenerator
+ * @param class-string $dispatcher
+ * @param class-string $routeCollector
+ * @param Cache|class-string|null $cacheDriver
+ */
+ private function __construct(
+ private readonly Closure $routeDefinitionCallback,
+ private readonly string $routeParser,
+ private readonly string $dataGenerator,
+ private readonly string $dispatcher,
+ private readonly string $routeCollector,
+ private readonly Cache|string|null $cacheDriver,
+ ) {
+ }
+
+ /** @param Closure(RouteCollector):void $routeDefinitionCallback */
+ public static function recommendedSettings(Closure $routeDefinitionCallback): self
+ {
+ return new self(
+ $routeDefinitionCallback,
+ RouteParser\Std::class,
+ DataGenerator\MarkBased::class,
+ Dispatcher\MarkBased::class,
+ RouteCollector::class,
+ FileCache::class,
+ );
+ }
+
+ public function disableCache(): self
+ {
+ return new self(
+ $this->routeDefinitionCallback,
+ $this->routeParser,
+ $this->dataGenerator,
+ $this->dispatcher,
+ $this->routeCollector,
+ null,
+ );
+ }
+
+ /** @param Cache|class-string $driver */
+ public function withCache(Cache|string $driver): self
+ {
+ return new self(
+ $this->routeDefinitionCallback,
+ $this->routeParser,
+ $this->dataGenerator,
+ $this->dispatcher,
+ $this->routeCollector,
+ $driver,
+ );
+ }
+
+ public function useCharCountDispatcher(): self
+ {
+ return $this->useCustomDispatcher(DataGenerator\CharCountBased::class, Dispatcher\CharCountBased::class);
+ }
+
+ public function useGroupCountDispatcher(): self
+ {
+ return $this->useCustomDispatcher(DataGenerator\GroupCountBased::class, Dispatcher\GroupCountBased::class);
+ }
+
+ public function useGroupPosDispatcher(): self
+ {
+ return $this->useCustomDispatcher(DataGenerator\GroupPosBased::class, Dispatcher\GroupPosBased::class);
+ }
+
+ public function useMarkDispatcher(): self
+ {
+ return $this->useCustomDispatcher(DataGenerator\MarkBased::class, Dispatcher\MarkBased::class);
+ }
+
+ /**
+ * @param class-string $dataGenerator
+ * @param class-string $dispatcher
+ */
+ public function useCustomDispatcher(string $dataGenerator, string $dispatcher): self
+ {
+ return new self(
+ $this->routeDefinitionCallback,
+ $this->routeParser,
+ $dataGenerator,
+ $dispatcher,
+ $this->routeCollector,
+ $this->cacheDriver,
+ );
+ }
+
+ public function dispatcher(string $cacheKey): Dispatcher
+ {
+ $loader = function (): array {
+ $collector = new $this->routeCollector(
+ new $this->routeParser(),
+ new $this->dataGenerator(),
+ );
+
+ ($this->routeDefinitionCallback)($collector);
+
+ return $collector->getData();
+ };
+
+ if ($this->cacheDriver === null) {
+ return new $this->dispatcher($loader());
+ }
+
+ $cache = is_string($this->cacheDriver)
+ ? new $this->cacheDriver()
+ : $this->cacheDriver;
+
+ return new $this->dispatcher($cache->get($cacheKey, $loader));
+ }
+}
diff --git a/src/Route.php b/src/Route.php
index 8e72198..19a54cb 100644
--- a/src/Route.php
+++ b/src/Route.php
@@ -9,26 +9,18 @@
class Route
{
- /** @param array $variables */
- public function __construct(
- public string $httpMethod,
- public mixed $handler,
- public string $regex,
- public array $variables,
- ) {
- }
+ public readonly string $regex;
- /** @param array $routeData */
- public static function fromParsedRoute(string $httpMethod, array $routeData, mixed $handler): self
- {
- [$regex, $variables] = self::extractRegex($routeData);
+ /** @var array $variables */
+ public readonly array $variables;
- return new self(
- $httpMethod,
- $handler,
- $regex,
- $variables,
- );
+ /** @param array $routeData */
+ public function __construct(
+ public readonly string $httpMethod,
+ array $routeData,
+ public readonly mixed $handler,
+ ) {
+ [$this->regex, $this->variables] = self::extractRegex($routeData);
}
/**
diff --git a/src/RouteCollector.php b/src/RouteCollector.php
index 2b80bc2..0a1ebd9 100644
--- a/src/RouteCollector.php
+++ b/src/RouteCollector.php
@@ -8,8 +8,10 @@ class RouteCollector
{
protected string $currentGroupPrefix = '';
- public function __construct(protected RouteParser $routeParser, protected DataGenerator $dataGenerator)
- {
+ public function __construct(
+ protected readonly RouteParser $routeParser,
+ protected readonly DataGenerator $dataGenerator,
+ ) {
}
/**
diff --git a/src/functions.php b/src/functions.php
index ba0890b..a619ed5 100644
--- a/src/functions.php
+++ b/src/functions.php
@@ -6,12 +6,18 @@
use FastRoute\Cache\FileCache;
use LogicException;
-use function array_key_exists;
use function function_exists;
use function is_string;
if (! function_exists('FastRoute\simpleDispatcher')) {
- /** @param array{routeParser?: class-string, dataGenerator?: class-string, dispatcher?: class-string, routeCollector?: class-string, cacheDisabled?: bool, cacheKey?: string, cacheDriver?: class-string|Cache} $options */
+ /**
+ * @deprecated since v2.0 and will be removed in v3.0
+ *
+ * @see FastRoute::recommendedSettings()
+ * @see FastRoute::disableCache()
+ *
+ * @param array{routeParser?: class-string, dataGenerator?: class-string, dispatcher?: class-string, routeCollector?: class-string, cacheDisabled?: bool, cacheKey?: string, cacheFile?: string, cacheDriver?: class-string|Cache} $options
+ */
function simpleDispatcher(callable $routeDefinitionCallback, array $options = []): Dispatcher
{
return \FastRoute\cachedDispatcher(
@@ -20,7 +26,13 @@ function simpleDispatcher(callable $routeDefinitionCallback, array $options = []
);
}
- /** @param array{routeParser?: class-string, dataGenerator?: class-string, dispatcher?: class-string, routeCollector?: class-string, cacheDisabled?: bool, cacheKey?: string, cacheDriver?: class-string|Cache} $options */
+ /**
+ * @deprecated since v2.0 and will be removed in v3.0
+ *
+ * @see FastRoute::recommendedSettings()
+ *
+ * @param array{routeParser?: class-string, dataGenerator?: class-string, dispatcher?: class-string, routeCollector?: class-string, cacheDisabled?: bool, cacheKey?: string, cacheFile?: string, cacheDriver?: class-string|Cache} $options
+ */
function cachedDispatcher(callable $routeDefinitionCallback, array $options = []): Dispatcher
{
$options += [
@@ -47,7 +59,9 @@ function cachedDispatcher(callable $routeDefinitionCallback, array $options = []
return new $options['dispatcher']($loader());
}
- if (! array_key_exists('cacheKey', $options)) {
+ $cacheKey = $options['cacheKey'] ?? $options['cacheFile'] ?? null;
+
+ if ($cacheKey === null) {
throw new LogicException('Must specify "cacheKey" option');
}
@@ -57,6 +71,6 @@ function cachedDispatcher(callable $routeDefinitionCallback, array $options = []
$cache = new $cache();
}
- return new $options['dispatcher']($cache->get($options['cacheKey'], $loader));
+ return new $options['dispatcher']($cache->get($cacheKey, $loader));
}
}
diff --git a/test/Cache/Psr16CacheTest.php b/test/Cache/Psr16CacheTest.php
new file mode 100644
index 0000000..ed9ff81
--- /dev/null
+++ b/test/Cache/Psr16CacheTest.php
@@ -0,0 +1,55 @@
+ ['/' => 'test']], []];
+
+ $adapter = new Psr16Cache($this->createDummyCache($data));
+ $result = $adapter->get('test', static fn () => $generatedData);
+
+ self::assertSame($generatedData, $result);
+ self::assertSame($generatedData, $data['test']);
+
+ // Try again, now with a different callback
+ $result = $adapter->get('test', static fn () => [['POST' => ['/' => 'test']], []]);
+
+ self::assertSame($generatedData, $result);
+ }
+
+ /** @param array $data */
+ private function createDummyCache(array &$data): CacheInterface
+ {
+ $cache = $this->createMock(CacheInterface::class);
+
+ $cache->method('get')
+ ->willReturnCallback(
+ static function (string $key, mixed $default) use (&$data): mixed {
+ return $data[$key] ?? $default;
+ },
+ );
+
+ $cache->method('set')
+ ->willReturnCallback(
+ static function (string $key, mixed $value) use (&$data): bool {
+ $data[$key] = $value;
+
+ return true;
+ },
+ );
+
+ return $cache;
+ }
+}
diff --git a/test/Dispatcher/CachingTest.php b/test/Dispatcher/CachingTest.php
index 6c233ed..e91b7da 100644
--- a/test/Dispatcher/CachingTest.php
+++ b/test/Dispatcher/CachingTest.php
@@ -27,21 +27,23 @@ public function warmUpCache(): void
$this->createDispatcher();
}
- public function createDispatcher(): Dispatcher
+ public function createDispatcher(string $optionName = 'cacheKey'): Dispatcher
{
return cachedDispatcher(
static function (RouteCollector $collector): void {
$collector->get('/testing', ['test']);
$collector->get('/admin/{page}', ['admin-page']);
},
- ['cacheKey' => self::CACHE_FILE],
+ // @phpstan-ignore-next-line we're doing dynamic configuration...
+ [$optionName => self::CACHE_FILE],
);
}
#[PHPUnit\Test]
- public function dynamicRouteShouldMatch(): void
+ #[PHPUnit\DataProvider('possiblePropertyNames')]
+ public function dynamicRouteShouldMatch(string $propertyName): void
{
- $dispatcher = $this->createDispatcher();
+ $dispatcher = $this->createDispatcher($propertyName);
$result = $dispatcher->dispatch('GET', '/admin/1234');
self::assertSame(Dispatcher::FOUND, $result[0]);
@@ -50,9 +52,10 @@ public function dynamicRouteShouldMatch(): void
}
#[PHPUnit\Test]
- public function staticRouteShouldMatch(): void
+ #[PHPUnit\DataProvider('possiblePropertyNames')]
+ public function staticRouteShouldMatch(string $propertyName): void
{
- $dispatcher = $this->createDispatcher();
+ $dispatcher = $this->createDispatcher($propertyName);
$result = $dispatcher->dispatch('GET', '/testing');
self::assertSame(Dispatcher::FOUND, $result[0]);
@@ -60,11 +63,19 @@ public function staticRouteShouldMatch(): void
}
#[PHPUnit\Test]
- public function missingRoutShouldNotBeFound(): void
+ #[PHPUnit\DataProvider('possiblePropertyNames')]
+ public function missingRoutShouldNotBeFound(string $propertyName): void
{
- $dispatcher = $this->createDispatcher();
+ $dispatcher = $this->createDispatcher($propertyName);
$result = $dispatcher->dispatch('GET', '/testing2');
self::assertSame(Dispatcher::NOT_FOUND, $result[0]);
}
+
+ /** @return iterable */
+ public static function possiblePropertyNames(): iterable
+ {
+ yield 'v1' => ['cacheFile'];
+ yield 'v2' => ['cacheKey'];
+ }
}
diff --git a/test/FastRouteTest.php b/test/FastRouteTest.php
new file mode 100644
index 0000000..e103d3b
--- /dev/null
+++ b/test/FastRouteTest.php
@@ -0,0 +1,100 @@
+disableCache()
+ ->dispatcher('test');
+
+ self::assertInstanceOf(Dispatcher\MarkBased::class, $dispatcher);
+ }
+
+ #[PHPUnit\Test]
+ public function canBeConfiguredToUseCharCountDispatcher(): void
+ {
+ $dispatcher = FastRoute::recommendedSettings(self::routes(...))
+ ->disableCache()
+ ->useCharCountDispatcher()
+ ->dispatcher('test');
+
+ self::assertInstanceOf(Dispatcher\CharCountBased::class, $dispatcher);
+ }
+
+ #[PHPUnit\Test]
+ public function canBeConfiguredToUseGroupPosDispatcher(): void
+ {
+ $dispatcher = FastRoute::recommendedSettings(self::routes(...))
+ ->disableCache()
+ ->useGroupPosDispatcher()
+ ->dispatcher('test');
+
+ self::assertInstanceOf(Dispatcher\GroupPosBased::class, $dispatcher);
+ }
+
+ #[PHPUnit\Test]
+ public function canBeConfiguredToUseGroupCountDispatcher(): void
+ {
+ $dispatcher = FastRoute::recommendedSettings(self::routes(...))
+ ->disableCache()
+ ->useGroupCountDispatcher()
+ ->dispatcher('test');
+
+ self::assertInstanceOf(Dispatcher\GroupCountBased::class, $dispatcher);
+ }
+
+ #[PHPUnit\Test]
+ public function canBeConfiguredToUseMarkDispatcher(): void
+ {
+ $dispatcher = FastRoute::recommendedSettings(self::routes(...))
+ ->disableCache()
+ ->useCharCountDispatcher()
+ ->useMarkDispatcher()
+ ->dispatcher('test');
+
+ self::assertInstanceOf(Dispatcher\MarkBased::class, $dispatcher);
+ }
+
+ #[PHPUnit\Test]
+ public function canBeConfiguredToUseCustomCache(): void
+ {
+ $cache = new class () implements Cache {
+ /** @inheritDoc */
+ public function get(string $key, callable $loader): array
+ {
+ if ($key === 'test') {
+ return [['GET' => ['/' => 'test2']], []];
+ }
+
+ throw new RuntimeException('This dummy implementation is not meant for other cases');
+ }
+ };
+
+ $dispatcher = FastRoute::recommendedSettings(self::routes(...))
+ ->withCache($cache)
+ ->dispatcher('test');
+
+ $result = $dispatcher->dispatch('GET', '/');
+
+ self::assertInstanceOf(Dispatcher\Result\Matched::class, $result);
+ self::assertSame('test2', $result->handler); // should use data from cache, not from loader
+ }
+
+ private static function routes(RouteCollector $collector): void
+ {
+ $collector->get('/', 'test');
+ }
+}