'
+ )
+ );
label.appendChild($.render(''));
}
@@ -311,7 +319,12 @@ define(["../notjQuery", "../vendor/Sortable", "BaseInput"], function ($, Sortabl
}
onButtonClick(event) {
- if (! this.hasSyntaxError()) {
+ // Exchange terms only when an Enter key is pressed while not in the term input.
+ // If the pointerType is not empty, the click event is triggered by clicking the Submit button in the form,
+ // and the default submit event should not be prevented.
+ // The below solution does not work if the click event is triggered by pressing Space while on the Submit button.
+ // In which case the Submit button needs to be clicked again to trigger the form submission.
+ if (! this.hasSyntaxError() && event.pointerType === '') {
let addedTerms = this.exchangeTerm();
if (Object.keys(addedTerms).length) {
this.togglePlaceholder();
diff --git a/composer.lock b/composer.lock
index 2d119b7..3c16199 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,30 +4,29 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "20d4022bc196691807f55d4a47c06474",
+ "content-hash": "7a1692c86b6fc70eaaf43c4bee3673aa",
"packages": [
{
"name": "brick/math",
- "version": "0.9.3",
+ "version": "0.14.0",
"source": {
"type": "git",
"url": "https://github.com/brick/math.git",
- "reference": "ca57d18f028f84f777b2168cd1911b0dee2343ae"
+ "reference": "113a8ee2656b882d4c3164fa31aa6e12cbb7aaa2"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/brick/math/zipball/ca57d18f028f84f777b2168cd1911b0dee2343ae",
- "reference": "ca57d18f028f84f777b2168cd1911b0dee2343ae",
+ "url": "https://api.github.com/repos/brick/math/zipball/113a8ee2656b882d4c3164fa31aa6e12cbb7aaa2",
+ "reference": "113a8ee2656b882d4c3164fa31aa6e12cbb7aaa2",
"shasum": ""
},
"require": {
- "ext-json": "*",
- "php": "^7.1 || ^8.0"
+ "php": "^8.2"
},
"require-dev": {
"php-coveralls/php-coveralls": "^2.2",
- "phpunit/phpunit": "^7.5.15 || ^8.5 || ^9.0",
- "vimeo/psalm": "4.9.2"
+ "phpstan/phpstan": "2.1.22",
+ "phpunit/phpunit": "^11.5"
},
"type": "library",
"autoload": {
@@ -47,101 +46,56 @@
"arithmetic",
"bigdecimal",
"bignum",
+ "bignumber",
"brick",
- "math"
+ "decimal",
+ "integer",
+ "math",
+ "mathematics",
+ "rational"
],
"support": {
"issues": "https://github.com/brick/math/issues",
- "source": "https://github.com/brick/math/tree/0.9.3"
+ "source": "https://github.com/brick/math/tree/0.14.0"
},
"funding": [
{
"url": "https://github.com/BenMorel",
"type": "github"
- },
- {
- "url": "https://tidelift.com/funding/github/packagist/brick/math",
- "type": "tidelift"
}
],
- "time": "2021-08-15T20:50:18+00:00"
- },
- {
- "name": "cweagans/composer-patches",
- "version": "1.7.3",
- "source": {
- "type": "git",
- "url": "https://github.com/cweagans/composer-patches.git",
- "reference": "e190d4466fe2b103a55467dfa83fc2fecfcaf2db"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/cweagans/composer-patches/zipball/e190d4466fe2b103a55467dfa83fc2fecfcaf2db",
- "reference": "e190d4466fe2b103a55467dfa83fc2fecfcaf2db",
- "shasum": ""
- },
- "require": {
- "composer-plugin-api": "^1.0 || ^2.0",
- "php": ">=5.3.0"
- },
- "require-dev": {
- "composer/composer": "~1.0 || ~2.0",
- "phpunit/phpunit": "~4.6"
- },
- "type": "composer-plugin",
- "extra": {
- "class": "cweagans\\Composer\\Patches"
- },
- "autoload": {
- "psr-4": {
- "cweagans\\Composer\\": "src"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Cameron Eagans",
- "email": "me@cweagans.net"
- }
- ],
- "description": "Provides a way to patch Composer packages.",
- "support": {
- "issues": "https://github.com/cweagans/composer-patches/issues",
- "source": "https://github.com/cweagans/composer-patches/tree/1.7.3"
- },
- "time": "2022-12-20T22:53:13+00:00"
+ "time": "2025-08-29T12:40:03+00:00"
},
{
"name": "doctrine/collections",
- "version": "1.8.0",
+ "version": "2.3.0",
"source": {
"type": "git",
"url": "https://github.com/doctrine/collections.git",
- "reference": "2b44dd4cbca8b5744327de78bafef5945c7e7b5e"
+ "reference": "2eb07e5953eed811ce1b309a7478a3b236f2273d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/doctrine/collections/zipball/2b44dd4cbca8b5744327de78bafef5945c7e7b5e",
- "reference": "2b44dd4cbca8b5744327de78bafef5945c7e7b5e",
+ "url": "https://api.github.com/repos/doctrine/collections/zipball/2eb07e5953eed811ce1b309a7478a3b236f2273d",
+ "reference": "2eb07e5953eed811ce1b309a7478a3b236f2273d",
"shasum": ""
},
"require": {
- "doctrine/deprecations": "^0.5.3 || ^1",
- "php": "^7.1.3 || ^8.0"
+ "doctrine/deprecations": "^1",
+ "php": "^8.1",
+ "symfony/polyfill-php84": "^1.30"
},
"require-dev": {
- "doctrine/coding-standard": "^9.0 || ^10.0",
- "phpstan/phpstan": "^1.4.8",
- "phpunit/phpunit": "^7.5 || ^8.5 || ^9.1.5",
- "vimeo/psalm": "^4.22"
+ "doctrine/coding-standard": "^12",
+ "ext-json": "*",
+ "phpstan/phpstan": "^1.8",
+ "phpstan/phpstan-phpunit": "^1.0",
+ "phpunit/phpunit": "^10.5"
},
"type": "library",
"autoload": {
"psr-4": {
- "Doctrine\\Common\\Collections\\": "lib/Doctrine/Common/Collections"
+ "Doctrine\\Common\\Collections\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
@@ -180,9 +134,23 @@
],
"support": {
"issues": "https://github.com/doctrine/collections/issues",
- "source": "https://github.com/doctrine/collections/tree/1.8.0"
+ "source": "https://github.com/doctrine/collections/tree/2.3.0"
},
- "time": "2022-09-01T20:12:10+00:00"
+ "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%2Fcollections",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2025-03-22T10:17:19+00:00"
},
{
"name": "doctrine/deprecations",
@@ -507,16 +475,16 @@
},
{
"name": "ipl/html",
- "version": "v0.8.2",
+ "version": "dev-main",
"source": {
"type": "git",
"url": "https://github.com/Icinga/ipl-html.git",
- "reference": "e18bdf11abca5e477100e2c7d190ef5f424d0d98"
+ "reference": "9f698b99cab6bd0ab36ea56022c53ac89a7150fc"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Icinga/ipl-html/zipball/e18bdf11abca5e477100e2c7d190ef5f424d0d98",
- "reference": "e18bdf11abca5e477100e2c7d190ef5f424d0d98",
+ "url": "https://api.github.com/repos/Icinga/ipl-html/zipball/9f698b99cab6bd0ab36ea56022c53ac89a7150fc",
+ "reference": "9f698b99cab6bd0ab36ea56022c53ac89a7150fc",
"shasum": ""
},
"require": {
@@ -524,13 +492,15 @@
"guzzlehttp/psr7": "^2.5",
"ipl/stdlib": ">=0.12.0",
"ipl/validator": ">=0.5.0",
- "php": ">=7.2",
+ "php": ">=8.2",
"psr/http-message": "^1.1"
},
"require-dev": {
+ "ext-dom": "*",
"ipl/stdlib": "dev-main",
"ipl/validator": "dev-main"
},
+ "default-branch": true,
"type": "library",
"autoload": {
"psr-4": {
@@ -548,22 +518,22 @@
],
"support": {
"issues": "https://github.com/Icinga/ipl-html/issues",
- "source": "https://github.com/Icinga/ipl-html/tree/v0.8.2"
+ "source": "https://github.com/Icinga/ipl-html/tree/main"
},
- "time": "2025-05-21T09:00:03+00:00"
+ "time": "2025-10-02T13:04:12+00:00"
},
{
"name": "ipl/i18n",
- "version": "v0.2.2",
+ "version": "dev-main",
"source": {
"type": "git",
"url": "https://github.com/Icinga/ipl-i18n.git",
- "reference": "a2b6109c5a93f86ce46d5dc351dbe75e8502cf8c"
+ "reference": "692c33cf46fb8a4511da613dbf97c6216c345cc5"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Icinga/ipl-i18n/zipball/a2b6109c5a93f86ce46d5dc351dbe75e8502cf8c",
- "reference": "a2b6109c5a93f86ce46d5dc351dbe75e8502cf8c",
+ "url": "https://api.github.com/repos/Icinga/ipl-i18n/zipball/692c33cf46fb8a4511da613dbf97c6216c345cc5",
+ "reference": "692c33cf46fb8a4511da613dbf97c6216c345cc5",
"shasum": ""
},
"require": {
@@ -575,6 +545,7 @@
"require-dev": {
"ipl/stdlib": "dev-main"
},
+ "default-branch": true,
"type": "library",
"autoload": {
"files": [
@@ -599,35 +570,36 @@
],
"support": {
"issues": "https://github.com/Icinga/ipl-i18n/issues",
- "source": "https://github.com/Icinga/ipl-i18n/tree/v0.2.2"
+ "source": "https://github.com/Icinga/ipl-i18n/tree/main"
},
- "time": "2024-04-08T12:28:47+00:00"
+ "time": "2025-06-12T11:57:41+00:00"
},
{
"name": "ipl/orm",
- "version": "v0.6.3",
+ "version": "dev-main",
"source": {
"type": "git",
"url": "https://github.com/Icinga/ipl-orm.git",
- "reference": "a775a2745764a8dc7f28618cce69dcd7bbfd7915"
+ "reference": "2a0b72d21e2444501a940975f869297998c6cdfe"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Icinga/ipl-orm/zipball/a775a2745764a8dc7f28618cce69dcd7bbfd7915",
- "reference": "a775a2745764a8dc7f28618cce69dcd7bbfd7915",
+ "url": "https://api.github.com/repos/Icinga/ipl-orm/zipball/2a0b72d21e2444501a940975f869297998c6cdfe",
+ "reference": "2a0b72d21e2444501a940975f869297998c6cdfe",
"shasum": ""
},
"require": {
"ext-pdo": "*",
"ipl/sql": ">=0.7.0",
"ipl/stdlib": ">=0.12.0",
- "php": ">=7.2"
+ "php": ">=8.2"
},
"require-dev": {
"ext-pdo_sqlite": "*",
"ipl/sql": "dev-main",
"ipl/stdlib": "dev-main"
},
+ "default-branch": true,
"type": "library",
"autoload": {
"psr-4": {
@@ -647,22 +619,22 @@
],
"support": {
"issues": "https://github.com/Icinga/ipl-orm/issues",
- "source": "https://github.com/Icinga/ipl-orm/tree/v0.6.3"
+ "source": "https://github.com/Icinga/ipl-orm/tree/main"
},
- "time": "2025-06-12T11:57:55+00:00"
+ "time": "2025-10-15T11:46:22+00:00"
},
{
"name": "ipl/scheduler",
- "version": "v0.1.2",
+ "version": "dev-main",
"source": {
"type": "git",
"url": "https://github.com/Icinga/ipl-scheduler.git",
- "reference": "6119afdea07b1390bd728e350e0d80b26ec8d6ba"
+ "reference": "3e4e8db870239d213b1dfd5d79d59fc7784b4c34"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Icinga/ipl-scheduler/zipball/6119afdea07b1390bd728e350e0d80b26ec8d6ba",
- "reference": "6119afdea07b1390bd728e350e0d80b26ec8d6ba",
+ "url": "https://api.github.com/repos/Icinga/ipl-scheduler/zipball/3e4e8db870239d213b1dfd5d79d59fc7784b4c34",
+ "reference": "3e4e8db870239d213b1dfd5d79d59fc7784b4c34",
"shasum": ""
},
"require": {
@@ -682,6 +654,7 @@
"suggest": {
"ext-ev": "Improves performance, efficiency and avoids system limitations. Highly recommended! (See https://www.php.net/manual/en/intro.ev.php for details)"
},
+ "default-branch": true,
"type": "library",
"autoload": {
"files": [
@@ -705,22 +678,22 @@
],
"support": {
"issues": "https://github.com/Icinga/ipl-scheduler/issues",
- "source": "https://github.com/Icinga/ipl-scheduler/tree/v0.1.2"
+ "source": "https://github.com/Icinga/ipl-scheduler/tree/main"
},
- "time": "2023-08-30T14:14:23+00:00"
+ "time": "2025-06-12T11:58:09+00:00"
},
{
"name": "ipl/sql",
- "version": "v0.7.1",
+ "version": "dev-main",
"source": {
"type": "git",
"url": "https://github.com/Icinga/ipl-sql.git",
- "reference": "e80f1b712c4b96099b0bf9096e6efe317a165e3b"
+ "reference": "6f4258c4e3b20655db57d248e26edf7b54c04729"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Icinga/ipl-sql/zipball/e80f1b712c4b96099b0bf9096e6efe317a165e3b",
- "reference": "e80f1b712c4b96099b0bf9096e6efe317a165e3b",
+ "url": "https://api.github.com/repos/Icinga/ipl-sql/zipball/6f4258c4e3b20655db57d248e26edf7b54c04729",
+ "reference": "6f4258c4e3b20655db57d248e26edf7b54c04729",
"shasum": ""
},
"require": {
@@ -731,6 +704,7 @@
"require-dev": {
"ipl/stdlib": "dev-main"
},
+ "default-branch": true,
"type": "library",
"autoload": {
"psr-4": {
@@ -749,22 +723,22 @@
],
"support": {
"issues": "https://github.com/Icinga/ipl-sql/issues",
- "source": "https://github.com/Icinga/ipl-sql/tree/v0.7.1"
+ "source": "https://github.com/Icinga/ipl-sql/tree/main"
},
- "time": "2024-06-25T09:55:43+00:00"
+ "time": "2025-10-08T07:03:38+00:00"
},
{
"name": "ipl/stdlib",
- "version": "v0.14.0",
+ "version": "dev-main",
"source": {
"type": "git",
"url": "https://github.com/Icinga/ipl-stdlib.git",
- "reference": "bf5fc8f40b86bd90337db6f3be389be2a93fa64a"
+ "reference": "9b7a903fbfc341da59f242149ac333594e4a6fa3"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Icinga/ipl-stdlib/zipball/bf5fc8f40b86bd90337db6f3be389be2a93fa64a",
- "reference": "bf5fc8f40b86bd90337db6f3be389be2a93fa64a",
+ "url": "https://api.github.com/repos/Icinga/ipl-stdlib/zipball/9b7a903fbfc341da59f242149ac333594e4a6fa3",
+ "reference": "9b7a903fbfc341da59f242149ac333594e4a6fa3",
"shasum": ""
},
"require": {
@@ -772,6 +746,7 @@
"ext-openssl": "*",
"php": ">=7.2"
},
+ "default-branch": true,
"type": "library",
"autoload": {
"files": [
@@ -788,22 +763,22 @@
"description": "ipl Standard Library",
"support": {
"issues": "https://github.com/Icinga/ipl-stdlib/issues",
- "source": "https://github.com/Icinga/ipl-stdlib/tree/v0.14.0"
+ "source": "https://github.com/Icinga/ipl-stdlib/tree/main"
},
- "time": "2024-04-22T08:47:08+00:00"
+ "time": "2025-09-05T12:07:21+00:00"
},
{
"name": "ipl/validator",
- "version": "v0.5.0",
+ "version": "dev-main",
"source": {
"type": "git",
"url": "https://github.com/Icinga/ipl-validator.git",
- "reference": "a601fae0ed330e63cea50e4a2a6659ca1ad97bde"
+ "reference": "eac5c6c114d8007db5c24ae159fe6f55e89a946b"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Icinga/ipl-validator/zipball/a601fae0ed330e63cea50e4a2a6659ca1ad97bde",
- "reference": "a601fae0ed330e63cea50e4a2a6659ca1ad97bde",
+ "url": "https://api.github.com/repos/Icinga/ipl-validator/zipball/eac5c6c114d8007db5c24ae159fe6f55e89a946b",
+ "reference": "eac5c6c114d8007db5c24ae159fe6f55e89a946b",
"shasum": ""
},
"require": {
@@ -812,11 +787,14 @@
"ipl/i18n": ">=0.2.0",
"ipl/stdlib": ">=0.12.0",
"php": ">=7.2",
- "psr/http-message": "~1.0"
+ "psr/http-message": "^1.1"
},
"require-dev": {
- "guzzlehttp/psr7": "^1"
+ "guzzlehttp/psr7": "^1",
+ "ipl/i18n": "dev-main",
+ "ipl/stdlib": "dev-main"
},
+ "default-branch": true,
"type": "library",
"autoload": {
"psr-4": {
@@ -831,33 +809,33 @@
"homepage": "https://github.com/Icinga/ipl-validator",
"support": {
"issues": "https://github.com/Icinga/ipl-validator/issues",
- "source": "https://github.com/Icinga/ipl-validator/tree/v0.5.0"
+ "source": "https://github.com/Icinga/ipl-validator/tree/main"
},
- "time": "2023-03-21T15:59:00+00:00"
+ "time": "2025-06-12T11:59:27+00:00"
},
{
"name": "ipl/web",
- "version": "v0.10.2",
+ "version": "dev-main",
"source": {
"type": "git",
"url": "https://github.com/Icinga/ipl-web.git",
- "reference": "a3d134c0d67aa51a9b186519c76e718603fda835"
+ "reference": "1fdd7aa977f8da19e17cc4535b023c0760aa442a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Icinga/ipl-web/zipball/a3d134c0d67aa51a9b186519c76e718603fda835",
- "reference": "a3d134c0d67aa51a9b186519c76e718603fda835",
+ "url": "https://api.github.com/repos/Icinga/ipl-web/zipball/1fdd7aa977f8da19e17cc4535b023c0760aa442a",
+ "reference": "1fdd7aa977f8da19e17cc4535b023c0760aa442a",
"shasum": ""
},
"require": {
"ext-json": "*",
"fortawesome/font-awesome": "^6",
- "ipl/html": ">=0.8.0",
+ "ipl/html": ">=0.9.0",
"ipl/i18n": ">=0.2.0",
"ipl/orm": ">=0.5.2",
"ipl/scheduler": ">=0.1.0",
"ipl/stdlib": ">=0.13.0",
- "php": ">=7.2",
+ "php": ">=8.2",
"psr/http-message": "^1.1",
"wikimedia/less.php": "^3.2.1"
},
@@ -869,6 +847,7 @@
"ipl/stdlib": "dev-main",
"shardj/zf1-future": "^1.22"
},
+ "default-branch": true,
"type": "library",
"autoload": {
"psr-4": {
@@ -886,9 +865,9 @@
],
"support": {
"issues": "https://github.com/Icinga/ipl-web/issues",
- "source": "https://github.com/Icinga/ipl-web/tree/v0.10.2"
+ "source": "https://github.com/Icinga/ipl-web/tree/main"
},
- "time": "2025-03-26T07:49:58+00:00"
+ "time": "2025-10-17T12:11:07+00:00"
},
{
"name": "psr/http-factory",
@@ -1094,40 +1073,49 @@
},
{
"name": "ramsey/collection",
- "version": "1.1.4",
+ "version": "2.1.1",
"source": {
"type": "git",
"url": "https://github.com/ramsey/collection.git",
- "reference": "ab2237657ad99667a5143e32ba2683c8029563d4"
+ "reference": "344572933ad0181accbf4ba763e85a0306a8c5e2"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/ramsey/collection/zipball/ab2237657ad99667a5143e32ba2683c8029563d4",
- "reference": "ab2237657ad99667a5143e32ba2683c8029563d4",
+ "url": "https://api.github.com/repos/ramsey/collection/zipball/344572933ad0181accbf4ba763e85a0306a8c5e2",
+ "reference": "344572933ad0181accbf4ba763e85a0306a8c5e2",
"shasum": ""
},
"require": {
- "php": "^7.2 || ^8"
+ "php": "^8.1"
},
"require-dev": {
- "captainhook/captainhook": "^5.3",
- "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
- "ergebnis/composer-normalize": "^2.6",
- "fakerphp/faker": "^1.5",
- "hamcrest/hamcrest-php": "^2",
- "jangregor/phpstan-prophecy": "^0.8",
- "mockery/mockery": "^1.3",
- "phpstan/extension-installer": "^1",
- "phpstan/phpstan": "^0.12.32",
- "phpstan/phpstan-mockery": "^0.12.5",
- "phpstan/phpstan-phpunit": "^0.12.11",
- "phpunit/phpunit": "^8.5 || ^9",
- "psy/psysh": "^0.10.4",
- "slevomat/coding-standard": "^6.3",
- "squizlabs/php_codesniffer": "^3.5",
- "vimeo/psalm": "^4.4"
+ "captainhook/plugin-composer": "^5.3",
+ "ergebnis/composer-normalize": "^2.45",
+ "fakerphp/faker": "^1.24",
+ "hamcrest/hamcrest-php": "^2.0",
+ "jangregor/phpstan-prophecy": "^2.1",
+ "mockery/mockery": "^1.6",
+ "php-parallel-lint/php-console-highlighter": "^1.0",
+ "php-parallel-lint/php-parallel-lint": "^1.4",
+ "phpspec/prophecy-phpunit": "^2.3",
+ "phpstan/extension-installer": "^1.4",
+ "phpstan/phpstan": "^2.1",
+ "phpstan/phpstan-mockery": "^2.0",
+ "phpstan/phpstan-phpunit": "^2.0",
+ "phpunit/phpunit": "^10.5",
+ "ramsey/coding-standard": "^2.3",
+ "ramsey/conventional-commits": "^1.6",
+ "roave/security-advisories": "dev-latest"
},
"type": "library",
+ "extra": {
+ "captainhook": {
+ "force-install": true
+ },
+ "ramsey/conventional-commits": {
+ "configFile": "conventional-commits.json"
+ }
+ },
"autoload": {
"psr-4": {
"Ramsey\\Collection\\": "src/"
@@ -1144,7 +1132,7 @@
"homepage": "https://benramsey.com"
}
],
- "description": "A PHP 7.2+ library for representing and manipulating collections.",
+ "description": "A PHP library for representing and manipulating collections.",
"keywords": [
"array",
"collection",
@@ -1155,70 +1143,53 @@
],
"support": {
"issues": "https://github.com/ramsey/collection/issues",
- "source": "https://github.com/ramsey/collection/tree/1.1.4"
+ "source": "https://github.com/ramsey/collection/tree/2.1.1"
},
- "funding": [
- {
- "url": "https://github.com/ramsey",
- "type": "github"
- },
- {
- "url": "https://tidelift.com/funding/github/packagist/ramsey/collection",
- "type": "tidelift"
- }
- ],
- "time": "2021-07-30T00:58:27+00:00"
+ "time": "2025-03-22T05:38:12+00:00"
},
{
"name": "ramsey/uuid",
- "version": "4.2.3",
+ "version": "4.9.1",
"source": {
"type": "git",
"url": "https://github.com/ramsey/uuid.git",
- "reference": "fc9bb7fb5388691fd7373cd44dcb4d63bbcf24df"
+ "reference": "81f941f6f729b1e3ceea61d9d014f8b6c6800440"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/ramsey/uuid/zipball/fc9bb7fb5388691fd7373cd44dcb4d63bbcf24df",
- "reference": "fc9bb7fb5388691fd7373cd44dcb4d63bbcf24df",
+ "url": "https://api.github.com/repos/ramsey/uuid/zipball/81f941f6f729b1e3ceea61d9d014f8b6c6800440",
+ "reference": "81f941f6f729b1e3ceea61d9d014f8b6c6800440",
"shasum": ""
},
"require": {
- "brick/math": "^0.8 || ^0.9",
- "ext-json": "*",
- "php": "^7.2 || ^8.0",
- "ramsey/collection": "^1.0",
- "symfony/polyfill-ctype": "^1.8",
- "symfony/polyfill-php80": "^1.14"
+ "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12 || ^0.13 || ^0.14",
+ "php": "^8.0",
+ "ramsey/collection": "^1.2 || ^2.0"
},
"replace": {
"rhumsaa/uuid": "self.version"
},
"require-dev": {
- "captainhook/captainhook": "^5.10",
+ "captainhook/captainhook": "^5.25",
"captainhook/plugin-composer": "^5.3",
- "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
- "doctrine/annotations": "^1.8",
- "ergebnis/composer-normalize": "^2.15",
- "mockery/mockery": "^1.3",
- "moontoast/math": "^1.1",
+ "dealerdirect/phpcodesniffer-composer-installer": "^1.0",
+ "ergebnis/composer-normalize": "^2.47",
+ "mockery/mockery": "^1.6",
"paragonie/random-lib": "^2",
- "php-mock/php-mock": "^2.2",
- "php-mock/php-mock-mockery": "^1.3",
- "php-parallel-lint/php-parallel-lint": "^1.1",
- "phpbench/phpbench": "^1.0",
- "phpstan/extension-installer": "^1.0",
- "phpstan/phpstan": "^0.12",
- "phpstan/phpstan-mockery": "^0.12",
- "phpstan/phpstan-phpunit": "^0.12",
- "phpunit/phpunit": "^8.5 || ^9",
- "slevomat/coding-standard": "^7.0",
- "squizlabs/php_codesniffer": "^3.5",
- "vimeo/psalm": "^4.9"
+ "php-mock/php-mock": "^2.6",
+ "php-mock/php-mock-mockery": "^1.5",
+ "php-parallel-lint/php-parallel-lint": "^1.4.0",
+ "phpbench/phpbench": "^1.2.14",
+ "phpstan/extension-installer": "^1.4",
+ "phpstan/phpstan": "^2.1",
+ "phpstan/phpstan-mockery": "^2.0",
+ "phpstan/phpstan-phpunit": "^2.0",
+ "phpunit/phpunit": "^9.6",
+ "slevomat/coding-standard": "^8.18",
+ "squizlabs/php_codesniffer": "^3.13"
},
"suggest": {
"ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.",
- "ext-ctype": "Enables faster processing of character classification using ctype functions.",
"ext-gmp": "Enables faster math with arbitrary-precision integers using GMP.",
"ext-uuid": "Enables the use of PeclUuidTimeGenerator and PeclUuidRandomGenerator.",
"paragonie/random-lib": "Provides RandomLib for use with the RandomLibAdapter",
@@ -1228,9 +1199,6 @@
"extra": {
"captainhook": {
"force-install": true
- },
- "branch-alias": {
- "dev-main": "4.x-dev"
}
},
"autoload": {
@@ -1253,19 +1221,9 @@
],
"support": {
"issues": "https://github.com/ramsey/uuid/issues",
- "source": "https://github.com/ramsey/uuid/tree/4.2.3"
+ "source": "https://github.com/ramsey/uuid/tree/4.9.1"
},
- "funding": [
- {
- "url": "https://github.com/ramsey",
- "type": "github"
- },
- {
- "url": "https://tidelift.com/funding/github/packagist/ramsey/uuid",
- "type": "tidelift"
- }
- ],
- "time": "2021-09-25T23:10:38+00:00"
+ "time": "2025-09-04T20:59:21+00:00"
},
{
"name": "react/event-loop",
@@ -1471,100 +1429,17 @@
"time": "2024-12-12T15:39:24+00:00"
},
{
- "name": "symfony/polyfill-ctype",
+ "name": "symfony/polyfill-php84",
"version": "v1.33.0",
"source": {
"type": "git",
- "url": "https://github.com/symfony/polyfill-ctype.git",
- "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638"
+ "url": "https://github.com/symfony/polyfill-php84.git",
+ "reference": "d8ced4d875142b6a7426000426b8abc631d6b191"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638",
- "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638",
- "shasum": ""
- },
- "require": {
- "php": ">=7.2"
- },
- "provide": {
- "ext-ctype": "*"
- },
- "suggest": {
- "ext-ctype": "For best performance"
- },
- "type": "library",
- "extra": {
- "thanks": {
- "url": "https://github.com/symfony/polyfill",
- "name": "symfony/polyfill"
- }
- },
- "autoload": {
- "files": [
- "bootstrap.php"
- ],
- "psr-4": {
- "Symfony\\Polyfill\\Ctype\\": ""
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Gert de Pagter",
- "email": "BackEndTea@gmail.com"
- },
- {
- "name": "Symfony Community",
- "homepage": "https://symfony.com/contributors"
- }
- ],
- "description": "Symfony polyfill for ctype functions",
- "homepage": "https://symfony.com",
- "keywords": [
- "compatibility",
- "ctype",
- "polyfill",
- "portable"
- ],
- "support": {
- "source": "https://github.com/symfony/polyfill-ctype/tree/v1.33.0"
- },
- "funding": [
- {
- "url": "https://symfony.com/sponsor",
- "type": "custom"
- },
- {
- "url": "https://github.com/fabpot",
- "type": "github"
- },
- {
- "url": "https://github.com/nicolas-grekas",
- "type": "github"
- },
- {
- "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
- "type": "tidelift"
- }
- ],
- "time": "2024-09-09T11:45:10+00:00"
- },
- {
- "name": "symfony/polyfill-php80",
- "version": "v1.33.0",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/polyfill-php80.git",
- "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/0cc9dd0f17f61d8131e7df6b84bd344899fe2608",
- "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608",
+ "url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/d8ced4d875142b6a7426000426b8abc631d6b191",
+ "reference": "d8ced4d875142b6a7426000426b8abc631d6b191",
"shasum": ""
},
"require": {
@@ -1582,7 +1457,7 @@
"bootstrap.php"
],
"psr-4": {
- "Symfony\\Polyfill\\Php80\\": ""
+ "Symfony\\Polyfill\\Php84\\": ""
},
"classmap": [
"Resources/stubs"
@@ -1593,10 +1468,6 @@
"MIT"
],
"authors": [
- {
- "name": "Ion Bazan",
- "email": "ion.bazan@gmail.com"
- },
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
@@ -1606,7 +1477,7 @@
"homepage": "https://symfony.com/contributors"
}
],
- "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions",
+ "description": "Symfony polyfill backporting some PHP 8.4+ features to lower PHP versions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
@@ -1615,7 +1486,7 @@
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-php80/tree/v1.33.0"
+ "source": "https://github.com/symfony/polyfill-php84/tree/v1.33.0"
},
"funding": [
{
@@ -1635,7 +1506,7 @@
"type": "tidelift"
}
],
- "time": "2025-01-02T08:10:11+00:00"
+ "time": "2025-06-24T13:30:11+00:00"
},
{
"name": "webmozart/assert",
@@ -1772,17 +1643,75 @@
}
],
"packages-dev": [],
- "aliases": [],
- "minimum-stability": "stable",
- "stability-flags": [],
- "prefer-stable": false,
+ "aliases": [
+ {
+ "package": "ipl/html",
+ "version": "dev-main",
+ "alias": "99.x-dev",
+ "alias_normalized": "99.9999999.9999999.9999999-dev"
+ },
+ {
+ "package": "ipl/i18n",
+ "version": "dev-main",
+ "alias": "99.x-dev",
+ "alias_normalized": "99.9999999.9999999.9999999-dev"
+ },
+ {
+ "package": "ipl/orm",
+ "version": "dev-main",
+ "alias": "99.x-dev",
+ "alias_normalized": "99.9999999.9999999.9999999-dev"
+ },
+ {
+ "package": "ipl/scheduler",
+ "version": "dev-main",
+ "alias": "99.x-dev",
+ "alias_normalized": "99.9999999.9999999.9999999-dev"
+ },
+ {
+ "package": "ipl/sql",
+ "version": "dev-main",
+ "alias": "99.x-dev",
+ "alias_normalized": "99.9999999.9999999.9999999-dev"
+ },
+ {
+ "package": "ipl/stdlib",
+ "version": "dev-main",
+ "alias": "99.x-dev",
+ "alias_normalized": "99.9999999.9999999.9999999-dev"
+ },
+ {
+ "package": "ipl/validator",
+ "version": "dev-main",
+ "alias": "99.x-dev",
+ "alias_normalized": "99.9999999.9999999.9999999-dev"
+ },
+ {
+ "package": "ipl/web",
+ "version": "dev-main",
+ "alias": "99.x-dev",
+ "alias_normalized": "99.9999999.9999999.9999999-dev"
+ }
+ ],
+ "minimum-stability": "dev",
+ "stability-flags": {
+ "ipl/html": 20,
+ "ipl/i18n": 20,
+ "ipl/orm": 20,
+ "ipl/scheduler": 20,
+ "ipl/sql": 20,
+ "ipl/stdlib": 20,
+ "ipl/validator": 20,
+ "ipl/web": 20
+ },
+ "prefer-stable": true,
"prefer-lowest": false,
"platform": {
"php": ">=7.2"
},
- "platform-dev": [],
+ "platform-dev": {},
"platform-overrides": {
- "php": "7.2.9"
+ "php": "8.2"
},
"plugin-api-version": "2.6.0"
}
diff --git a/vendor/autoload.php b/vendor/autoload.php
index 076e293..5c3658e 100644
--- a/vendor/autoload.php
+++ b/vendor/autoload.php
@@ -14,12 +14,9 @@ if (PHP_VERSION_ID < 50600) {
echo $err;
}
}
- trigger_error(
- $err,
- E_USER_ERROR
- );
+ throw new RuntimeException($err);
}
require_once __DIR__ . '/composer/autoload_real.php';
-return ComposerAutoloaderInit20d4022bc196691807f55d4a47c06474::getLoader();
+return ComposerAutoloaderInit7a1692c86b6fc70eaaf43c4bee3673aa::getLoader();
diff --git a/vendor/brick/math/composer.json b/vendor/brick/math/composer.json
index ec19663..ad1dfe0 100644
--- a/vendor/brick/math/composer.json
+++ b/vendor/brick/math/composer.json
@@ -5,22 +5,26 @@
"keywords": [
"Brick",
"Math",
+ "Mathematics",
"Arbitrary-precision",
"Arithmetic",
"BigInteger",
"BigDecimal",
"BigRational",
- "Bignum"
+ "BigNumber",
+ "Bignum",
+ "Decimal",
+ "Rational",
+ "Integer"
],
"license": "MIT",
"require": {
- "php": "^7.1 || ^8.0",
- "ext-json": "*"
+ "php": "^8.2"
},
"require-dev": {
- "phpunit/phpunit": "^7.5.15 || ^8.5 || ^9.0",
+ "phpunit/phpunit": "^11.5",
"php-coveralls/php-coveralls": "^2.2",
- "vimeo/psalm": "4.9.2"
+ "phpstan/phpstan": "2.1.22"
},
"autoload": {
"psr-4": {
diff --git a/vendor/brick/math/src/BigDecimal.php b/vendor/brick/math/src/BigDecimal.php
index 7824650..1a540c7 100644
--- a/vendor/brick/math/src/BigDecimal.php
+++ b/vendor/brick/math/src/BigDecimal.php
@@ -8,13 +8,13 @@ use Brick\Math\Exception\DivisionByZeroException;
use Brick\Math\Exception\MathException;
use Brick\Math\Exception\NegativeNumberException;
use Brick\Math\Internal\Calculator;
+use Brick\Math\Internal\CalculatorRegistry;
+use Override;
/**
* Immutable, arbitrary-precision signed decimal numbers.
- *
- * @psalm-immutable
*/
-final class BigDecimal extends BigNumber
+final readonly class BigDecimal extends BigNumber
{
/**
* The unscaled value of this decimal number.
@@ -22,25 +22,23 @@ final class BigDecimal extends BigNumber
* This is a string of digits with an optional leading minus sign.
* No leading zero must be present.
* No leading minus sign must be present if the value is 0.
- *
- * @var string
*/
- private $value;
+ private string $value;
/**
* The scale (number of digits after the decimal point) of this decimal number.
*
* This must be zero or more.
- *
- * @var int
*/
- private $scale;
+ private int $scale;
/**
* Protected constructor. Use a factory method to obtain an instance.
*
* @param string $value The unscaled value, validated.
* @param int $scale The scale, validated.
+ *
+ * @pure
*/
protected function __construct(string $value, int $scale = 0)
{
@@ -48,20 +46,10 @@ final class BigDecimal extends BigNumber
$this->scale = $scale;
}
- /**
- * Creates a BigDecimal of the given value.
- *
- * @param BigNumber|int|float|string $value
- *
- * @return BigDecimal
- *
- * @throws MathException If the value cannot be converted to a BigDecimal.
- *
- * @psalm-pure
- */
- public static function of($value) : BigNumber
+ #[Override]
+ protected static function from(BigNumber $number): static
{
- return parent::of($value)->toBigDecimal();
+ return $number->toBigDecimal();
}
/**
@@ -70,36 +58,33 @@ final class BigDecimal extends BigNumber
* Example: `(12345, 3)` will result in the BigDecimal `12.345`.
*
* @param BigNumber|int|float|string $value The unscaled value. Must be convertible to a BigInteger.
- * @param int $scale The scale of the number, positive or zero.
+ * @param int $scale The scale of the number. If negative, the scale will be set to zero
+ * and the unscaled value will be adjusted accordingly.
*
- * @return BigDecimal
- *
- * @throws \InvalidArgumentException If the scale is negative.
- *
- * @psalm-pure
+ * @pure
*/
- public static function ofUnscaledValue($value, int $scale = 0) : BigDecimal
+ public static function ofUnscaledValue(BigNumber|int|float|string $value, int $scale = 0) : BigDecimal
{
+ $value = (string) BigInteger::of($value);
+
if ($scale < 0) {
- throw new \InvalidArgumentException('The scale cannot be negative.');
+ if ($value !== '0') {
+ $value .= \str_repeat('0', -$scale);
+ }
+ $scale = 0;
}
- return new BigDecimal((string) BigInteger::of($value), $scale);
+ return new BigDecimal($value, $scale);
}
/**
* Returns a BigDecimal representing zero, with a scale of zero.
*
- * @return BigDecimal
- *
- * @psalm-pure
+ * @pure
*/
public static function zero() : BigDecimal
{
- /**
- * @psalm-suppress ImpureStaticVariable
- * @var BigDecimal|null $zero
- */
+ /** @var BigDecimal|null $zero */
static $zero;
if ($zero === null) {
@@ -112,16 +97,11 @@ final class BigDecimal extends BigNumber
/**
* Returns a BigDecimal representing one, with a scale of zero.
*
- * @return BigDecimal
- *
- * @psalm-pure
+ * @pure
*/
public static function one() : BigDecimal
{
- /**
- * @psalm-suppress ImpureStaticVariable
- * @var BigDecimal|null $one
- */
+ /** @var BigDecimal|null $one */
static $one;
if ($one === null) {
@@ -134,16 +114,11 @@ final class BigDecimal extends BigNumber
/**
* Returns a BigDecimal representing ten, with a scale of zero.
*
- * @return BigDecimal
- *
- * @psalm-pure
+ * @pure
*/
public static function ten() : BigDecimal
{
- /**
- * @psalm-suppress ImpureStaticVariable
- * @var BigDecimal|null $ten
- */
+ /** @var BigDecimal|null $ten */
static $ten;
if ($ten === null) {
@@ -160,11 +135,11 @@ final class BigDecimal extends BigNumber
*
* @param BigNumber|int|float|string $that The number to add. Must be convertible to a BigDecimal.
*
- * @return BigDecimal The result.
- *
* @throws MathException If the number is not valid, or is not convertible to a BigDecimal.
+ *
+ * @pure
*/
- public function plus($that) : BigDecimal
+ public function plus(BigNumber|int|float|string $that) : BigDecimal
{
$that = BigDecimal::of($that);
@@ -178,7 +153,7 @@ final class BigDecimal extends BigNumber
[$a, $b] = $this->scaleValues($this, $that);
- $value = Calculator::get()->add($a, $b);
+ $value = CalculatorRegistry::get()->add($a, $b);
$scale = $this->scale > $that->scale ? $this->scale : $that->scale;
return new BigDecimal($value, $scale);
@@ -191,11 +166,11 @@ final class BigDecimal extends BigNumber
*
* @param BigNumber|int|float|string $that The number to subtract. Must be convertible to a BigDecimal.
*
- * @return BigDecimal The result.
- *
* @throws MathException If the number is not valid, or is not convertible to a BigDecimal.
+ *
+ * @pure
*/
- public function minus($that) : BigDecimal
+ public function minus(BigNumber|int|float|string $that) : BigDecimal
{
$that = BigDecimal::of($that);
@@ -205,7 +180,7 @@ final class BigDecimal extends BigNumber
[$a, $b] = $this->scaleValues($this, $that);
- $value = Calculator::get()->sub($a, $b);
+ $value = CalculatorRegistry::get()->sub($a, $b);
$scale = $this->scale > $that->scale ? $this->scale : $that->scale;
return new BigDecimal($value, $scale);
@@ -218,11 +193,11 @@ final class BigDecimal extends BigNumber
*
* @param BigNumber|int|float|string $that The multiplier. Must be convertible to a BigDecimal.
*
- * @return BigDecimal The result.
- *
* @throws MathException If the multiplier is not a valid number, or is not convertible to a BigDecimal.
+ *
+ * @pure
*/
- public function multipliedBy($that) : BigDecimal
+ public function multipliedBy(BigNumber|int|float|string $that) : BigDecimal
{
$that = BigDecimal::of($that);
@@ -234,7 +209,7 @@ final class BigDecimal extends BigNumber
return $that;
}
- $value = Calculator::get()->mul($this->value, $that->value);
+ $value = CalculatorRegistry::get()->mul($this->value, $that->value);
$scale = $this->scale + $that->scale;
return new BigDecimal($value, $scale);
@@ -245,14 +220,14 @@ final class BigDecimal extends BigNumber
*
* @param BigNumber|int|float|string $that The divisor.
* @param int|null $scale The desired scale, or null to use the scale of this number.
- * @param int $roundingMode An optional rounding mode.
- *
- * @return BigDecimal
+ * @param RoundingMode $roundingMode An optional rounding mode, defaults to UNNECESSARY.
*
* @throws \InvalidArgumentException If the scale or rounding mode is invalid.
* @throws MathException If the number is invalid, is zero, or rounding was necessary.
+ *
+ * @pure
*/
- public function dividedBy($that, ?int $scale = null, int $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal
+ public function dividedBy(BigNumber|int|float|string $that, ?int $scale = null, RoundingMode $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal
{
$that = BigDecimal::of($that);
@@ -273,7 +248,7 @@ final class BigDecimal extends BigNumber
$p = $this->valueWithMinScale($that->scale + $scale);
$q = $that->valueWithMinScale($this->scale - $scale);
- $result = Calculator::get()->divRound($p, $q, $roundingMode);
+ $result = CalculatorRegistry::get()->divRound($p, $q, $roundingMode);
return new BigDecimal($result, $scale);
}
@@ -285,12 +260,12 @@ final class BigDecimal extends BigNumber
*
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigDecimal.
*
- * @return BigDecimal The result.
- *
* @throws MathException If the divisor is not a valid number, is not convertible to a BigDecimal, is zero,
* or the result yields an infinite number of digits.
+ *
+ * @pure
*/
- public function exactlyDividedBy($that) : BigDecimal
+ public function exactlyDividedBy(BigNumber|int|float|string $that) : BigDecimal
{
$that = BigDecimal::of($that);
@@ -303,7 +278,7 @@ final class BigDecimal extends BigNumber
$d = \rtrim($b, '0');
$scale = \strlen($b) - \strlen($d);
- $calculator = Calculator::get();
+ $calculator = CalculatorRegistry::get();
foreach ([5, 2] as $prime) {
for (;;) {
@@ -321,16 +296,36 @@ final class BigDecimal extends BigNumber
return $this->dividedBy($that, $scale)->stripTrailingZeros();
}
+ /**
+ * Limits (clamps) this number between the given minimum and maximum values.
+ *
+ * If the number is lower than $min, returns a copy of $min.
+ * If the number is greater than $max, returns a copy of $max.
+ * Otherwise, returns this number unchanged.
+ *
+ * @param BigNumber|int|float|string $min The minimum. Must be convertible to a BigDecimal.
+ * @param BigNumber|int|float|string $max The maximum. Must be convertible to a BigDecimal.
+ *
+ * @throws MathException If min/max are not convertible to a BigDecimal.
+ */
+ public function clamp(BigNumber|int|float|string $min, BigNumber|int|float|string $max) : BigDecimal
+ {
+ if ($this->isLessThan($min)) {
+ return BigDecimal::of($min);
+ } elseif ($this->isGreaterThan($max)) {
+ return BigDecimal::of($max);
+ }
+ return $this;
+ }
+
/**
* Returns this number exponentiated to the given value.
*
* The result has a scale of `$this->scale * $exponent`.
*
- * @param int $exponent The exponent.
- *
- * @return BigDecimal The result.
- *
* @throws \InvalidArgumentException If the exponent is not in the range 0 to 1,000,000.
+ *
+ * @pure
*/
public function power(int $exponent) : BigDecimal
{
@@ -350,21 +345,21 @@ final class BigDecimal extends BigNumber
));
}
- return new BigDecimal(Calculator::get()->pow($this->value, $exponent), $this->scale * $exponent);
+ return new BigDecimal(CalculatorRegistry::get()->pow($this->value, $exponent), $this->scale * $exponent);
}
/**
- * Returns the quotient of the division of this number by this given one.
+ * Returns the quotient of the division of this number by the given one.
*
* The quotient has a scale of `0`.
*
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigDecimal.
*
- * @return BigDecimal The quotient.
- *
* @throws MathException If the divisor is not a valid decimal number, or is zero.
+ *
+ * @pure
*/
- public function quotient($that) : BigDecimal
+ public function quotient(BigNumber|int|float|string $that) : BigDecimal
{
$that = BigDecimal::of($that);
@@ -375,23 +370,23 @@ final class BigDecimal extends BigNumber
$p = $this->valueWithMinScale($that->scale);
$q = $that->valueWithMinScale($this->scale);
- $quotient = Calculator::get()->divQ($p, $q);
+ $quotient = CalculatorRegistry::get()->divQ($p, $q);
return new BigDecimal($quotient, 0);
}
/**
- * Returns the remainder of the division of this number by this given one.
+ * Returns the remainder of the division of this number by the given one.
*
* The remainder has a scale of `max($this->scale, $that->scale)`.
*
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigDecimal.
*
- * @return BigDecimal The remainder.
- *
* @throws MathException If the divisor is not a valid decimal number, or is zero.
+ *
+ * @pure
*/
- public function remainder($that) : BigDecimal
+ public function remainder(BigNumber|int|float|string $that) : BigDecimal
{
$that = BigDecimal::of($that);
@@ -402,7 +397,7 @@ final class BigDecimal extends BigNumber
$p = $this->valueWithMinScale($that->scale);
$q = $that->valueWithMinScale($this->scale);
- $remainder = Calculator::get()->divR($p, $q);
+ $remainder = CalculatorRegistry::get()->divR($p, $q);
$scale = $this->scale > $that->scale ? $this->scale : $that->scale;
@@ -416,11 +411,13 @@ final class BigDecimal extends BigNumber
*
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigDecimal.
*
- * @return BigDecimal[] An array containing the quotient and the remainder.
+ * @return array{BigDecimal, BigDecimal} An array containing the quotient and the remainder.
*
* @throws MathException If the divisor is not a valid decimal number, or is zero.
+ *
+ * @pure
*/
- public function quotientAndRemainder($that) : array
+ public function quotientAndRemainder(BigNumber|int|float|string $that) : array
{
$that = BigDecimal::of($that);
@@ -431,7 +428,7 @@ final class BigDecimal extends BigNumber
$p = $this->valueWithMinScale($that->scale);
$q = $that->valueWithMinScale($this->scale);
- [$quotient, $remainder] = Calculator::get()->divQR($p, $q);
+ [$quotient, $remainder] = CalculatorRegistry::get()->divQR($p, $q);
$scale = $this->scale > $that->scale ? $this->scale : $that->scale;
@@ -444,12 +441,10 @@ final class BigDecimal extends BigNumber
/**
* Returns the square root of this number, rounded down to the given number of decimals.
*
- * @param int $scale
- *
- * @return BigDecimal
- *
* @throws \InvalidArgumentException If the scale is negative.
* @throws NegativeNumberException If this number is negative.
+ *
+ * @pure
*/
public function sqrt(int $scale) : BigDecimal
{
@@ -481,7 +476,7 @@ final class BigDecimal extends BigNumber
$value = \substr($value, 0, $addDigits);
}
- $value = Calculator::get()->sqrt($value);
+ $value = CalculatorRegistry::get()->sqrt($value);
return new BigDecimal($value, $scale);
}
@@ -489,9 +484,7 @@ final class BigDecimal extends BigNumber
/**
* Returns a copy of this BigDecimal with the decimal point moved $n places to the left.
*
- * @param int $n
- *
- * @return BigDecimal
+ * @pure
*/
public function withPointMovedLeft(int $n) : BigDecimal
{
@@ -509,9 +502,7 @@ final class BigDecimal extends BigNumber
/**
* Returns a copy of this BigDecimal with the decimal point moved $n places to the right.
*
- * @param int $n
- *
- * @return BigDecimal
+ * @pure
*/
public function withPointMovedRight(int $n) : BigDecimal
{
@@ -539,7 +530,7 @@ final class BigDecimal extends BigNumber
/**
* Returns a copy of this BigDecimal with any trailing zeros removed from the fractional part.
*
- * @return BigDecimal
+ * @pure
*/
public function stripTrailingZeros() : BigDecimal
{
@@ -572,7 +563,7 @@ final class BigDecimal extends BigNumber
/**
* Returns the absolute value of this number.
*
- * @return BigDecimal
+ * @pure
*/
public function abs() : BigDecimal
{
@@ -582,17 +573,15 @@ final class BigDecimal extends BigNumber
/**
* Returns the negated value of this number.
*
- * @return BigDecimal
+ * @pure
*/
public function negated() : BigDecimal
{
- return new BigDecimal(Calculator::get()->neg($this->value), $this->scale);
+ return new BigDecimal(CalculatorRegistry::get()->neg($this->value), $this->scale);
}
- /**
- * {@inheritdoc}
- */
- public function compareTo($that) : int
+ #[Override]
+ public function compareTo(BigNumber|int|float|string $that) : int
{
$that = BigNumber::of($that);
@@ -603,42 +592,69 @@ final class BigDecimal extends BigNumber
if ($that instanceof BigDecimal) {
[$a, $b] = $this->scaleValues($this, $that);
- return Calculator::get()->cmp($a, $b);
+ return CalculatorRegistry::get()->cmp($a, $b);
}
return - $that->compareTo($this);
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function getSign() : int
{
return ($this->value === '0') ? 0 : (($this->value[0] === '-') ? -1 : 1);
}
/**
- * @return BigInteger
+ * @pure
*/
public function getUnscaledValue() : BigInteger
{
- return BigInteger::create($this->value);
+ return self::newBigInteger($this->value);
}
/**
- * @return int
+ * @pure
*/
public function getScale() : int
{
return $this->scale;
}
+ /**
+ * Returns the number of significant digits in the number.
+ *
+ * This is the number of digits to both sides of the decimal point, stripped of leading zeros.
+ * The sign has no impact on the result.
+ *
+ * Examples:
+ * 0 => 0
+ * 0.0 => 0
+ * 123 => 3
+ * 123.456 => 6
+ * 0.00123 => 3
+ * 0.0012300 => 5
+ *
+ * @pure
+ */
+ public function getPrecision(): int
+ {
+ $value = $this->value;
+
+ if ($value === '0') {
+ return 0;
+ }
+
+ $length = \strlen($value);
+
+ return ($value[0] === '-') ? $length - 1 : $length;
+ }
+
/**
* Returns a string representing the integral part of this decimal number.
*
* Example: `-123.456` => `-123`.
*
- * @return string
+ * @pure
*/
public function getIntegralPart() : string
{
@@ -658,7 +674,7 @@ final class BigDecimal extends BigNumber
*
* Examples: `-123.456` => '456', `123` => ''.
*
- * @return string
+ * @pure
*/
public function getFractionalPart() : string
{
@@ -674,46 +690,38 @@ final class BigDecimal extends BigNumber
/**
* Returns whether this decimal number has a non-zero fractional part.
*
- * @return bool
+ * @pure
*/
public function hasNonZeroFractionalPart() : bool
{
return $this->getFractionalPart() !== \str_repeat('0', $this->scale);
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function toBigInteger() : BigInteger
{
$zeroScaleDecimal = $this->scale === 0 ? $this : $this->dividedBy(1, 0);
- return BigInteger::create($zeroScaleDecimal->value);
+ return self::newBigInteger($zeroScaleDecimal->value);
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function toBigDecimal() : BigDecimal
{
return $this;
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function toBigRational() : BigRational
{
- $numerator = BigInteger::create($this->value);
- $denominator = BigInteger::create('1' . \str_repeat('0', $this->scale));
+ $numerator = self::newBigInteger($this->value);
+ $denominator = self::newBigInteger('1' . \str_repeat('0', $this->scale));
- return BigRational::create($numerator, $denominator, false);
+ return self::newBigRational($numerator, $denominator, false);
}
- /**
- * {@inheritdoc}
- */
- public function toScale(int $scale, int $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal
+ #[Override]
+ public function toScale(int $scale, RoundingMode $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal
{
if ($scale === $this->scale) {
return $this;
@@ -722,33 +730,32 @@ final class BigDecimal extends BigNumber
return $this->dividedBy(BigDecimal::one(), $scale, $roundingMode);
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function toInt() : int
{
return $this->toBigInteger()->toInt();
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function toFloat() : float
{
return (float) (string) $this;
}
/**
- * {@inheritdoc}
+ * @return numeric-string
*/
+ #[Override]
public function __toString() : string
{
if ($this->scale === 0) {
+ /** @var numeric-string */
return $this->value;
}
$value = $this->getUnscaledValueWithLeadingZeros();
+ /** @phpstan-ignore return.type */
return \substr($value, 0, -$this->scale) . '.' . \substr($value, -$this->scale);
}
@@ -768,67 +775,29 @@ final class BigDecimal extends BigNumber
* This method is only here to allow unserializing the object and cannot be accessed directly.
*
* @internal
- * @psalm-suppress RedundantPropertyInitializationCheck
*
* @param array{value: string, scale: int} $data
*
- * @return void
- *
* @throws \LogicException
*/
public function __unserialize(array $data): void
{
+ /** @phpstan-ignore isset.initializedProperty */
if (isset($this->value)) {
throw new \LogicException('__unserialize() is an internal function, it must not be called directly.');
}
+ /** @phpstan-ignore deadCode.unreachable */
$this->value = $data['value'];
$this->scale = $data['scale'];
}
- /**
- * This method is required by interface Serializable and SHOULD NOT be accessed directly.
- *
- * @internal
- *
- * @return string
- */
- public function serialize() : string
- {
- return $this->value . ':' . $this->scale;
- }
-
- /**
- * This method is only here to implement interface Serializable and cannot be accessed directly.
- *
- * @internal
- * @psalm-suppress RedundantPropertyInitializationCheck
- *
- * @param string $value
- *
- * @return void
- *
- * @throws \LogicException
- */
- public function unserialize($value) : void
- {
- if (isset($this->value)) {
- throw new \LogicException('unserialize() is an internal function, it must not be called directly.');
- }
-
- [$value, $scale] = \explode(':', $value);
-
- $this->value = $value;
- $this->scale = (int) $scale;
- }
-
/**
* Puts the internal values of the given decimal numbers on the same scale.
*
- * @param BigDecimal $x The first decimal number.
- * @param BigDecimal $y The second decimal number.
- *
* @return array{string, string} The scaled integer values of $x and $y.
+ *
+ * @pure
*/
private function scaleValues(BigDecimal $x, BigDecimal $y) : array
{
@@ -845,9 +814,7 @@ final class BigDecimal extends BigNumber
}
/**
- * @param int $scale
- *
- * @return string
+ * @pure
*/
private function valueWithMinScale(int $scale) : string
{
@@ -863,7 +830,7 @@ final class BigDecimal extends BigNumber
/**
* Adds leading zeros if necessary to the unscaled value to represent the full decimal number.
*
- * @return string
+ * @pure
*/
private function getUnscaledValueWithLeadingZeros() : string
{
diff --git a/vendor/brick/math/src/BigInteger.php b/vendor/brick/math/src/BigInteger.php
index f213fbe..48a7bb3 100644
--- a/vendor/brick/math/src/BigInteger.php
+++ b/vendor/brick/math/src/BigInteger.php
@@ -10,51 +10,41 @@ use Brick\Math\Exception\MathException;
use Brick\Math\Exception\NegativeNumberException;
use Brick\Math\Exception\NumberFormatException;
use Brick\Math\Internal\Calculator;
+use Brick\Math\Internal\CalculatorRegistry;
+use Override;
/**
* An arbitrary-size integer.
*
* All methods accepting a number as a parameter accept either a BigInteger instance,
* an integer, or a string representing an arbitrary size integer.
- *
- * @psalm-immutable
*/
-final class BigInteger extends BigNumber
+final readonly class BigInteger extends BigNumber
{
/**
* The value, as a string of digits with optional leading minus sign.
*
* No leading zeros must be present.
* No leading minus sign must be present if the number is zero.
- *
- * @var string
*/
- private $value;
+ private string $value;
/**
* Protected constructor. Use a factory method to obtain an instance.
*
* @param string $value A string of digits, with optional leading minus sign.
+ *
+ * @pure
*/
protected function __construct(string $value)
{
$this->value = $value;
}
- /**
- * Creates a BigInteger of the given value.
- *
- * @param BigNumber|int|float|string $value
- *
- * @return BigInteger
- *
- * @throws MathException If the value cannot be converted to a BigInteger.
- *
- * @psalm-pure
- */
- public static function of($value) : BigNumber
+ #[Override]
+ protected static function from(BigNumber $number): static
{
- return parent::of($value)->toBigInteger();
+ return $number->toBigInteger();
}
/**
@@ -71,12 +61,10 @@ final class BigInteger extends BigNumber
* @param string $number The number to convert, in the given base.
* @param int $base The base of the number, between 2 and 36.
*
- * @return BigInteger
- *
* @throws NumberFormatException If the number is empty, or contains invalid chars for the given base.
* @throws \InvalidArgumentException If the base is out of range.
*
- * @psalm-pure
+ * @pure
*/
public static function fromBase(string $number, int $base) : BigInteger
{
@@ -125,7 +113,7 @@ final class BigInteger extends BigNumber
return new BigInteger($sign . $number);
}
- $result = Calculator::get()->fromBase($number, $base);
+ $result = CalculatorRegistry::get()->fromBase($number, $base);
return new BigInteger($sign . $result);
}
@@ -138,12 +126,10 @@ final class BigInteger extends BigNumber
* @param string $number The number to parse.
* @param string $alphabet The alphabet, for example '01' for base 2, or '01234567' for base 8.
*
- * @return BigInteger
- *
* @throws NumberFormatException If the given number is empty or contains invalid chars for the given alphabet.
* @throws \InvalidArgumentException If the alphabet does not contain at least 2 chars.
*
- * @psalm-pure
+ * @pure
*/
public static function fromArbitraryBase(string $number, string $alphabet) : BigInteger
{
@@ -163,7 +149,7 @@ final class BigInteger extends BigNumber
throw NumberFormatException::charNotInAlphabet($matches[0]);
}
- $number = Calculator::get()->fromArbitraryBase($number, $alphabet, $base);
+ $number = CalculatorRegistry::get()->fromArbitraryBase($number, $alphabet, $base);
return new BigInteger($number);
}
@@ -183,9 +169,9 @@ final class BigInteger extends BigNumber
* @param bool $signed Whether to interpret as a signed number in two's-complement representation with a leading
* sign bit.
*
- * @return BigInteger
- *
* @throws NumberFormatException If the string is empty.
+ *
+ * @pure
*/
public static function fromBytes(string $value, bool $signed = true) : BigInteger
{
@@ -217,14 +203,10 @@ final class BigInteger extends BigNumber
*
* Using the default random bytes generator, this method is suitable for cryptographic use.
*
- * @psalm-param callable(int): string $randomBytesGenerator
- *
- * @param int $numBits The number of bits.
- * @param callable|null $randomBytesGenerator A function that accepts a number of bytes as an integer, and returns a
- * string of random bytes of the given length. Defaults to the
- * `random_bytes()` function.
- *
- * @return BigInteger
+ * @param int $numBits The number of bits.
+ * @param (callable(int): string)|null $randomBytesGenerator A function that accepts a number of bytes, and returns
+ * a string of random bytes of the given length. Defaults
+ * to the `random_bytes()` function.
*
* @throws \InvalidArgumentException If $numBits is negative.
*/
@@ -239,9 +221,10 @@ final class BigInteger extends BigNumber
}
if ($randomBytesGenerator === null) {
- $randomBytesGenerator = 'random_bytes';
+ $randomBytesGenerator = random_bytes(...);
}
+ /** @var int<1, max> $byteLength */
$byteLength = \intdiv($numBits - 1, 8) + 1;
$extraBits = ($byteLength * 8 - $numBits);
@@ -258,21 +241,20 @@ final class BigInteger extends BigNumber
*
* Using the default random bytes generator, this method is suitable for cryptographic use.
*
- * @psalm-param (callable(int): string)|null $randomBytesGenerator
- *
- * @param BigNumber|int|float|string $min The lower bound. Must be convertible to a BigInteger.
- * @param BigNumber|int|float|string $max The upper bound. Must be convertible to a BigInteger.
- * @param callable|null $randomBytesGenerator A function that accepts a number of bytes as an integer,
- * and returns a string of random bytes of the given length.
- * Defaults to the `random_bytes()` function.
- *
- * @return BigInteger
+ * @param BigNumber|int|float|string $min The lower bound. Must be convertible to a BigInteger.
+ * @param BigNumber|int|float|string $max The upper bound. Must be convertible to a BigInteger.
+ * @param (callable(int): string)|null $randomBytesGenerator A function that accepts a number of bytes, and returns
+ * a string of random bytes of the given length. Defaults
+ * to the `random_bytes()` function.
*
* @throws MathException If one of the parameters cannot be converted to a BigInteger,
* or `$min` is greater than `$max`.
*/
- public static function randomRange($min, $max, ?callable $randomBytesGenerator = null) : BigInteger
- {
+ public static function randomRange(
+ BigNumber|int|float|string $min,
+ BigNumber|int|float|string $max,
+ ?callable $randomBytesGenerator = null
+ ) : BigInteger {
$min = BigInteger::of($min);
$max = BigInteger::of($max);
@@ -298,16 +280,11 @@ final class BigInteger extends BigNumber
/**
* Returns a BigInteger representing zero.
*
- * @return BigInteger
- *
- * @psalm-pure
+ * @pure
*/
public static function zero() : BigInteger
{
- /**
- * @psalm-suppress ImpureStaticVariable
- * @var BigInteger|null $zero
- */
+ /** @var BigInteger|null $zero */
static $zero;
if ($zero === null) {
@@ -320,16 +297,11 @@ final class BigInteger extends BigNumber
/**
* Returns a BigInteger representing one.
*
- * @return BigInteger
- *
- * @psalm-pure
+ * @pure
*/
public static function one() : BigInteger
{
- /**
- * @psalm-suppress ImpureStaticVariable
- * @var BigInteger|null $one
- */
+ /** @var BigInteger|null $one */
static $one;
if ($one === null) {
@@ -342,16 +314,11 @@ final class BigInteger extends BigNumber
/**
* Returns a BigInteger representing ten.
*
- * @return BigInteger
- *
- * @psalm-pure
+ * @pure
*/
public static function ten() : BigInteger
{
- /**
- * @psalm-suppress ImpureStaticVariable
- * @var BigInteger|null $ten
- */
+ /** @var BigInteger|null $ten */
static $ten;
if ($ten === null) {
@@ -361,16 +328,34 @@ final class BigInteger extends BigNumber
return $ten;
}
+ /**
+ * @pure
+ */
+ public static function gcdMultiple(BigInteger $a, BigInteger ...$n): BigInteger
+ {
+ $result = $a;
+
+ foreach ($n as $next) {
+ $result = $result->gcd($next);
+
+ if ($result->isEqualTo(1)) {
+ return $result;
+ }
+ }
+
+ return $result;
+ }
+
/**
* Returns the sum of this number and the given one.
*
* @param BigNumber|int|float|string $that The number to add. Must be convertible to a BigInteger.
*
- * @return BigInteger The result.
- *
* @throws MathException If the number is not valid, or is not convertible to a BigInteger.
+ *
+ * @pure
*/
- public function plus($that) : BigInteger
+ public function plus(BigNumber|int|float|string $that) : BigInteger
{
$that = BigInteger::of($that);
@@ -382,7 +367,7 @@ final class BigInteger extends BigNumber
return $that;
}
- $value = Calculator::get()->add($this->value, $that->value);
+ $value = CalculatorRegistry::get()->add($this->value, $that->value);
return new BigInteger($value);
}
@@ -392,11 +377,11 @@ final class BigInteger extends BigNumber
*
* @param BigNumber|int|float|string $that The number to subtract. Must be convertible to a BigInteger.
*
- * @return BigInteger The result.
- *
* @throws MathException If the number is not valid, or is not convertible to a BigInteger.
+ *
+ * @pure
*/
- public function minus($that) : BigInteger
+ public function minus(BigNumber|int|float|string $that) : BigInteger
{
$that = BigInteger::of($that);
@@ -404,7 +389,7 @@ final class BigInteger extends BigNumber
return $this;
}
- $value = Calculator::get()->sub($this->value, $that->value);
+ $value = CalculatorRegistry::get()->sub($this->value, $that->value);
return new BigInteger($value);
}
@@ -414,11 +399,11 @@ final class BigInteger extends BigNumber
*
* @param BigNumber|int|float|string $that The multiplier. Must be convertible to a BigInteger.
*
- * @return BigInteger The result.
- *
* @throws MathException If the multiplier is not a valid number, or is not convertible to a BigInteger.
+ *
+ * @pure
*/
- public function multipliedBy($that) : BigInteger
+ public function multipliedBy(BigNumber|int|float|string $that) : BigInteger
{
$that = BigInteger::of($that);
@@ -430,7 +415,7 @@ final class BigInteger extends BigNumber
return $that;
}
- $value = Calculator::get()->mul($this->value, $that->value);
+ $value = CalculatorRegistry::get()->mul($this->value, $that->value);
return new BigInteger($value);
}
@@ -439,14 +424,14 @@ final class BigInteger extends BigNumber
* Returns the result of the division of this number by the given one.
*
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigInteger.
- * @param int $roundingMode An optional rounding mode.
- *
- * @return BigInteger The result.
+ * @param RoundingMode $roundingMode An optional rounding mode, defaults to UNNECESSARY.
*
* @throws MathException If the divisor is not a valid number, is not convertible to a BigInteger, is zero,
* or RoundingMode::UNNECESSARY is used and the remainder is not zero.
+ *
+ * @pure
*/
- public function dividedBy($that, int $roundingMode = RoundingMode::UNNECESSARY) : BigInteger
+ public function dividedBy(BigNumber|int|float|string $that, RoundingMode $roundingMode = RoundingMode::UNNECESSARY) : BigInteger
{
$that = BigInteger::of($that);
@@ -458,19 +443,40 @@ final class BigInteger extends BigNumber
throw DivisionByZeroException::divisionByZero();
}
- $result = Calculator::get()->divRound($this->value, $that->value, $roundingMode);
+ $result = CalculatorRegistry::get()->divRound($this->value, $that->value, $roundingMode);
return new BigInteger($result);
}
+ /**
+ * Limits (clamps) this number between the given minimum and maximum values.
+ *
+ * If the number is lower than $min, returns a copy of $min.
+ * If the number is greater than $max, returns a copy of $max.
+ * Otherwise, returns this number unchanged.
+ *
+ * @param BigNumber|int|float|string $min The minimum. Must be convertible to a BigInteger.
+ * @param BigNumber|int|float|string $max The maximum. Must be convertible to a BigInteger.
+ *
+ * @throws MathException If min/max are not convertible to a BigInteger.
+ */
+ public function clamp(BigNumber|int|float|string $min, BigNumber|int|float|string $max) : BigInteger
+ {
+ if ($this->isLessThan($min)) {
+ return BigInteger::of($min);
+ } elseif ($this->isGreaterThan($max)) {
+ return BigInteger::of($max);
+ }
+ return $this;
+ }
+
+
/**
* Returns this number exponentiated to the given value.
*
- * @param int $exponent The exponent.
- *
- * @return BigInteger The result.
- *
* @throws \InvalidArgumentException If the exponent is not in the range 0 to 1,000,000.
+ *
+ * @pure
*/
public function power(int $exponent) : BigInteger
{
@@ -490,7 +496,7 @@ final class BigInteger extends BigNumber
));
}
- return new BigInteger(Calculator::get()->pow($this->value, $exponent));
+ return new BigInteger(CalculatorRegistry::get()->pow($this->value, $exponent));
}
/**
@@ -498,11 +504,11 @@ final class BigInteger extends BigNumber
*
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigInteger.
*
- * @return BigInteger
- *
* @throws DivisionByZeroException If the divisor is zero.
+ *
+ * @pure
*/
- public function quotient($that) : BigInteger
+ public function quotient(BigNumber|int|float|string $that) : BigInteger
{
$that = BigInteger::of($that);
@@ -514,7 +520,7 @@ final class BigInteger extends BigNumber
throw DivisionByZeroException::divisionByZero();
}
- $quotient = Calculator::get()->divQ($this->value, $that->value);
+ $quotient = CalculatorRegistry::get()->divQ($this->value, $that->value);
return new BigInteger($quotient);
}
@@ -526,11 +532,11 @@ final class BigInteger extends BigNumber
*
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigInteger.
*
- * @return BigInteger
- *
* @throws DivisionByZeroException If the divisor is zero.
+ *
+ * @pure
*/
- public function remainder($that) : BigInteger
+ public function remainder(BigNumber|int|float|string $that) : BigInteger
{
$that = BigInteger::of($that);
@@ -542,7 +548,7 @@ final class BigInteger extends BigNumber
throw DivisionByZeroException::divisionByZero();
}
- $remainder = Calculator::get()->divR($this->value, $that->value);
+ $remainder = CalculatorRegistry::get()->divR($this->value, $that->value);
return new BigInteger($remainder);
}
@@ -552,11 +558,13 @@ final class BigInteger extends BigNumber
*
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigInteger.
*
- * @return BigInteger[] An array containing the quotient and the remainder.
+ * @return array{BigInteger, BigInteger} An array containing the quotient and the remainder.
*
* @throws DivisionByZeroException If the divisor is zero.
+ *
+ * @pure
*/
- public function quotientAndRemainder($that) : array
+ public function quotientAndRemainder(BigNumber|int|float|string $that) : array
{
$that = BigInteger::of($that);
@@ -564,7 +572,7 @@ final class BigInteger extends BigNumber
throw DivisionByZeroException::divisionByZero();
}
- [$quotient, $remainder] = Calculator::get()->divQR($this->value, $that->value);
+ [$quotient, $remainder] = CalculatorRegistry::get()->divQR($this->value, $that->value);
return [
new BigInteger($quotient),
@@ -582,11 +590,11 @@ final class BigInteger extends BigNumber
*
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigInteger.
*
- * @return BigInteger
- *
* @throws DivisionByZeroException If the divisor is zero.
+ *
+ * @pure
*/
- public function mod($that) : BigInteger
+ public function mod(BigNumber|int|float|string $that) : BigInteger
{
$that = BigInteger::of($that);
@@ -594,7 +602,7 @@ final class BigInteger extends BigNumber
throw DivisionByZeroException::modulusMustNotBeZero();
}
- $value = Calculator::get()->mod($this->value, $that->value);
+ $value = CalculatorRegistry::get()->mod($this->value, $that->value);
return new BigInteger($value);
}
@@ -602,14 +610,12 @@ final class BigInteger extends BigNumber
/**
* Returns the modular multiplicative inverse of this BigInteger modulo $m.
*
- * @param BigInteger $m
- *
- * @return BigInteger
- *
* @throws DivisionByZeroException If $m is zero.
* @throws NegativeNumberException If $m is negative.
* @throws MathException If this BigInteger has no multiplicative inverse mod m (that is, this BigInteger
* is not relatively prime to m).
+ *
+ * @pure
*/
public function modInverse(BigInteger $m) : BigInteger
{
@@ -625,7 +631,7 @@ final class BigInteger extends BigNumber
return BigInteger::zero();
}
- $value = Calculator::get()->modInverse($this->value, $m->value);
+ $value = CalculatorRegistry::get()->modInverse($this->value, $m->value);
if ($value === null) {
throw new MathException('Unable to compute the modInverse for the given modulus.');
@@ -642,12 +648,12 @@ final class BigInteger extends BigNumber
* @param BigNumber|int|float|string $exp The exponent. Must be positive or zero.
* @param BigNumber|int|float|string $mod The modulus. Must be strictly positive.
*
- * @return BigInteger
- *
* @throws NegativeNumberException If any of the operands is negative.
* @throws DivisionByZeroException If the modulus is zero.
+ *
+ * @pure
*/
- public function modPow($exp, $mod) : BigInteger
+ public function modPow(BigNumber|int|float|string $exp, BigNumber|int|float|string $mod) : BigInteger
{
$exp = BigInteger::of($exp);
$mod = BigInteger::of($mod);
@@ -660,7 +666,7 @@ final class BigInteger extends BigNumber
throw DivisionByZeroException::modulusMustNotBeZero();
}
- $result = Calculator::get()->modPow($this->value, $exp->value, $mod->value);
+ $result = CalculatorRegistry::get()->modPow($this->value, $exp->value, $mod->value);
return new BigInteger($result);
}
@@ -672,9 +678,9 @@ final class BigInteger extends BigNumber
*
* @param BigNumber|int|float|string $that The operand. Must be convertible to an integer number.
*
- * @return BigInteger
+ * @pure
*/
- public function gcd($that) : BigInteger
+ public function gcd(BigNumber|int|float|string $that) : BigInteger
{
$that = BigInteger::of($that);
@@ -686,7 +692,7 @@ final class BigInteger extends BigNumber
return $that;
}
- $value = Calculator::get()->gcd($this->value, $that->value);
+ $value = CalculatorRegistry::get()->gcd($this->value, $that->value);
return new BigInteger($value);
}
@@ -696,9 +702,9 @@ final class BigInteger extends BigNumber
*
* The result is the largest x such that x² ≤ n.
*
- * @return BigInteger
- *
* @throws NegativeNumberException If this number is negative.
+ *
+ * @pure
*/
public function sqrt() : BigInteger
{
@@ -706,7 +712,7 @@ final class BigInteger extends BigNumber
throw new NegativeNumberException('Cannot calculate the square root of a negative number.');
}
- $value = Calculator::get()->sqrt($this->value);
+ $value = CalculatorRegistry::get()->sqrt($this->value);
return new BigInteger($value);
}
@@ -714,7 +720,7 @@ final class BigInteger extends BigNumber
/**
* Returns the absolute value of this number.
*
- * @return BigInteger
+ * @pure
*/
public function abs() : BigInteger
{
@@ -724,11 +730,11 @@ final class BigInteger extends BigNumber
/**
* Returns the inverse of this number.
*
- * @return BigInteger
+ * @pure
*/
public function negated() : BigInteger
{
- return new BigInteger(Calculator::get()->neg($this->value));
+ return new BigInteger(CalculatorRegistry::get()->neg($this->value));
}
/**
@@ -738,13 +744,13 @@ final class BigInteger extends BigNumber
*
* @param BigNumber|int|float|string $that The operand. Must be convertible to an integer number.
*
- * @return BigInteger
+ * @pure
*/
- public function and($that) : BigInteger
+ public function and(BigNumber|int|float|string $that) : BigInteger
{
$that = BigInteger::of($that);
- return new BigInteger(Calculator::get()->and($this->value, $that->value));
+ return new BigInteger(CalculatorRegistry::get()->and($this->value, $that->value));
}
/**
@@ -754,13 +760,13 @@ final class BigInteger extends BigNumber
*
* @param BigNumber|int|float|string $that The operand. Must be convertible to an integer number.
*
- * @return BigInteger
+ * @pure
*/
- public function or($that) : BigInteger
+ public function or(BigNumber|int|float|string $that) : BigInteger
{
$that = BigInteger::of($that);
- return new BigInteger(Calculator::get()->or($this->value, $that->value));
+ return new BigInteger(CalculatorRegistry::get()->or($this->value, $that->value));
}
/**
@@ -770,19 +776,19 @@ final class BigInteger extends BigNumber
*
* @param BigNumber|int|float|string $that The operand. Must be convertible to an integer number.
*
- * @return BigInteger
+ * @pure
*/
- public function xor($that) : BigInteger
+ public function xor(BigNumber|int|float|string $that) : BigInteger
{
$that = BigInteger::of($that);
- return new BigInteger(Calculator::get()->xor($this->value, $that->value));
+ return new BigInteger(CalculatorRegistry::get()->xor($this->value, $that->value));
}
/**
* Returns the bitwise-not of this BigInteger.
*
- * @return BigInteger
+ * @pure
*/
public function not() : BigInteger
{
@@ -792,9 +798,7 @@ final class BigInteger extends BigNumber
/**
* Returns the integer left shifted by a given number of bits.
*
- * @param int $distance The distance to shift.
- *
- * @return BigInteger
+ * @pure
*/
public function shiftedLeft(int $distance) : BigInteger
{
@@ -812,9 +816,7 @@ final class BigInteger extends BigNumber
/**
* Returns the integer right shifted by a given number of bits.
*
- * @param int $distance The distance to shift.
- *
- * @return BigInteger
+ * @pure
*/
public function shiftedRight(int $distance) : BigInteger
{
@@ -841,7 +843,7 @@ final class BigInteger extends BigNumber
* For positive BigIntegers, this is equivalent to the number of bits in the ordinary binary representation.
* Computes (ceil(log2(this < 0 ? -this : this+1))).
*
- * @return int
+ * @pure
*/
public function getBitLength() : int
{
@@ -861,7 +863,7 @@ final class BigInteger extends BigNumber
*
* Returns -1 if this BigInteger contains no one bits.
*
- * @return int
+ * @pure
*/
public function getLowestSetBit() : int
{
@@ -882,7 +884,7 @@ final class BigInteger extends BigNumber
/**
* Returns whether this number is even.
*
- * @return bool
+ * @pure
*/
public function isEven() : bool
{
@@ -892,7 +894,7 @@ final class BigInteger extends BigNumber
/**
* Returns whether this number is odd.
*
- * @return bool
+ * @pure
*/
public function isOdd() : bool
{
@@ -906,9 +908,9 @@ final class BigInteger extends BigNumber
*
* @param int $n The bit to test, 0-based.
*
- * @return bool
- *
* @throws \InvalidArgumentException If the bit to test is negative.
+ *
+ * @pure
*/
public function testBit(int $n) : bool
{
@@ -919,63 +921,49 @@ final class BigInteger extends BigNumber
return $this->shiftedRight($n)->isOdd();
}
- /**
- * {@inheritdoc}
- */
- public function compareTo($that) : int
+ #[Override]
+ public function compareTo(BigNumber|int|float|string $that) : int
{
$that = BigNumber::of($that);
if ($that instanceof BigInteger) {
- return Calculator::get()->cmp($this->value, $that->value);
+ return CalculatorRegistry::get()->cmp($this->value, $that->value);
}
return - $that->compareTo($this);
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function getSign() : int
{
return ($this->value === '0') ? 0 : (($this->value[0] === '-') ? -1 : 1);
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function toBigInteger() : BigInteger
{
return $this;
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function toBigDecimal() : BigDecimal
{
- return BigDecimal::create($this->value);
+ return self::newBigDecimal($this->value);
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function toBigRational() : BigRational
{
- return BigRational::create($this, BigInteger::one(), false);
+ return self::newBigRational($this, BigInteger::one(), false);
}
- /**
- * {@inheritdoc}
- */
- public function toScale(int $scale, int $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal
+ #[Override]
+ public function toScale(int $scale, RoundingMode $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal
{
return $this->toBigDecimal()->toScale($scale, $roundingMode);
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function toInt() : int
{
$intValue = (int) $this->value;
@@ -987,9 +975,7 @@ final class BigInteger extends BigNumber
return $intValue;
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function toFloat() : float
{
return (float) $this->value;
@@ -1000,11 +986,9 @@ final class BigInteger extends BigNumber
*
* The output will always be lowercase for bases greater than 10.
*
- * @param int $base
- *
- * @return string
- *
* @throws \InvalidArgumentException If the base is out of range.
+ *
+ * @pure
*/
public function toBase(int $base) : string
{
@@ -1016,7 +1000,7 @@ final class BigInteger extends BigNumber
throw new \InvalidArgumentException(\sprintf('Base %d is out of range [2, 36]', $base));
}
- return Calculator::get()->toBase($this->value, $base);
+ return CalculatorRegistry::get()->toBase($this->value, $base);
}
/**
@@ -1027,10 +1011,10 @@ final class BigInteger extends BigNumber
*
* @param string $alphabet The alphabet, for example '01' for base 2, or '01234567' for base 8.
*
- * @return string
- *
* @throws NegativeNumberException If this number is negative.
* @throws \InvalidArgumentException If the given alphabet does not contain at least 2 chars.
+ *
+ * @pure
*/
public function toArbitraryBase(string $alphabet) : string
{
@@ -1044,7 +1028,7 @@ final class BigInteger extends BigNumber
throw new NegativeNumberException(__FUNCTION__ . '() does not support negative numbers.');
}
- return Calculator::get()->toArbitraryBase($this->value, $alphabet, $base);
+ return CalculatorRegistry::get()->toArbitraryBase($this->value, $alphabet, $base);
}
/**
@@ -1063,9 +1047,9 @@ final class BigInteger extends BigNumber
*
* @param bool $signed Whether to output a signed number in two's-complement representation with a leading sign bit.
*
- * @return string
- *
* @throws NegativeNumberException If $signed is false, and the number is negative.
+ *
+ * @pure
*/
public function toBytes(bool $signed = true) : string
{
@@ -1105,14 +1089,19 @@ final class BigInteger extends BigNumber
}
}
- return \hex2bin($hex);
+ $result = \hex2bin($hex);
+ assert($result !== false);
+
+ return $result;
}
/**
- * {@inheritdoc}
+ * @return numeric-string
*/
+ #[Override]
public function __toString() : string
{
+ /** @var numeric-string */
return $this->value;
}
@@ -1132,53 +1121,19 @@ final class BigInteger extends BigNumber
* This method is only here to allow unserializing the object and cannot be accessed directly.
*
* @internal
- * @psalm-suppress RedundantPropertyInitializationCheck
*
* @param array{value: string} $data
*
- * @return void
- *
* @throws \LogicException
*/
public function __unserialize(array $data): void
{
+ /** @phpstan-ignore isset.initializedProperty */
if (isset($this->value)) {
throw new \LogicException('__unserialize() is an internal function, it must not be called directly.');
}
+ /** @phpstan-ignore deadCode.unreachable */
$this->value = $data['value'];
}
-
- /**
- * This method is required by interface Serializable and SHOULD NOT be accessed directly.
- *
- * @internal
- *
- * @return string
- */
- public function serialize() : string
- {
- return $this->value;
- }
-
- /**
- * This method is only here to implement interface Serializable and cannot be accessed directly.
- *
- * @internal
- * @psalm-suppress RedundantPropertyInitializationCheck
- *
- * @param string $value
- *
- * @return void
- *
- * @throws \LogicException
- */
- public function unserialize($value) : void
- {
- if (isset($this->value)) {
- throw new \LogicException('unserialize() is an internal function, it must not be called directly.');
- }
-
- $this->value = $value;
- }
}
diff --git a/vendor/brick/math/src/BigNumber.php b/vendor/brick/math/src/BigNumber.php
index 38c8c55..2fbdf69 100644
--- a/vendor/brick/math/src/BigNumber.php
+++ b/vendor/brick/math/src/BigNumber.php
@@ -8,38 +8,46 @@ use Brick\Math\Exception\DivisionByZeroException;
use Brick\Math\Exception\MathException;
use Brick\Math\Exception\NumberFormatException;
use Brick\Math\Exception\RoundingNecessaryException;
+use Override;
/**
- * Common interface for arbitrary-precision rational numbers.
+ * Base class for arbitrary-precision numbers.
*
- * @psalm-immutable
+ * This class is sealed: it is part of the public API but should not be subclassed in userland.
+ * Protected methods may change in any version.
+ *
+ * @phpstan-sealed BigInteger|BigDecimal|BigRational
*/
-abstract class BigNumber implements \Serializable, \JsonSerializable
+abstract readonly class BigNumber implements \JsonSerializable, \Stringable
{
/**
- * The regular expression used to parse integer, decimal and rational numbers.
+ * The regular expression used to parse integer or decimal numbers.
*/
- private const PARSE_REGEXP =
+ private const PARSE_REGEXP_NUMERICAL =
'/^' .
'(?[\-\+])?' .
- '(?:' .
- '(?:' .
- '(?[0-9]+)?' .
- '(?\.)?' .
- '(?[0-9]+)?' .
- '(?:[eE](?[\-\+]?[0-9]+))?' .
- ')|(?:' .
- '(?[0-9]+)' .
- '\/?' .
- '(?[0-9]+)' .
- ')' .
- ')' .
+ '(?[0-9]+)?' .
+ '(?\.)?' .
+ '(?[0-9]+)?' .
+ '(?:[eE](?[\-\+]?[0-9]+))?' .
+ '$/';
+
+ /**
+ * The regular expression used to parse rational numbers.
+ */
+ private const PARSE_REGEXP_RATIONAL =
+ '/^' .
+ '(?[\-\+])?' .
+ '(?[0-9]+)' .
+ '\/?' .
+ '(?[0-9]+)' .
'$/';
/**
* Creates a BigNumber of the given value.
*
- * The concrete return type is dependent on the given value, with the following rules:
+ * When of() is called on BigNumber, the concrete return type is dependent on the given value, with the following
+ * rules:
*
* - BigNumber instances are returned as is
* - integer numbers are returned as BigInteger
@@ -48,16 +56,35 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
* - strings containing a `.` character or using an exponential notation are returned as BigDecimal
* - strings containing only digits with an optional leading `+` or `-` sign are returned as BigInteger
*
- * @param BigNumber|int|float|string $value
+ * When of() is called on BigInteger, BigDecimal, or BigRational, the resulting number is converted to an instance
+ * of the subclass when possible; otherwise a RoundingNecessaryException exception is thrown.
*
- * @return BigNumber
+ * @throws NumberFormatException If the format of the number is not valid.
+ * @throws DivisionByZeroException If the value represents a rational number with a denominator of zero.
+ * @throws RoundingNecessaryException If the value cannot be converted to an instance of the subclass without rounding.
*
- * @throws NumberFormatException If the format of the number is not valid.
+ * @pure
+ */
+ final public static function of(BigNumber|int|float|string $value) : static
+ {
+ $value = self::_of($value);
+
+ if (static::class === BigNumber::class) {
+ assert($value instanceof static);
+
+ return $value;
+ }
+
+ return static::from($value);
+ }
+
+ /**
+ * @throws NumberFormatException If the format of the number is not valid.
* @throws DivisionByZeroException If the value represents a rational number with a denominator of zero.
*
- * @psalm-pure
+ * @pure
*/
- public static function of($value) : BigNumber
+ private static function _of(BigNumber|int|float|string $value) : BigNumber
{
if ($value instanceof BigNumber) {
return $value;
@@ -67,37 +94,22 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
return new BigInteger((string) $value);
}
- /** @psalm-suppress RedundantCastGivenDocblockType We cannot trust the untyped $value here! */
- $value = \is_float($value) ? self::floatToString($value) : (string) $value;
-
- $throw = static function() use ($value) : void {
- throw new NumberFormatException(\sprintf(
- 'The given value "%s" does not represent a valid number.',
- $value
- ));
- };
-
- if (\preg_match(self::PARSE_REGEXP, $value, $matches) !== 1) {
- $throw();
+ if (is_float($value)) {
+ $value = (string) $value;
}
- $getMatch = static function(string $value) use ($matches) : ?string {
- return isset($matches[$value]) && $matches[$value] !== '' ? $matches[$value] : null;
- };
-
- $sign = $getMatch('sign');
- $numerator = $getMatch('numerator');
- $denominator = $getMatch('denominator');
-
- if ($numerator !== null) {
- assert($denominator !== null);
-
- if ($sign !== null) {
- $numerator = $sign . $numerator;
+ if (str_contains($value, '/')) {
+ // Rational number
+ if (\preg_match(self::PARSE_REGEXP_RATIONAL, $value, $matches, PREG_UNMATCHED_AS_NULL) !== 1) {
+ throw NumberFormatException::invalidFormat($value);
}
- $numerator = self::cleanUp($numerator);
- $denominator = self::cleanUp($denominator);
+ $sign = $matches['sign'];
+ $numerator = $matches['numerator'];
+ $denominator = $matches['denominator'];
+
+ $numerator = self::cleanUp($sign, $numerator);
+ $denominator = self::cleanUp(null, $denominator);
if ($denominator === '0') {
throw DivisionByZeroException::denominatorMustNotBeZero();
@@ -108,88 +120,94 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
new BigInteger($denominator),
false
);
- }
-
- $point = $getMatch('point');
- $integral = $getMatch('integral');
- $fractional = $getMatch('fractional');
- $exponent = $getMatch('exponent');
-
- if ($integral === null && $fractional === null) {
- $throw();
- }
-
- if ($integral === null) {
- $integral = '0';
- }
-
- if ($point !== null || $exponent !== null) {
- $fractional = ($fractional ?? '');
- $exponent = ($exponent !== null) ? (int) $exponent : 0;
-
- if ($exponent === PHP_INT_MIN || $exponent === PHP_INT_MAX) {
- throw new NumberFormatException('Exponent too large.');
+ } else {
+ // Integer or decimal number
+ if (\preg_match(self::PARSE_REGEXP_NUMERICAL, $value, $matches, PREG_UNMATCHED_AS_NULL) !== 1) {
+ throw NumberFormatException::invalidFormat($value);
}
- $unscaledValue = self::cleanUp(($sign ?? ''). $integral . $fractional);
+ $sign = $matches['sign'];
+ $point = $matches['point'];
+ $integral = $matches['integral'];
+ $fractional = $matches['fractional'];
+ $exponent = $matches['exponent'];
- $scale = \strlen($fractional) - $exponent;
+ if ($integral === null && $fractional === null) {
+ throw NumberFormatException::invalidFormat($value);
+ }
- if ($scale < 0) {
- if ($unscaledValue !== '0') {
- $unscaledValue .= \str_repeat('0', - $scale);
+ if ($integral === null) {
+ $integral = '0';
+ }
+
+ if ($point !== null || $exponent !== null) {
+ $fractional ??= '';
+ $exponent = ($exponent !== null) ? (int)$exponent : 0;
+
+ if ($exponent === PHP_INT_MIN || $exponent === PHP_INT_MAX) {
+ throw new NumberFormatException('Exponent too large.');
}
- $scale = 0;
+
+ $unscaledValue = self::cleanUp($sign, $integral . $fractional);
+
+ $scale = \strlen($fractional) - $exponent;
+
+ if ($scale < 0) {
+ if ($unscaledValue !== '0') {
+ $unscaledValue .= \str_repeat('0', -$scale);
+ }
+ $scale = 0;
+ }
+
+ return new BigDecimal($unscaledValue, $scale);
}
- return new BigDecimal($unscaledValue, $scale);
+ $integral = self::cleanUp($sign, $integral);
+
+ return new BigInteger($integral);
}
-
- $integral = self::cleanUp(($sign ?? '') . $integral);
-
- return new BigInteger($integral);
}
/**
- * Safely converts float to string, avoiding locale-dependent issues.
+ * Overridden by subclasses to convert a BigNumber to an instance of the subclass.
*
- * @see https://github.com/brick/math/pull/20
+ * @throws RoundingNecessaryException If the value cannot be converted.
*
- * @param float $float
- *
- * @return string
- *
- * @psalm-pure
- * @psalm-suppress ImpureFunctionCall
+ * @pure
*/
- private static function floatToString(float $float) : string
- {
- $currentLocale = \setlocale(LC_NUMERIC, '0');
- \setlocale(LC_NUMERIC, 'C');
-
- $result = (string) $float;
-
- \setlocale(LC_NUMERIC, $currentLocale);
-
- return $result;
- }
+ abstract protected static function from(BigNumber $number): static;
/**
- * Proxy method to access protected constructors from sibling classes.
+ * Proxy method to access BigInteger's protected constructor from sibling classes.
*
+ * @pure
* @internal
- *
- * @param mixed ...$args The arguments to the constructor.
- *
- * @return static
- *
- * @psalm-pure
- * @psalm-suppress TooManyArguments
- * @psalm-suppress UnsafeInstantiation
*/
- protected static function create(... $args) : BigNumber
+ final protected function newBigInteger(string $value) : BigInteger
{
- return new static(... $args);
+ return new BigInteger($value);
+ }
+
+ /**
+ * Proxy method to access BigDecimal's protected constructor from sibling classes.
+ *
+ * @pure
+ * @internal
+ */
+ final protected function newBigDecimal(string $value, int $scale = 0) : BigDecimal
+ {
+ return new BigDecimal($value, $scale);
+ }
+
+ /**
+ * Proxy method to access BigRational's protected constructor from sibling classes.
+ *
+ * @pure
+ * @internal
+ */
+ final protected function newBigRational(BigInteger $numerator, BigInteger $denominator, bool $checkDenominator) : BigRational
+ {
+ return new BigRational($numerator, $denominator, $checkDenominator);
}
/**
@@ -198,16 +216,12 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
* @param BigNumber|int|float|string ...$values The numbers to compare. All the numbers need to be convertible
* to an instance of the class this method is called on.
*
- * @return static The minimum value.
- *
* @throws \InvalidArgumentException If no values are given.
* @throws MathException If an argument is not valid.
*
- * @psalm-suppress LessSpecificReturnStatement
- * @psalm-suppress MoreSpecificReturnType
- * @psalm-pure
+ * @pure
*/
- public static function min(...$values) : BigNumber
+ final public static function min(BigNumber|int|float|string ...$values) : static
{
$min = null;
@@ -232,16 +246,12 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
* @param BigNumber|int|float|string ...$values The numbers to compare. All the numbers need to be convertible
* to an instance of the class this method is called on.
*
- * @return static The maximum value.
- *
* @throws \InvalidArgumentException If no values are given.
* @throws MathException If an argument is not valid.
*
- * @psalm-suppress LessSpecificReturnStatement
- * @psalm-suppress MoreSpecificReturnType
- * @psalm-pure
+ * @pure
*/
- public static function max(...$values) : BigNumber
+ final public static function max(BigNumber|int|float|string ...$values) : static
{
$max = null;
@@ -263,50 +273,43 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
/**
* Returns the sum of the given values.
*
- * @param BigNumber|int|float|string ...$values The numbers to add. All the numbers need to be convertible
- * to an instance of the class this method is called on.
+ * When called on BigNumber, sum() accepts any supported type and returns a result whose type is the widest among
+ * the given values (BigInteger < BigDecimal < BigRational).
*
- * @return static The sum.
+ * When called on BigInteger, BigDecimal, or BigRational, sum() requires that all values can be converted to that
+ * specific subclass, and returns a result of the same type.
+ *
+ * @param BigNumber|int|float|string ...$values The values to add. All values must be convertible to the class on
+ * which this method is called.
*
* @throws \InvalidArgumentException If no values are given.
* @throws MathException If an argument is not valid.
*
- * @psalm-suppress LessSpecificReturnStatement
- * @psalm-suppress MoreSpecificReturnType
- * @psalm-pure
+ * @pure
*/
- public static function sum(...$values) : BigNumber
+ final public static function sum(BigNumber|int|float|string ...$values) : static
{
- /** @var BigNumber|null $sum */
- $sum = null;
+ $first = array_shift($values);
- foreach ($values as $value) {
- $value = static::of($value);
-
- $sum = $sum === null ? $value : self::add($sum, $value);
- }
-
- if ($sum === null) {
+ if ($first === null) {
throw new \InvalidArgumentException(__METHOD__ . '() expects at least one value.');
}
+ $sum = static::of($first);
+
+ foreach ($values as $value) {
+ $sum = self::add($sum, static::of($value));
+ }
+
+ assert($sum instanceof static);
+
return $sum;
}
/**
* Adds two BigNumber instances in the correct order to avoid a RoundingNecessaryException.
*
- * @todo This could be better resolved by creating an abstract protected method in BigNumber, and leaving to
- * concrete classes the responsibility to perform the addition themselves or delegate it to the given number,
- * depending on their ability to perform the operation. This will also require a version bump because we're
- * potentially breaking custom BigNumber implementations (if any...)
- *
- * @param BigNumber $a
- * @param BigNumber $b
- *
- * @return BigNumber
- *
- * @psalm-pure
+ * @pure
*/
private static function add(BigNumber $a, BigNumber $b) : BigNumber
{
@@ -326,49 +329,34 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
return $b->plus($a);
}
- /** @var BigInteger $a */
-
return $a->plus($b);
}
/**
- * Removes optional leading zeros and + sign from the given number.
+ * Removes optional leading zeros and applies sign.
*
- * @param string $number The number, validated as a non-empty string of digits with optional leading sign.
+ * @param string|null $sign The sign, '+' or '-', optional. Null is allowed for convenience and treated as '+'.
+ * @param string $number The number, validated as a string of digits.
*
- * @return string
- *
- * @psalm-pure
+ * @pure
*/
- private static function cleanUp(string $number) : string
+ private static function cleanUp(string|null $sign, string $number) : string
{
- $firstChar = $number[0];
-
- if ($firstChar === '+' || $firstChar === '-') {
- $number = \substr($number, 1);
- }
-
$number = \ltrim($number, '0');
if ($number === '') {
return '0';
}
- if ($firstChar === '-') {
- return '-' . $number;
- }
-
- return $number;
+ return $sign === '-' ? '-' . $number : $number;
}
/**
* Checks if this number is equal to the given one.
*
- * @param BigNumber|int|float|string $that
- *
- * @return bool
+ * @pure
*/
- public function isEqualTo($that) : bool
+ final public function isEqualTo(BigNumber|int|float|string $that) : bool
{
return $this->compareTo($that) === 0;
}
@@ -376,11 +364,9 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
/**
* Checks if this number is strictly lower than the given one.
*
- * @param BigNumber|int|float|string $that
- *
- * @return bool
+ * @pure
*/
- public function isLessThan($that) : bool
+ final public function isLessThan(BigNumber|int|float|string $that) : bool
{
return $this->compareTo($that) < 0;
}
@@ -388,11 +374,9 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
/**
* Checks if this number is lower than or equal to the given one.
*
- * @param BigNumber|int|float|string $that
- *
- * @return bool
+ * @pure
*/
- public function isLessThanOrEqualTo($that) : bool
+ final public function isLessThanOrEqualTo(BigNumber|int|float|string $that) : bool
{
return $this->compareTo($that) <= 0;
}
@@ -400,11 +384,9 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
/**
* Checks if this number is strictly greater than the given one.
*
- * @param BigNumber|int|float|string $that
- *
- * @return bool
+ * @pure
*/
- public function isGreaterThan($that) : bool
+ final public function isGreaterThan(BigNumber|int|float|string $that) : bool
{
return $this->compareTo($that) > 0;
}
@@ -412,11 +394,9 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
/**
* Checks if this number is greater than or equal to the given one.
*
- * @param BigNumber|int|float|string $that
- *
- * @return bool
+ * @pure
*/
- public function isGreaterThanOrEqualTo($that) : bool
+ final public function isGreaterThanOrEqualTo(BigNumber|int|float|string $that) : bool
{
return $this->compareTo($that) >= 0;
}
@@ -424,9 +404,9 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
/**
* Checks if this number equals zero.
*
- * @return bool
+ * @pure
*/
- public function isZero() : bool
+ final public function isZero() : bool
{
return $this->getSign() === 0;
}
@@ -434,9 +414,9 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
/**
* Checks if this number is strictly negative.
*
- * @return bool
+ * @pure
*/
- public function isNegative() : bool
+ final public function isNegative() : bool
{
return $this->getSign() < 0;
}
@@ -444,9 +424,9 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
/**
* Checks if this number is negative or zero.
*
- * @return bool
+ * @pure
*/
- public function isNegativeOrZero() : bool
+ final public function isNegativeOrZero() : bool
{
return $this->getSign() <= 0;
}
@@ -454,9 +434,9 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
/**
* Checks if this number is strictly positive.
*
- * @return bool
+ * @pure
*/
- public function isPositive() : bool
+ final public function isPositive() : bool
{
return $this->getSign() > 0;
}
@@ -464,9 +444,9 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
/**
* Checks if this number is positive or zero.
*
- * @return bool
+ * @pure
*/
- public function isPositiveOrZero() : bool
+ final public function isPositiveOrZero() : bool
{
return $this->getSign() >= 0;
}
@@ -474,58 +454,64 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
/**
* Returns the sign of this number.
*
- * @return int -1 if the number is negative, 0 if zero, 1 if positive.
+ * Returns -1 if the number is negative, 0 if zero, 1 if positive.
+ *
+ * @return -1|0|1
+ *
+ * @pure
*/
abstract public function getSign() : int;
/**
* Compares this number to the given one.
*
- * @param BigNumber|int|float|string $that
+ * Returns -1 if `$this` is lower than, 0 if equal to, 1 if greater than `$that`.
*
- * @return int [-1,0,1] If `$this` is lower than, equal to, or greater than `$that`.
+ * @return -1|0|1
*
* @throws MathException If the number is not valid.
+ *
+ * @pure
*/
- abstract public function compareTo($that) : int;
+ abstract public function compareTo(BigNumber|int|float|string $that) : int;
/**
* Converts this number to a BigInteger.
*
- * @return BigInteger The converted number.
- *
* @throws RoundingNecessaryException If this number cannot be converted to a BigInteger without rounding.
+ *
+ * @pure
*/
abstract public function toBigInteger() : BigInteger;
/**
* Converts this number to a BigDecimal.
*
- * @return BigDecimal The converted number.
- *
* @throws RoundingNecessaryException If this number cannot be converted to a BigDecimal without rounding.
+ *
+ * @pure
*/
abstract public function toBigDecimal() : BigDecimal;
/**
* Converts this number to a BigRational.
*
- * @return BigRational The converted number.
+ * @pure
*/
abstract public function toBigRational() : BigRational;
/**
* Converts this number to a BigDecimal with the given scale, using rounding if necessary.
*
- * @param int $scale The scale of the resulting `BigDecimal`.
- * @param int $roundingMode A `RoundingMode` constant.
- *
- * @return BigDecimal
+ * @param int $scale The scale of the resulting `BigDecimal`.
+ * @param RoundingMode $roundingMode An optional rounding mode, defaults to UNNECESSARY.
*
* @throws RoundingNecessaryException If this number cannot be converted to the given scale without rounding.
* This only applies when RoundingMode::UNNECESSARY is used.
+ *
+ * @pure
*/
- abstract public function toScale(int $scale, int $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal;
+ abstract public function toScale(int $scale, RoundingMode $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal;
/**
* Returns the exact value of this number as a native integer.
@@ -533,9 +519,9 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
* If this number cannot be converted to a native integer without losing precision, an exception is thrown.
* Note that the acceptable range for an integer depends on the platform and differs for 32-bit and 64-bit.
*
- * @return int The converted value.
- *
* @throws MathException If this number cannot be exactly converted to a native integer.
+ *
+ * @pure
*/
abstract public function toInt() : int;
@@ -548,7 +534,7 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
* If the number is greater than the largest representable floating point number, positive infinity is returned.
* If the number is less than the smallest representable floating point number, negative infinity is returned.
*
- * @return float The converted value.
+ * @pure
*/
abstract public function toFloat() : float;
@@ -558,14 +544,12 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
* The output of this method can be parsed by the `of()` factory method;
* this will yield an object equal to this one, without any information loss.
*
- * @return string
+ * @pure
*/
abstract public function __toString() : string;
- /**
- * {@inheritdoc}
- */
- public function jsonSerialize() : string
+ #[Override]
+ final public function jsonSerialize() : string
{
return $this->__toString();
}
diff --git a/vendor/brick/math/src/BigRational.php b/vendor/brick/math/src/BigRational.php
index bee094f..56045e5 100644
--- a/vendor/brick/math/src/BigRational.php
+++ b/vendor/brick/math/src/BigRational.php
@@ -8,29 +8,24 @@ use Brick\Math\Exception\DivisionByZeroException;
use Brick\Math\Exception\MathException;
use Brick\Math\Exception\NumberFormatException;
use Brick\Math\Exception\RoundingNecessaryException;
+use Override;
/**
* An arbitrarily large rational number.
*
* This class is immutable.
- *
- * @psalm-immutable
*/
-final class BigRational extends BigNumber
+final readonly class BigRational extends BigNumber
{
/**
* The numerator.
- *
- * @var BigInteger
*/
- private $numerator;
+ private BigInteger $numerator;
/**
* The denominator. Always strictly positive.
- *
- * @var BigInteger
*/
- private $denominator;
+ private BigInteger $denominator;
/**
* Protected constructor. Use a factory method to obtain an instance.
@@ -40,6 +35,8 @@ final class BigRational extends BigNumber
* @param bool $checkDenominator Whether to check the denominator for negative and zero.
*
* @throws DivisionByZeroException If the denominator is zero.
+ *
+ * @pure
*/
protected function __construct(BigInteger $numerator, BigInteger $denominator, bool $checkDenominator)
{
@@ -58,20 +55,10 @@ final class BigRational extends BigNumber
$this->denominator = $denominator;
}
- /**
- * Creates a BigRational of the given value.
- *
- * @param BigNumber|int|float|string $value
- *
- * @return BigRational
- *
- * @throws MathException If the value cannot be converted to a BigRational.
- *
- * @psalm-pure
- */
- public static function of($value) : BigNumber
+ #[Override]
+ protected static function from(BigNumber $number): static
{
- return parent::of($value)->toBigRational();
+ return $number->toBigRational();
}
/**
@@ -83,16 +70,16 @@ final class BigRational extends BigNumber
* @param BigNumber|int|float|string $numerator The numerator. Must be convertible to a BigInteger.
* @param BigNumber|int|float|string $denominator The denominator. Must be convertible to a BigInteger.
*
- * @return BigRational
- *
* @throws NumberFormatException If an argument does not represent a valid number.
* @throws RoundingNecessaryException If an argument represents a non-integer number.
* @throws DivisionByZeroException If the denominator is zero.
*
- * @psalm-pure
+ * @pure
*/
- public static function nd($numerator, $denominator) : BigRational
- {
+ public static function nd(
+ BigNumber|int|float|string $numerator,
+ BigNumber|int|float|string $denominator,
+ ) : BigRational {
$numerator = BigInteger::of($numerator);
$denominator = BigInteger::of($denominator);
@@ -102,16 +89,11 @@ final class BigRational extends BigNumber
/**
* Returns a BigRational representing zero.
*
- * @return BigRational
- *
- * @psalm-pure
+ * @pure
*/
public static function zero() : BigRational
{
- /**
- * @psalm-suppress ImpureStaticVariable
- * @var BigRational|null $zero
- */
+ /** @var BigRational|null $zero */
static $zero;
if ($zero === null) {
@@ -124,16 +106,11 @@ final class BigRational extends BigNumber
/**
* Returns a BigRational representing one.
*
- * @return BigRational
- *
- * @psalm-pure
+ * @pure
*/
public static function one() : BigRational
{
- /**
- * @psalm-suppress ImpureStaticVariable
- * @var BigRational|null $one
- */
+ /** @var BigRational|null $one */
static $one;
if ($one === null) {
@@ -146,16 +123,11 @@ final class BigRational extends BigNumber
/**
* Returns a BigRational representing ten.
*
- * @return BigRational
- *
- * @psalm-pure
+ * @pure
*/
public static function ten() : BigRational
{
- /**
- * @psalm-suppress ImpureStaticVariable
- * @var BigRational|null $ten
- */
+ /** @var BigRational|null $ten */
static $ten;
if ($ten === null) {
@@ -166,7 +138,7 @@ final class BigRational extends BigNumber
}
/**
- * @return BigInteger
+ * @pure
*/
public function getNumerator() : BigInteger
{
@@ -174,7 +146,7 @@ final class BigRational extends BigNumber
}
/**
- * @return BigInteger
+ * @pure
*/
public function getDenominator() : BigInteger
{
@@ -184,7 +156,7 @@ final class BigRational extends BigNumber
/**
* Returns the quotient of the division of the numerator by the denominator.
*
- * @return BigInteger
+ * @pure
*/
public function quotient() : BigInteger
{
@@ -194,7 +166,7 @@ final class BigRational extends BigNumber
/**
* Returns the remainder of the division of the numerator by the denominator.
*
- * @return BigInteger
+ * @pure
*/
public function remainder() : BigInteger
{
@@ -204,7 +176,9 @@ final class BigRational extends BigNumber
/**
* Returns the quotient and remainder of the division of the numerator by the denominator.
*
- * @return BigInteger[]
+ * @return array{BigInteger, BigInteger}
+ *
+ * @pure
*/
public function quotientAndRemainder() : array
{
@@ -216,11 +190,11 @@ final class BigRational extends BigNumber
*
* @param BigNumber|int|float|string $that The number to add.
*
- * @return BigRational The result.
- *
* @throws MathException If the number is not valid.
+ *
+ * @pure
*/
- public function plus($that) : BigRational
+ public function plus(BigNumber|int|float|string $that) : BigRational
{
$that = BigRational::of($that);
@@ -236,11 +210,11 @@ final class BigRational extends BigNumber
*
* @param BigNumber|int|float|string $that The number to subtract.
*
- * @return BigRational The result.
- *
* @throws MathException If the number is not valid.
+ *
+ * @pure
*/
- public function minus($that) : BigRational
+ public function minus(BigNumber|int|float|string $that) : BigRational
{
$that = BigRational::of($that);
@@ -256,11 +230,11 @@ final class BigRational extends BigNumber
*
* @param BigNumber|int|float|string $that The multiplier.
*
- * @return BigRational The result.
- *
* @throws MathException If the multiplier is not a valid number.
+ *
+ * @pure
*/
- public function multipliedBy($that) : BigRational
+ public function multipliedBy(BigNumber|int|float|string $that) : BigRational
{
$that = BigRational::of($that);
@@ -275,11 +249,11 @@ final class BigRational extends BigNumber
*
* @param BigNumber|int|float|string $that The divisor.
*
- * @return BigRational The result.
- *
* @throws MathException If the divisor is not a valid number, or is zero.
+ *
+ * @pure
*/
- public function dividedBy($that) : BigRational
+ public function dividedBy(BigNumber|int|float|string $that) : BigRational
{
$that = BigRational::of($that);
@@ -292,11 +266,9 @@ final class BigRational extends BigNumber
/**
* Returns this number exponentiated to the given value.
*
- * @param int $exponent The exponent.
- *
- * @return BigRational The result.
- *
* @throws \InvalidArgumentException If the exponent is not in the range 0 to 1,000,000.
+ *
+ * @pure
*/
public function power(int $exponent) : BigRational
{
@@ -322,9 +294,9 @@ final class BigRational extends BigNumber
*
* The reciprocal has the numerator and denominator swapped.
*
- * @return BigRational
- *
* @throws DivisionByZeroException If the numerator is zero.
+ *
+ * @pure
*/
public function reciprocal() : BigRational
{
@@ -334,7 +306,7 @@ final class BigRational extends BigNumber
/**
* Returns the absolute value of this BigRational.
*
- * @return BigRational
+ * @pure
*/
public function abs() : BigRational
{
@@ -344,7 +316,7 @@ final class BigRational extends BigNumber
/**
* Returns the negated value of this BigRational.
*
- * @return BigRational
+ * @pure
*/
public function negated() : BigRational
{
@@ -354,7 +326,7 @@ final class BigRational extends BigNumber
/**
* Returns the simplified value of this BigRational.
*
- * @return BigRational
+ * @pure
*/
public function simplified() : BigRational
{
@@ -366,25 +338,19 @@ final class BigRational extends BigNumber
return new BigRational($numerator, $denominator, false);
}
- /**
- * {@inheritdoc}
- */
- public function compareTo($that) : int
+ #[Override]
+ public function compareTo(BigNumber|int|float|string $that) : int
{
return $this->minus($that)->getSign();
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function getSign() : int
{
return $this->numerator->getSign();
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function toBigInteger() : BigInteger
{
$simplified = $this->simplified();
@@ -396,49 +362,38 @@ final class BigRational extends BigNumber
return $simplified->numerator;
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function toBigDecimal() : BigDecimal
{
return $this->numerator->toBigDecimal()->exactlyDividedBy($this->denominator);
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function toBigRational() : BigRational
{
return $this;
}
- /**
- * {@inheritdoc}
- */
- public function toScale(int $scale, int $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal
+ #[Override]
+ public function toScale(int $scale, RoundingMode $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal
{
return $this->numerator->toBigDecimal()->dividedBy($this->denominator, $scale, $roundingMode);
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function toInt() : int
{
return $this->toBigInteger()->toInt();
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function toFloat() : float
{
- return $this->numerator->toFloat() / $this->denominator->toFloat();
+ $simplified = $this->simplified();
+ return $simplified->numerator->toFloat() / $simplified->denominator->toFloat();
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function __toString() : string
{
$numerator = (string) $this->numerator;
@@ -448,7 +403,7 @@ final class BigRational extends BigNumber
return $numerator;
}
- return $this->numerator . '/' . $this->denominator;
+ return $numerator . '/' . $denominator;
}
/**
@@ -467,57 +422,20 @@ final class BigRational extends BigNumber
* This method is only here to allow unserializing the object and cannot be accessed directly.
*
* @internal
- * @psalm-suppress RedundantPropertyInitializationCheck
*
* @param array{numerator: BigInteger, denominator: BigInteger} $data
*
- * @return void
- *
* @throws \LogicException
*/
public function __unserialize(array $data): void
{
+ /** @phpstan-ignore isset.initializedProperty */
if (isset($this->numerator)) {
throw new \LogicException('__unserialize() is an internal function, it must not be called directly.');
}
+ /** @phpstan-ignore deadCode.unreachable */
$this->numerator = $data['numerator'];
$this->denominator = $data['denominator'];
}
-
- /**
- * This method is required by interface Serializable and SHOULD NOT be accessed directly.
- *
- * @internal
- *
- * @return string
- */
- public function serialize() : string
- {
- return $this->numerator . '/' . $this->denominator;
- }
-
- /**
- * This method is only here to implement interface Serializable and cannot be accessed directly.
- *
- * @internal
- * @psalm-suppress RedundantPropertyInitializationCheck
- *
- * @param string $value
- *
- * @return void
- *
- * @throws \LogicException
- */
- public function unserialize($value) : void
- {
- if (isset($this->numerator)) {
- throw new \LogicException('unserialize() is an internal function, it must not be called directly.');
- }
-
- [$numerator, $denominator] = \explode('/', $value);
-
- $this->numerator = BigInteger::of($numerator);
- $this->denominator = BigInteger::of($denominator);
- }
}
diff --git a/vendor/brick/math/src/Exception/DivisionByZeroException.php b/vendor/brick/math/src/Exception/DivisionByZeroException.php
index a4e4431..2daaf5e 100644
--- a/vendor/brick/math/src/Exception/DivisionByZeroException.php
+++ b/vendor/brick/math/src/Exception/DivisionByZeroException.php
@@ -7,12 +7,10 @@ namespace Brick\Math\Exception;
/**
* Exception thrown when a division by zero occurs.
*/
-class DivisionByZeroException extends MathException
+final class DivisionByZeroException extends MathException
{
/**
- * @return DivisionByZeroException
- *
- * @psalm-pure
+ * @pure
*/
public static function divisionByZero() : DivisionByZeroException
{
@@ -20,9 +18,7 @@ class DivisionByZeroException extends MathException
}
/**
- * @return DivisionByZeroException
- *
- * @psalm-pure
+ * @pure
*/
public static function modulusMustNotBeZero() : DivisionByZeroException
{
@@ -30,9 +26,7 @@ class DivisionByZeroException extends MathException
}
/**
- * @return DivisionByZeroException
- *
- * @psalm-pure
+ * @pure
*/
public static function denominatorMustNotBeZero() : DivisionByZeroException
{
diff --git a/vendor/brick/math/src/Exception/IntegerOverflowException.php b/vendor/brick/math/src/Exception/IntegerOverflowException.php
index e0b07d3..56f3cf8 100644
--- a/vendor/brick/math/src/Exception/IntegerOverflowException.php
+++ b/vendor/brick/math/src/Exception/IntegerOverflowException.php
@@ -9,14 +9,10 @@ use Brick\Math\BigInteger;
/**
* Exception thrown when an integer overflow occurs.
*/
-class IntegerOverflowException extends MathException
+final class IntegerOverflowException extends MathException
{
/**
- * @param BigInteger $value
- *
- * @return IntegerOverflowException
- *
- * @psalm-pure
+ * @pure
*/
public static function toIntOverflow(BigInteger $value) : IntegerOverflowException
{
diff --git a/vendor/brick/math/src/Exception/MathException.php b/vendor/brick/math/src/Exception/MathException.php
index 21fda90..8facd9c 100644
--- a/vendor/brick/math/src/Exception/MathException.php
+++ b/vendor/brick/math/src/Exception/MathException.php
@@ -6,8 +6,6 @@ namespace Brick\Math\Exception;
/**
* Base class for all math exceptions.
- *
- * This class is abstract to ensure that only fine-grained exceptions are thrown throughout the code.
*/
class MathException extends \RuntimeException
{
diff --git a/vendor/brick/math/src/Exception/NegativeNumberException.php b/vendor/brick/math/src/Exception/NegativeNumberException.php
index 4739113..73ed3a4 100644
--- a/vendor/brick/math/src/Exception/NegativeNumberException.php
+++ b/vendor/brick/math/src/Exception/NegativeNumberException.php
@@ -7,6 +7,6 @@ namespace Brick\Math\Exception;
/**
* Exception thrown when attempting to perform an unsupported operation, such as a square root, on a negative number.
*/
-class NegativeNumberException extends MathException
+final class NegativeNumberException extends MathException
{
}
diff --git a/vendor/brick/math/src/Exception/NumberFormatException.php b/vendor/brick/math/src/Exception/NumberFormatException.php
index 2fd0be7..0dcda34 100644
--- a/vendor/brick/math/src/Exception/NumberFormatException.php
+++ b/vendor/brick/math/src/Exception/NumberFormatException.php
@@ -7,14 +7,23 @@ namespace Brick\Math\Exception;
/**
* Exception thrown when attempting to create a number from a string with an invalid format.
*/
-class NumberFormatException extends MathException
+final class NumberFormatException extends MathException
{
+ /**
+ * @pure
+ */
+ public static function invalidFormat(string $value) : self
+ {
+ return new self(\sprintf(
+ 'The given value "%s" does not represent a valid number.',
+ $value,
+ ));
+ }
+
/**
* @param string $char The failing character.
*
- * @return NumberFormatException
- *
- * @psalm-pure
+ * @pure
*/
public static function charNotInAlphabet(string $char) : self
{
@@ -30,6 +39,6 @@ class NumberFormatException extends MathException
$char = '"' . $char . '"';
}
- return new self(sprintf('Char %s is not a valid character in the given alphabet.', $char));
+ return new self(\sprintf('Char %s is not a valid character in the given alphabet.', $char));
}
}
diff --git a/vendor/brick/math/src/Exception/RoundingNecessaryException.php b/vendor/brick/math/src/Exception/RoundingNecessaryException.php
index 1c61005..034a040 100644
--- a/vendor/brick/math/src/Exception/RoundingNecessaryException.php
+++ b/vendor/brick/math/src/Exception/RoundingNecessaryException.php
@@ -7,12 +7,10 @@ namespace Brick\Math\Exception;
/**
* Exception thrown when a number cannot be represented at the requested scale without rounding.
*/
-class RoundingNecessaryException extends MathException
+final class RoundingNecessaryException extends MathException
{
/**
- * @return RoundingNecessaryException
- *
- * @psalm-pure
+ * @pure
*/
public static function roundingNecessary() : RoundingNecessaryException
{
diff --git a/vendor/brick/math/src/Internal/Calculator.php b/vendor/brick/math/src/Internal/Calculator.php
index a6eac79..a5e000a 100644
--- a/vendor/brick/math/src/Internal/Calculator.php
+++ b/vendor/brick/math/src/Internal/Calculator.php
@@ -17,89 +17,25 @@ use Brick\Math\RoundingMode;
* All methods must return strings respecting this format, unless specified otherwise.
*
* @internal
- *
- * @psalm-immutable
*/
-abstract class Calculator
+abstract readonly class Calculator
{
/**
* The maximum exponent value allowed for the pow() method.
*/
- public const MAX_POWER = 1000000;
+ public const MAX_POWER = 1_000_000;
/**
* The alphabet for converting from and to base 2 to 36, lowercase.
*/
public const ALPHABET = '0123456789abcdefghijklmnopqrstuvwxyz';
- /**
- * The Calculator instance in use.
- *
- * @var Calculator|null
- */
- private static $instance;
-
- /**
- * Sets the Calculator instance to use.
- *
- * An instance is typically set only in unit tests: the autodetect is usually the best option.
- *
- * @param Calculator|null $calculator The calculator instance, or NULL to revert to autodetect.
- *
- * @return void
- */
- final public static function set(?Calculator $calculator) : void
- {
- self::$instance = $calculator;
- }
-
- /**
- * Returns the Calculator instance to use.
- *
- * If none has been explicitly set, the fastest available implementation will be returned.
- *
- * @return Calculator
- *
- * @psalm-pure
- * @psalm-suppress ImpureStaticProperty
- */
- final public static function get() : Calculator
- {
- if (self::$instance === null) {
- /** @psalm-suppress ImpureMethodCall */
- self::$instance = self::detect();
- }
-
- return self::$instance;
- }
-
- /**
- * Returns the fastest available Calculator implementation.
- *
- * @codeCoverageIgnore
- *
- * @return Calculator
- */
- private static function detect() : Calculator
- {
- if (\extension_loaded('gmp')) {
- return new Calculator\GmpCalculator();
- }
-
- if (\extension_loaded('bcmath')) {
- return new Calculator\BcMathCalculator();
- }
-
- return new Calculator\NativeCalculator();
- }
-
/**
* Extracts the sign & digits of the operands.
*
- * @param string $a The first operand.
- * @param string $b The second operand.
- *
* @return array{bool, bool, string, string} Whether $a and $b are negative, followed by their digits.
+ *
+ * @pure
*/
final protected function init(string $a, string $b) : array
{
@@ -115,9 +51,7 @@ abstract class Calculator
/**
* Returns the absolute value of a number.
*
- * @param string $n The number.
- *
- * @return string The absolute value.
+ * @pure
*/
final public function abs(string $n) : string
{
@@ -127,9 +61,7 @@ abstract class Calculator
/**
* Negates a number.
*
- * @param string $n The number.
- *
- * @return string The negated value.
+ * @pure
*/
final public function neg(string $n) : string
{
@@ -147,10 +79,11 @@ abstract class Calculator
/**
* Compares two numbers.
*
- * @param string $a The first number.
- * @param string $b The second number.
+ * Returns -1 if the first number is less than, 0 if equal to, 1 if greater than the second number.
*
- * @return int [-1, 0, 1] If the first number is less than, equal to, or greater than the second number.
+ * @return -1|0|1
+ *
+ * @pure
*/
final public function cmp(string $a, string $b) : int
{
@@ -181,30 +114,21 @@ abstract class Calculator
/**
* Adds two numbers.
*
- * @param string $a The augend.
- * @param string $b The addend.
- *
- * @return string The sum.
+ * @pure
*/
abstract public function add(string $a, string $b) : string;
/**
* Subtracts two numbers.
*
- * @param string $a The minuend.
- * @param string $b The subtrahend.
- *
- * @return string The difference.
+ * @pure
*/
abstract public function sub(string $a, string $b) : string;
/**
* Multiplies two numbers.
*
- * @param string $a The multiplicand.
- * @param string $b The multiplier.
- *
- * @return string The product.
+ * @pure
*/
abstract public function mul(string $a, string $b) : string;
@@ -215,6 +139,8 @@ abstract class Calculator
* @param string $b The divisor, must not be zero.
*
* @return string The quotient.
+ *
+ * @pure
*/
abstract public function divQ(string $a, string $b) : string;
@@ -225,6 +151,8 @@ abstract class Calculator
* @param string $b The divisor, must not be zero.
*
* @return string The remainder.
+ *
+ * @pure
*/
abstract public function divR(string $a, string $b) : string;
@@ -234,7 +162,9 @@ abstract class Calculator
* @param string $a The dividend.
* @param string $b The divisor, must not be zero.
*
- * @return string[] An array containing the quotient and remainder.
+ * @return array{string, string} An array containing the quotient and remainder.
+ *
+ * @pure
*/
abstract public function divQR(string $a, string $b) : array;
@@ -245,14 +175,15 @@ abstract class Calculator
* @param int $e The exponent, validated as an integer between 0 and MAX_POWER.
*
* @return string The power.
+ *
+ * @pure
*/
abstract public function pow(string $a, int $e) : string;
/**
- * @param string $a
* @param string $b The modulus; must not be zero.
*
- * @return string
+ * @pure
*/
public function mod(string $a, string $b) : string
{
@@ -266,10 +197,9 @@ abstract class Calculator
*
* This method can be overridden by the concrete implementation if the underlying library has built-in support.
*
- * @param string $x
* @param string $m The modulus; must not be negative or zero.
*
- * @return string|null
+ * @pure
*/
public function modInverse(string $x, string $m) : ?string
{
@@ -283,9 +213,7 @@ abstract class Calculator
$modVal = $this->mod($x, $m);
}
- $x = '0';
- $y = '0';
- $g = $this->gcdExtended($modVal, $m, $x, $y);
+ [$g, $x] = $this->gcdExtended($modVal, $m);
if ($g !== '1') {
return null;
@@ -301,7 +229,7 @@ abstract class Calculator
* @param string $exp The exponent; must be positive or zero.
* @param string $mod The modulus; must be strictly positive.
*
- * @return string The power.
+ * @pure
*/
abstract public function modPow(string $base, string $exp, string $mod) : string;
@@ -311,10 +239,9 @@ abstract class Calculator
* This method can be overridden by the concrete implementation if the underlying library
* has built-in support for GCD calculations.
*
- * @param string $a The first number.
- * @param string $b The second number.
- *
* @return string The GCD, always positive, or zero if both arguments are zero.
+ *
+ * @pure
*/
public function gcd(string $a, string $b) : string
{
@@ -329,24 +256,23 @@ abstract class Calculator
return $this->gcd($b, $this->divR($a, $b));
}
- private function gcdExtended(string $a, string $b, string &$x, string &$y) : string
+ /**
+ * @return array{string, string, string} GCD, X, Y
+ *
+ * @pure
+ */
+ private function gcdExtended(string $a, string $b) : array
{
if ($a === '0') {
- $x = '0';
- $y = '1';
-
- return $b;
+ return [$b, '0', '1'];
}
- $x1 = '0';
- $y1 = '0';
-
- $gcd = $this->gcdExtended($this->mod($b, $a), $a, $x1, $y1);
+ [$gcd, $x1, $y1] = $this->gcdExtended($this->mod($b, $a), $a);
$x = $this->sub($y1, $this->mul($this->divQ($b, $a), $x1));
$y = $x1;
- return $gcd;
+ return [$gcd, $x, $y];
}
/**
@@ -355,9 +281,7 @@ abstract class Calculator
* The result is the largest x such that x² ≤ n.
* The input MUST NOT be negative.
*
- * @param string $n The number.
- *
- * @return string The square root.
+ * @pure
*/
abstract public function sqrt(string $n) : string;
@@ -371,6 +295,8 @@ abstract class Calculator
* @param int $base The base of the number, validated from 2 to 36.
*
* @return string The converted number, following the Calculator conventions.
+ *
+ * @pure
*/
public function fromBase(string $number, int $base) : string
{
@@ -387,6 +313,8 @@ abstract class Calculator
* @param int $base The base to convert to, validated from 2 to 36.
*
* @return string The converted number, lowercase.
+ *
+ * @pure
*/
public function toBase(string $number, int $base) : string
{
@@ -414,6 +342,8 @@ abstract class Calculator
* @param int $base The base of the number, validated from 2 to alphabet length.
*
* @return string The number in base 10, following the Calculator conventions.
+ *
+ * @pure
*/
final public function fromArbitraryBase(string $number, string $alphabet, int $base) : string
{
@@ -460,6 +390,8 @@ abstract class Calculator
* @param int $base The base to convert to, validated from 2 to alphabet length.
*
* @return string The converted number in the given alphabet.
+ *
+ * @pure
*/
final public function toArbitraryBase(string $number, string $alphabet, int $base) : string
{
@@ -485,16 +417,15 @@ abstract class Calculator
*
* Rounding is performed when the remainder of the division is not zero.
*
- * @param string $a The dividend.
- * @param string $b The divisor, must not be zero.
- * @param int $roundingMode The rounding mode.
+ * @param string $a The dividend.
+ * @param string $b The divisor, must not be zero.
+ * @param RoundingMode $roundingMode The rounding mode.
*
- * @return string
- *
- * @throws \InvalidArgumentException If the rounding mode is invalid.
* @throws RoundingNecessaryException If RoundingMode::UNNECESSARY is provided but rounding is necessary.
+ *
+ * @pure
*/
- final public function divRound(string $a, string $b, int $roundingMode) : string
+ final public function divRound(string $a, string $b, RoundingMode $roundingMode) : string
{
[$quotient, $remainder] = $this->divQR($a, $b);
@@ -553,9 +484,6 @@ abstract class Calculator
$lastDigitIsEven = ($lastDigit % 2 === 0);
$increment = $lastDigitIsEven ? $discardedFractionSign() > 0 : $discardedFractionSign() >= 0;
break;
-
- default:
- throw new \InvalidArgumentException('Invalid rounding mode.');
}
if ($increment) {
@@ -571,10 +499,7 @@ abstract class Calculator
* This method can be overridden by the concrete implementation if the underlying library
* has built-in support for bitwise operations.
*
- * @param string $a
- * @param string $b
- *
- * @return string
+ * @pure
*/
public function and(string $a, string $b) : string
{
@@ -587,10 +512,7 @@ abstract class Calculator
* This method can be overridden by the concrete implementation if the underlying library
* has built-in support for bitwise operations.
*
- * @param string $a
- * @param string $b
- *
- * @return string
+ * @pure
*/
public function or(string $a, string $b) : string
{
@@ -603,10 +525,7 @@ abstract class Calculator
* This method can be overridden by the concrete implementation if the underlying library
* has built-in support for bitwise operations.
*
- * @param string $a
- * @param string $b
- *
- * @return string
+ * @pure
*/
public function xor(string $a, string $b) : string
{
@@ -616,11 +535,11 @@ abstract class Calculator
/**
* Performs a bitwise operation on a decimal number.
*
- * @param string $operator The operator to use, must be "and", "or" or "xor".
- * @param string $a The left operand.
- * @param string $b The right operand.
+ * @param 'and'|'or'|'xor' $operator The operator to use.
+ * @param string $a The left operand.
+ * @param string $b The right operand.
*
- * @return string
+ * @pure
*/
private function bitwise(string $operator, string $a, string $b) : string
{
@@ -645,27 +564,17 @@ abstract class Calculator
$bBin = $this->twosComplement($bBin);
}
- switch ($operator) {
- case 'and':
- $value = $aBin & $bBin;
- $negative = ($aNeg and $bNeg);
- break;
+ $value = match ($operator) {
+ 'and' => $aBin & $bBin,
+ 'or' => $aBin | $bBin,
+ 'xor' => $aBin ^ $bBin,
+ };
- case 'or':
- $value = $aBin | $bBin;
- $negative = ($aNeg or $bNeg);
- break;
-
- case 'xor':
- $value = $aBin ^ $bBin;
- $negative = ($aNeg xor $bNeg);
- break;
-
- // @codeCoverageIgnoreStart
- default:
- throw new \InvalidArgumentException('Invalid bitwise operator.');
- // @codeCoverageIgnoreEnd
- }
+ $negative = match ($operator) {
+ 'and' => $aNeg and $bNeg,
+ 'or' => $aNeg or $bNeg,
+ 'xor' => $aNeg xor $bNeg,
+ };
if ($negative) {
$value = $this->twosComplement($value);
@@ -679,7 +588,7 @@ abstract class Calculator
/**
* @param string $number A positive, binary number.
*
- * @return string
+ * @pure
*/
private function twosComplement(string $number) : string
{
@@ -710,7 +619,7 @@ abstract class Calculator
*
* @param string $number The number to convert, positive or zero, only digits.
*
- * @return string
+ * @pure
*/
private function toBinary(string $number) : string
{
@@ -729,7 +638,7 @@ abstract class Calculator
*
* @param string $bytes The bytes representing the number.
*
- * @return string
+ * @pure
*/
private function toDecimal(string $bytes) : string
{
diff --git a/vendor/brick/math/src/Internal/Calculator/BcMathCalculator.php b/vendor/brick/math/src/Internal/Calculator/BcMathCalculator.php
index 6632b37..5ba961e 100644
--- a/vendor/brick/math/src/Internal/Calculator/BcMathCalculator.php
+++ b/vendor/brick/math/src/Internal/Calculator/BcMathCalculator.php
@@ -5,110 +5,67 @@ declare(strict_types=1);
namespace Brick\Math\Internal\Calculator;
use Brick\Math\Internal\Calculator;
+use Override;
/**
* Calculator implementation built around the bcmath library.
*
* @internal
- *
- * @psalm-immutable
*/
-class BcMathCalculator extends Calculator
+final readonly class BcMathCalculator extends Calculator
{
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function add(string $a, string $b) : string
{
return \bcadd($a, $b, 0);
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function sub(string $a, string $b) : string
{
return \bcsub($a, $b, 0);
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function mul(string $a, string $b) : string
{
return \bcmul($a, $b, 0);
}
- /**
- * {@inheritdoc}
- *
- * @psalm-suppress InvalidNullableReturnType
- * @psalm-suppress NullableReturnStatement
- */
+ #[Override]
public function divQ(string $a, string $b) : string
{
return \bcdiv($a, $b, 0);
}
- /**
- * {@inheritdoc}
- *
- * @psalm-suppress InvalidNullableReturnType
- * @psalm-suppress NullableReturnStatement
- */
+ #[Override]
public function divR(string $a, string $b) : string
{
- if (version_compare(PHP_VERSION, '7.2') >= 0) {
- return \bcmod($a, $b, 0);
- }
-
- return \bcmod($a, $b);
+ return \bcmod($a, $b, 0);
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function divQR(string $a, string $b) : array
{
$q = \bcdiv($a, $b, 0);
-
- if (version_compare(PHP_VERSION, '7.2') >= 0) {
- $r = \bcmod($a, $b, 0);
- } else {
- $r = \bcmod($a, $b);
- }
-
- assert($q !== null);
- assert($r !== null);
+ $r = \bcmod($a, $b, 0);
return [$q, $r];
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function pow(string $a, int $e) : string
{
return \bcpow($a, (string) $e, 0);
}
- /**
- * {@inheritdoc}
- *
- * @psalm-suppress InvalidNullableReturnType
- * @psalm-suppress NullableReturnStatement
- */
+ #[Override]
public function modPow(string $base, string $exp, string $mod) : string
{
return \bcpowmod($base, $exp, $mod, 0);
}
- /**
- * {@inheritDoc}
- *
- * @psalm-suppress NullableReturnStatement
- * @psalm-suppress InvalidNullableReturnType
- */
+ #[Override]
public function sqrt(string $n) : string
{
return \bcsqrt($n, 0);
diff --git a/vendor/brick/math/src/Internal/Calculator/GmpCalculator.php b/vendor/brick/math/src/Internal/Calculator/GmpCalculator.php
index 52d1880..c0f9bd5 100644
--- a/vendor/brick/math/src/Internal/Calculator/GmpCalculator.php
+++ b/vendor/brick/math/src/Internal/Calculator/GmpCalculator.php
@@ -5,80 +5,68 @@ declare(strict_types=1);
namespace Brick\Math\Internal\Calculator;
use Brick\Math\Internal\Calculator;
+use GMP;
+use Override;
/**
* Calculator implementation built around the GMP library.
*
* @internal
- *
- * @psalm-immutable
*/
-class GmpCalculator extends Calculator
+final readonly class GmpCalculator extends Calculator
{
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function add(string $a, string $b) : string
{
return \gmp_strval(\gmp_add($a, $b));
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function sub(string $a, string $b) : string
{
return \gmp_strval(\gmp_sub($a, $b));
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function mul(string $a, string $b) : string
{
return \gmp_strval(\gmp_mul($a, $b));
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function divQ(string $a, string $b) : string
{
return \gmp_strval(\gmp_div_q($a, $b));
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function divR(string $a, string $b) : string
{
return \gmp_strval(\gmp_div_r($a, $b));
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function divQR(string $a, string $b) : array
{
[$q, $r] = \gmp_div_qr($a, $b);
+ /**
+ * @var GMP $q
+ * @var GMP $r
+ */
return [
\gmp_strval($q),
\gmp_strval($r)
];
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function pow(string $a, int $e) : string
{
return \gmp_strval(\gmp_pow($a, $e));
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function modInverse(string $x, string $m) : ?string
{
$result = \gmp_invert($x, $m);
@@ -90,65 +78,49 @@ class GmpCalculator extends Calculator
return \gmp_strval($result);
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function modPow(string $base, string $exp, string $mod) : string
{
return \gmp_strval(\gmp_powm($base, $exp, $mod));
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function gcd(string $a, string $b) : string
{
return \gmp_strval(\gmp_gcd($a, $b));
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function fromBase(string $number, int $base) : string
{
return \gmp_strval(\gmp_init($number, $base));
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function toBase(string $number, int $base) : string
{
return \gmp_strval($number, $base);
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function and(string $a, string $b) : string
{
return \gmp_strval(\gmp_and($a, $b));
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function or(string $a, string $b) : string
{
return \gmp_strval(\gmp_or($a, $b));
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function xor(string $a, string $b) : string
{
return \gmp_strval(\gmp_xor($a, $b));
}
- /**
- * {@inheritDoc}
- */
+ #[Override]
public function sqrt(string $n) : string
{
return \gmp_strval(\gmp_sqrt($n));
diff --git a/vendor/brick/math/src/Internal/Calculator/NativeCalculator.php b/vendor/brick/math/src/Internal/Calculator/NativeCalculator.php
index 020a633..ee476c9 100644
--- a/vendor/brick/math/src/Internal/Calculator/NativeCalculator.php
+++ b/vendor/brick/math/src/Internal/Calculator/NativeCalculator.php
@@ -5,57 +5,43 @@ declare(strict_types=1);
namespace Brick\Math\Internal\Calculator;
use Brick\Math\Internal\Calculator;
+use Override;
/**
* Calculator implementation using only native PHP code.
*
* @internal
- *
- * @psalm-immutable
*/
-class NativeCalculator extends Calculator
+final readonly class NativeCalculator extends Calculator
{
/**
* The max number of digits the platform can natively add, subtract, multiply or divide without overflow.
* For multiplication, this represents the max sum of the lengths of both operands.
*
- * For addition, it is assumed that an extra digit can hold a carry (1) without overflowing.
+ * In addition, it is assumed that an extra digit can hold a carry (1) without overflowing.
* Example: 32-bit: max number 1,999,999,999 (9 digits + carry)
* 64-bit: max number 1,999,999,999,999,999,999 (18 digits + carry)
- *
- * @var int
*/
- private $maxDigits;
+ private int $maxDigits;
/**
- * Class constructor.
- *
+ * @pure
* @codeCoverageIgnore
*/
public function __construct()
{
- switch (PHP_INT_SIZE) {
- case 4:
- $this->maxDigits = 9;
- break;
-
- case 8:
- $this->maxDigits = 18;
- break;
-
- default:
- throw new \RuntimeException('The platform is not 32-bit or 64-bit as expected.');
- }
+ $this->maxDigits = match (PHP_INT_SIZE) {
+ 4 => 9,
+ 8 => 18,
+ };
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function add(string $a, string $b) : string
{
/**
- * @psalm-var numeric-string $a
- * @psalm-var numeric-string $b
+ * @var numeric-string $a
+ * @var numeric-string $b
*/
$result = $a + $b;
@@ -82,22 +68,18 @@ class NativeCalculator extends Calculator
return $result;
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function sub(string $a, string $b) : string
{
return $this->add($a, $this->neg($b));
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function mul(string $a, string $b) : string
{
/**
- * @psalm-var numeric-string $a
- * @psalm-var numeric-string $b
+ * @var numeric-string $a
+ * @var numeric-string $b
*/
$result = $a * $b;
@@ -136,25 +118,19 @@ class NativeCalculator extends Calculator
return $result;
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function divQ(string $a, string $b) : string
{
return $this->divQR($a, $b)[0];
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function divR(string $a, string $b): string
{
return $this->divQR($a, $b)[1];
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function divQR(string $a, string $b) : array
{
if ($a === '0') {
@@ -173,20 +149,18 @@ class NativeCalculator extends Calculator
return [$this->neg($a), '0'];
}
- /** @psalm-var numeric-string $a */
+ /** @var numeric-string $a */
$na = $a * 1; // cast to number
if (is_int($na)) {
- /** @psalm-var numeric-string $b */
+ /** @var numeric-string $b */
$nb = $b * 1;
if (is_int($nb)) {
// the only division that may overflow is PHP_INT_MIN / -1,
// which cannot happen here as we've already handled a divisor of -1 above.
+ $q = intdiv($na, $nb);
$r = $na % $nb;
- $q = ($na - $r) / $nb;
-
- assert(is_int($q));
return [
(string) $q,
@@ -210,9 +184,7 @@ class NativeCalculator extends Calculator
return [$q, $r];
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function pow(string $a, int $e) : string
{
if ($e === 0) {
@@ -228,7 +200,6 @@ class NativeCalculator extends Calculator
$aa = $this->mul($a, $a);
- /** @psalm-suppress PossiblyInvalidArgument We're sure that $e / 2 is an int now */
$result = $this->pow($aa, $e / 2);
if ($odd === 1) {
@@ -240,9 +211,8 @@ class NativeCalculator extends Calculator
/**
* Algorithm from: https://www.geeksforgeeks.org/modular-exponentiation-power-in-modular-arithmetic/
- *
- * {@inheritdoc}
*/
+ #[Override]
public function modPow(string $base, string $exp, string $mod) : string
{
// special case: the algorithm below fails with 0 power 0 mod 1 (returns 1 instead of 0)
@@ -276,9 +246,8 @@ class NativeCalculator extends Calculator
/**
* Adapted from https://cp-algorithms.com/num_methods/roots_newton.html
- *
- * {@inheritDoc}
*/
+ #[Override]
public function sqrt(string $n) : string
{
if ($n === '0') {
@@ -307,10 +276,7 @@ class NativeCalculator extends Calculator
/**
* Performs the addition of two non-signed large integers.
*
- * @param string $a The first operand.
- * @param string $b The second operand.
- *
- * @return string
+ * @pure
*/
private function doAdd(string $a, string $b) : string
{
@@ -324,14 +290,13 @@ class NativeCalculator extends Calculator
if ($i < 0) {
$blockLength += $i;
- /** @psalm-suppress LoopInvalidation */
$i = 0;
}
- /** @psalm-var numeric-string $blockA */
+ /** @var numeric-string $blockA */
$blockA = \substr($a, $i, $blockLength);
- /** @psalm-var numeric-string $blockB */
+ /** @var numeric-string $blockB */
$blockB = \substr($b, $i, $blockLength);
$sum = (string) ($blockA + $blockB + $carry);
@@ -364,10 +329,7 @@ class NativeCalculator extends Calculator
/**
* Performs the subtraction of two non-signed large integers.
*
- * @param string $a The first operand.
- * @param string $b The second operand.
- *
- * @return string
+ * @pure
*/
private function doSub(string $a, string $b) : string
{
@@ -398,14 +360,13 @@ class NativeCalculator extends Calculator
if ($i < 0) {
$blockLength += $i;
- /** @psalm-suppress LoopInvalidation */
$i = 0;
}
- /** @psalm-var numeric-string $blockA */
+ /** @var numeric-string $blockA */
$blockA = \substr($a, $i, $blockLength);
- /** @psalm-var numeric-string $blockB */
+ /** @var numeric-string $blockB */
$blockB = \substr($b, $i, $blockLength);
$sum = $blockA - $blockB - $carry;
@@ -446,10 +407,7 @@ class NativeCalculator extends Calculator
/**
* Performs the multiplication of two non-signed large integers.
*
- * @param string $a The first operand.
- * @param string $b The second operand.
- *
- * @return string
+ * @pure
*/
private function doMul(string $a, string $b) : string
{
@@ -466,7 +424,6 @@ class NativeCalculator extends Calculator
if ($i < 0) {
$blockALength += $i;
- /** @psalm-suppress LoopInvalidation */
$i = 0;
}
@@ -480,7 +437,6 @@ class NativeCalculator extends Calculator
if ($j < 0) {
$blockBLength += $j;
- /** @psalm-suppress LoopInvalidation */
$j = 0;
}
@@ -522,10 +478,9 @@ class NativeCalculator extends Calculator
/**
* Performs the division of two non-signed large integers.
*
- * @param string $a The first operand.
- * @param string $b The second operand.
- *
* @return string[] The quotient and remainder.
+ *
+ * @pure
*/
private function doDiv(string $a, string $b) : array
{
@@ -544,6 +499,22 @@ class NativeCalculator extends Calculator
$r = $a; // remainder
$z = $y; // focus length, always $y or $y+1
+ /** @var numeric-string $b */
+ $nb = $b * 1; // cast to number
+ // performance optimization in cases where the remainder will never cause int overflow
+ if (is_int(($nb - 1) * 10 + 9)) {
+ $r = (int) \substr($a, 0, $z - 1);
+
+ for ($i = $z - 1; $i < $x; $i++) {
+ $n = $r * 10 + (int) $a[$i];
+ /** @var int $nb */
+ $q .= \intdiv($n, $nb);
+ $r = $n % $nb;
+ }
+
+ return [\ltrim($q, '0') ?: '0', (string) $r];
+ }
+
for (;;) {
$focus = \substr($a, 0, $z);
@@ -583,10 +554,9 @@ class NativeCalculator extends Calculator
/**
* Compares two non-signed large numbers.
*
- * @param string $a The first operand.
- * @param string $b The second operand.
+ * @return -1|0|1
*
- * @return int [-1, 0, 1]
+ * @pure
*/
private function doCmp(string $a, string $b) : int
{
@@ -599,7 +569,7 @@ class NativeCalculator extends Calculator
return $cmp;
}
- return \strcmp($a, $b) <=> 0; // enforce [-1, 0, 1]
+ return \strcmp($a, $b) <=> 0; // enforce -1|0|1
}
/**
@@ -607,10 +577,9 @@ class NativeCalculator extends Calculator
*
* The numbers must only consist of digits, without leading minus sign.
*
- * @param string $a The first operand.
- * @param string $b The second operand.
- *
* @return array{string, string, int}
+ *
+ * @pure
*/
private function pad(string $a, string $b) : array
{
diff --git a/vendor/brick/math/src/Internal/CalculatorRegistry.php b/vendor/brick/math/src/Internal/CalculatorRegistry.php
new file mode 100644
index 0000000..394fae6
--- /dev/null
+++ b/vendor/brick/math/src/Internal/CalculatorRegistry.php
@@ -0,0 +1,73 @@
+= 0.5; otherwise, behaves as for DOWN.
* Note that this is the rounding mode commonly taught at school.
*/
- public const HALF_UP = 5;
+ case HALF_UP;
/**
* Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round down.
*
* Behaves as for UP if the discarded fraction is > 0.5; otherwise, behaves as for DOWN.
*/
- public const HALF_DOWN = 6;
+ case HALF_DOWN;
/**
* Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round towards positive infinity.
*
* If the result is positive, behaves as for HALF_UP; if negative, behaves as for HALF_DOWN.
*/
- public const HALF_CEILING = 7;
+ case HALF_CEILING;
/**
* Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round towards negative infinity.
*
* If the result is positive, behaves as for HALF_DOWN; if negative, behaves as for HALF_UP.
*/
- public const HALF_FLOOR = 8;
+ case HALF_FLOOR;
/**
* Rounds towards the "nearest neighbor" unless both neighbors are equidistant, in which case rounds towards the even neighbor.
@@ -103,5 +94,5 @@ final class RoundingMode
* cumulative error when applied repeatedly over a sequence of calculations.
* It is sometimes known as "Banker's rounding", and is chiefly used in the USA.
*/
- public const HALF_EVEN = 9;
+ case HALF_EVEN;
}
diff --git a/vendor/composer/InstalledVersions.php b/vendor/composer/InstalledVersions.php
index 51e734a..2052022 100644
--- a/vendor/composer/InstalledVersions.php
+++ b/vendor/composer/InstalledVersions.php
@@ -26,12 +26,23 @@ use Composer\Semver\VersionParser;
*/
class InstalledVersions
{
+ /**
+ * @var string|null if set (by reflection by Composer), this should be set to the path where this class is being copied to
+ * @internal
+ */
+ private static $selfDir = null;
+
/**
* @var mixed[]|null
* @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array}|array{}|null
*/
private static $installed;
+ /**
+ * @var bool
+ */
+ private static $installedIsLocalDir;
+
/**
* @var bool|null
*/
@@ -309,6 +320,24 @@ class InstalledVersions
{
self::$installed = $data;
self::$installedByVendor = array();
+
+ // when using reload, we disable the duplicate protection to ensure that self::$installed data is
+ // always returned, but we cannot know whether it comes from the installed.php in __DIR__ or not,
+ // so we have to assume it does not, and that may result in duplicate data being returned when listing
+ // all installed packages for example
+ self::$installedIsLocalDir = false;
+ }
+
+ /**
+ * @return string
+ */
+ private static function getSelfDir()
+ {
+ if (self::$selfDir === null) {
+ self::$selfDir = strtr(__DIR__, '\\', '/');
+ }
+
+ return self::$selfDir;
}
/**
@@ -322,19 +351,27 @@ class InstalledVersions
}
$installed = array();
+ $copiedLocalDir = false;
if (self::$canGetVendors) {
+ $selfDir = self::getSelfDir();
foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
+ $vendorDir = strtr($vendorDir, '\\', '/');
if (isset(self::$installedByVendor[$vendorDir])) {
$installed[] = self::$installedByVendor[$vendorDir];
} elseif (is_file($vendorDir.'/composer/installed.php')) {
/** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} $required */
$required = require $vendorDir.'/composer/installed.php';
- $installed[] = self::$installedByVendor[$vendorDir] = $required;
- if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
- self::$installed = $installed[count($installed) - 1];
+ self::$installedByVendor[$vendorDir] = $required;
+ $installed[] = $required;
+ if (self::$installed === null && $vendorDir.'/composer' === $selfDir) {
+ self::$installed = $required;
+ self::$installedIsLocalDir = true;
}
}
+ if (self::$installedIsLocalDir && $vendorDir.'/composer' === $selfDir) {
+ $copiedLocalDir = true;
+ }
}
}
@@ -350,7 +387,7 @@ class InstalledVersions
}
}
- if (self::$installed !== array()) {
+ if (self::$installed !== array() && !$copiedLocalDir) {
$installed[] = self::$installed;
}
diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php
index a16ffbd..005b68e 100644
--- a/vendor/composer/autoload_classmap.php
+++ b/vendor/composer/autoload_classmap.php
@@ -6,11 +6,8 @@ $vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(
- 'Attribute' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Attribute.php',
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
- 'PhpToken' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php',
- 'Stringable' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Stringable.php',
- 'UnhandledMatchError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php',
- 'ValueError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/ValueError.php',
+ 'Deprecated' => $vendorDir . '/symfony/polyfill-php84/Resources/stubs/Deprecated.php',
+ 'ReflectionConstant' => $vendorDir . '/symfony/polyfill-php84/Resources/stubs/ReflectionConstant.php',
'lessc' => $vendorDir . '/wikimedia/less.php/lessc.inc.php',
);
diff --git a/vendor/composer/autoload_files.php b/vendor/composer/autoload_files.php
index 39e9a0d..6eb2a75 100644
--- a/vendor/composer/autoload_files.php
+++ b/vendor/composer/autoload_files.php
@@ -8,9 +8,8 @@ $baseDir = dirname($vendorDir);
return array(
'a2c78434f64e5f5ed402f42eee19c025' => $vendorDir . '/ipl/stdlib/src/functions_include.php',
'6076de347104821999fcfc82c8f19bc5' => $vendorDir . '/ipl/i18n/src/functions_include.php',
+ '9d2b9fc6db0f153a0a149fefb182415e' => $vendorDir . '/symfony/polyfill-php84/bootstrap.php',
'7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php',
- '320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php',
- 'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php',
'e39a8b23c42d4e1452234d762b03835a' => $vendorDir . '/ramsey/uuid/src/functions.php',
'ad155f8f1cf0d418fe49e248db8c661b' => $vendorDir . '/react/promise/src/functions_include.php',
'8e4ccce73649a2b516ec3b4571432da5' => $vendorDir . '/ipl/scheduler/src/register_cron_aliases.php',
diff --git a/vendor/composer/autoload_psr4.php b/vendor/composer/autoload_psr4.php
index 225315a..b04662e 100644
--- a/vendor/composer/autoload_psr4.php
+++ b/vendor/composer/autoload_psr4.php
@@ -14,21 +14,19 @@ return array(
'ipl\\Orm\\' => array($vendorDir . '/ipl/orm/src'),
'ipl\\I18n\\' => array($vendorDir . '/ipl/i18n/src'),
'ipl\\Html\\' => array($vendorDir . '/ipl/html/src'),
- 'cweagans\\Composer\\' => array($vendorDir . '/cweagans/composer-patches/src'),
'Webmozart\\Assert\\' => array($vendorDir . '/webmozart/assert/src'),
- 'Symfony\\Polyfill\\Php80\\' => array($vendorDir . '/symfony/polyfill-php80'),
- 'Symfony\\Polyfill\\Ctype\\' => array($vendorDir . '/symfony/polyfill-ctype'),
+ 'Symfony\\Polyfill\\Php84\\' => array($vendorDir . '/symfony/polyfill-php84'),
'Recurr\\' => array($vendorDir . '/simshaun/recurr/src/Recurr'),
'React\\Promise\\' => array($vendorDir . '/react/promise/src'),
'React\\EventLoop\\' => array($vendorDir . '/react/event-loop/src'),
'Ramsey\\Uuid\\' => array($vendorDir . '/ramsey/uuid/src'),
'Ramsey\\Collection\\' => array($vendorDir . '/ramsey/collection/src'),
'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
- 'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-message/src', $vendorDir . '/psr/http-factory/src'),
+ 'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-factory/src', $vendorDir . '/psr/http-message/src'),
'GuzzleHttp\\Psr7\\' => array($vendorDir . '/guzzlehttp/psr7/src'),
'Evenement\\' => array($vendorDir . '/evenement/evenement/src'),
'Doctrine\\Deprecations\\' => array($vendorDir . '/doctrine/deprecations/src'),
- 'Doctrine\\Common\\Collections\\' => array($vendorDir . '/doctrine/collections/lib/Doctrine/Common/Collections'),
+ 'Doctrine\\Common\\Collections\\' => array($vendorDir . '/doctrine/collections/src'),
'Cron\\' => array($vendorDir . '/dragonmantank/cron-expression/src/Cron'),
'Brick\\Math\\' => array($vendorDir . '/brick/math/src'),
);
diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php
index e12b2c4..02157ed 100644
--- a/vendor/composer/autoload_real.php
+++ b/vendor/composer/autoload_real.php
@@ -2,7 +2,7 @@
// autoload_real.php @generated by Composer
-class ComposerAutoloaderInit20d4022bc196691807f55d4a47c06474
+class ComposerAutoloaderInit7a1692c86b6fc70eaaf43c4bee3673aa
{
private static $loader;
@@ -24,16 +24,16 @@ class ComposerAutoloaderInit20d4022bc196691807f55d4a47c06474
require __DIR__ . '/platform_check.php';
- spl_autoload_register(array('ComposerAutoloaderInit20d4022bc196691807f55d4a47c06474', 'loadClassLoader'), true, true);
+ spl_autoload_register(array('ComposerAutoloaderInit7a1692c86b6fc70eaaf43c4bee3673aa', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
- spl_autoload_unregister(array('ComposerAutoloaderInit20d4022bc196691807f55d4a47c06474', 'loadClassLoader'));
+ spl_autoload_unregister(array('ComposerAutoloaderInit7a1692c86b6fc70eaaf43c4bee3673aa', 'loadClassLoader'));
require __DIR__ . '/autoload_static.php';
- call_user_func(\Composer\Autoload\ComposerStaticInit20d4022bc196691807f55d4a47c06474::getInitializer($loader));
+ call_user_func(\Composer\Autoload\ComposerStaticInit7a1692c86b6fc70eaaf43c4bee3673aa::getInitializer($loader));
$loader->register(true);
- $filesToLoad = \Composer\Autoload\ComposerStaticInit20d4022bc196691807f55d4a47c06474::$files;
+ $filesToLoad = \Composer\Autoload\ComposerStaticInit7a1692c86b6fc70eaaf43c4bee3673aa::$files;
$requireFile = \Closure::bind(static function ($fileIdentifier, $file) {
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php
index c727743..3b06e81 100644
--- a/vendor/composer/autoload_static.php
+++ b/vendor/composer/autoload_static.php
@@ -4,14 +4,13 @@
namespace Composer\Autoload;
-class ComposerStaticInit20d4022bc196691807f55d4a47c06474
+class ComposerStaticInit7a1692c86b6fc70eaaf43c4bee3673aa
{
public static $files = array (
'a2c78434f64e5f5ed402f42eee19c025' => __DIR__ . '/..' . '/ipl/stdlib/src/functions_include.php',
'6076de347104821999fcfc82c8f19bc5' => __DIR__ . '/..' . '/ipl/i18n/src/functions_include.php',
+ '9d2b9fc6db0f153a0a149fefb182415e' => __DIR__ . '/..' . '/symfony/polyfill-php84/bootstrap.php',
'7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php',
- '320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php',
- 'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php',
'e39a8b23c42d4e1452234d762b03835a' => __DIR__ . '/..' . '/ramsey/uuid/src/functions.php',
'ad155f8f1cf0d418fe49e248db8c661b' => __DIR__ . '/..' . '/react/promise/src/functions_include.php',
'8e4ccce73649a2b516ec3b4571432da5' => __DIR__ . '/..' . '/ipl/scheduler/src/register_cron_aliases.php',
@@ -29,18 +28,13 @@ class ComposerStaticInit20d4022bc196691807f55d4a47c06474
'ipl\\I18n\\' => 9,
'ipl\\Html\\' => 9,
),
- 'c' =>
- array (
- 'cweagans\\Composer\\' => 18,
- ),
'W' =>
array (
'Webmozart\\Assert\\' => 17,
),
'S' =>
array (
- 'Symfony\\Polyfill\\Php80\\' => 23,
- 'Symfony\\Polyfill\\Ctype\\' => 23,
+ 'Symfony\\Polyfill\\Php84\\' => 23,
),
'R' =>
array (
@@ -111,21 +105,13 @@ class ComposerStaticInit20d4022bc196691807f55d4a47c06474
array (
0 => __DIR__ . '/..' . '/ipl/html/src',
),
- 'cweagans\\Composer\\' =>
- array (
- 0 => __DIR__ . '/..' . '/cweagans/composer-patches/src',
- ),
'Webmozart\\Assert\\' =>
array (
0 => __DIR__ . '/..' . '/webmozart/assert/src',
),
- 'Symfony\\Polyfill\\Php80\\' =>
+ 'Symfony\\Polyfill\\Php84\\' =>
array (
- 0 => __DIR__ . '/..' . '/symfony/polyfill-php80',
- ),
- 'Symfony\\Polyfill\\Ctype\\' =>
- array (
- 0 => __DIR__ . '/..' . '/symfony/polyfill-ctype',
+ 0 => __DIR__ . '/..' . '/symfony/polyfill-php84',
),
'Recurr\\' =>
array (
@@ -153,8 +139,8 @@ class ComposerStaticInit20d4022bc196691807f55d4a47c06474
),
'Psr\\Http\\Message\\' =>
array (
- 0 => __DIR__ . '/..' . '/psr/http-message/src',
- 1 => __DIR__ . '/..' . '/psr/http-factory/src',
+ 0 => __DIR__ . '/..' . '/psr/http-factory/src',
+ 1 => __DIR__ . '/..' . '/psr/http-message/src',
),
'GuzzleHttp\\Psr7\\' =>
array (
@@ -170,7 +156,7 @@ class ComposerStaticInit20d4022bc196691807f55d4a47c06474
),
'Doctrine\\Common\\Collections\\' =>
array (
- 0 => __DIR__ . '/..' . '/doctrine/collections/lib/Doctrine/Common/Collections',
+ 0 => __DIR__ . '/..' . '/doctrine/collections/src',
),
'Cron\\' =>
array (
@@ -200,22 +186,19 @@ class ComposerStaticInit20d4022bc196691807f55d4a47c06474
);
public static $classMap = array (
- 'Attribute' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Attribute.php',
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
- 'PhpToken' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php',
- 'Stringable' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Stringable.php',
- 'UnhandledMatchError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php',
- 'ValueError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/ValueError.php',
+ 'Deprecated' => __DIR__ . '/..' . '/symfony/polyfill-php84/Resources/stubs/Deprecated.php',
+ 'ReflectionConstant' => __DIR__ . '/..' . '/symfony/polyfill-php84/Resources/stubs/ReflectionConstant.php',
'lessc' => __DIR__ . '/..' . '/wikimedia/less.php/lessc.inc.php',
);
public static function getInitializer(ClassLoader $loader)
{
return \Closure::bind(function () use ($loader) {
- $loader->prefixLengthsPsr4 = ComposerStaticInit20d4022bc196691807f55d4a47c06474::$prefixLengthsPsr4;
- $loader->prefixDirsPsr4 = ComposerStaticInit20d4022bc196691807f55d4a47c06474::$prefixDirsPsr4;
- $loader->prefixesPsr0 = ComposerStaticInit20d4022bc196691807f55d4a47c06474::$prefixesPsr0;
- $loader->classMap = ComposerStaticInit20d4022bc196691807f55d4a47c06474::$classMap;
+ $loader->prefixLengthsPsr4 = ComposerStaticInit7a1692c86b6fc70eaaf43c4bee3673aa::$prefixLengthsPsr4;
+ $loader->prefixDirsPsr4 = ComposerStaticInit7a1692c86b6fc70eaaf43c4bee3673aa::$prefixDirsPsr4;
+ $loader->prefixesPsr0 = ComposerStaticInit7a1692c86b6fc70eaaf43c4bee3673aa::$prefixesPsr0;
+ $loader->classMap = ComposerStaticInit7a1692c86b6fc70eaaf43c4bee3673aa::$classMap;
}, null, ClassLoader::class);
}
diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json
index d19f842..cd0a6ce 100644
--- a/vendor/composer/installed.json
+++ b/vendor/composer/installed.json
@@ -2,29 +2,28 @@
"packages": [
{
"name": "brick/math",
- "version": "0.9.3",
- "version_normalized": "0.9.3.0",
+ "version": "0.14.0",
+ "version_normalized": "0.14.0.0",
"source": {
"type": "git",
"url": "https://github.com/brick/math.git",
- "reference": "ca57d18f028f84f777b2168cd1911b0dee2343ae"
+ "reference": "113a8ee2656b882d4c3164fa31aa6e12cbb7aaa2"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/brick/math/zipball/ca57d18f028f84f777b2168cd1911b0dee2343ae",
- "reference": "ca57d18f028f84f777b2168cd1911b0dee2343ae",
+ "url": "https://api.github.com/repos/brick/math/zipball/113a8ee2656b882d4c3164fa31aa6e12cbb7aaa2",
+ "reference": "113a8ee2656b882d4c3164fa31aa6e12cbb7aaa2",
"shasum": ""
},
"require": {
- "ext-json": "*",
- "php": "^7.1 || ^8.0"
+ "php": "^8.2"
},
"require-dev": {
"php-coveralls/php-coveralls": "^2.2",
- "phpunit/phpunit": "^7.5.15 || ^8.5 || ^9.0",
- "vimeo/psalm": "4.9.2"
+ "phpstan/phpstan": "2.1.22",
+ "phpunit/phpunit": "^11.5"
},
- "time": "2021-08-15T20:50:18+00:00",
+ "time": "2025-08-29T12:40:03+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@@ -44,107 +43,59 @@
"arithmetic",
"bigdecimal",
"bignum",
+ "bignumber",
"brick",
- "math"
+ "decimal",
+ "integer",
+ "math",
+ "mathematics",
+ "rational"
],
"support": {
"issues": "https://github.com/brick/math/issues",
- "source": "https://github.com/brick/math/tree/0.9.3"
+ "source": "https://github.com/brick/math/tree/0.14.0"
},
"funding": [
{
"url": "https://github.com/BenMorel",
"type": "github"
- },
- {
- "url": "https://tidelift.com/funding/github/packagist/brick/math",
- "type": "tidelift"
}
],
"install-path": "../brick/math"
},
- {
- "name": "cweagans/composer-patches",
- "version": "1.7.3",
- "version_normalized": "1.7.3.0",
- "source": {
- "type": "git",
- "url": "https://github.com/cweagans/composer-patches.git",
- "reference": "e190d4466fe2b103a55467dfa83fc2fecfcaf2db"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/cweagans/composer-patches/zipball/e190d4466fe2b103a55467dfa83fc2fecfcaf2db",
- "reference": "e190d4466fe2b103a55467dfa83fc2fecfcaf2db",
- "shasum": ""
- },
- "require": {
- "composer-plugin-api": "^1.0 || ^2.0",
- "php": ">=5.3.0"
- },
- "require-dev": {
- "composer/composer": "~1.0 || ~2.0",
- "phpunit/phpunit": "~4.6"
- },
- "time": "2022-12-20T22:53:13+00:00",
- "type": "composer-plugin",
- "extra": {
- "class": "cweagans\\Composer\\Patches"
- },
- "installation-source": "dist",
- "autoload": {
- "psr-4": {
- "cweagans\\Composer\\": "src"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Cameron Eagans",
- "email": "me@cweagans.net"
- }
- ],
- "description": "Provides a way to patch Composer packages.",
- "support": {
- "issues": "https://github.com/cweagans/composer-patches/issues",
- "source": "https://github.com/cweagans/composer-patches/tree/1.7.3"
- },
- "install-path": "../cweagans/composer-patches"
- },
{
"name": "doctrine/collections",
- "version": "1.8.0",
- "version_normalized": "1.8.0.0",
+ "version": "2.3.0",
+ "version_normalized": "2.3.0.0",
"source": {
"type": "git",
"url": "https://github.com/doctrine/collections.git",
- "reference": "2b44dd4cbca8b5744327de78bafef5945c7e7b5e"
+ "reference": "2eb07e5953eed811ce1b309a7478a3b236f2273d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/doctrine/collections/zipball/2b44dd4cbca8b5744327de78bafef5945c7e7b5e",
- "reference": "2b44dd4cbca8b5744327de78bafef5945c7e7b5e",
+ "url": "https://api.github.com/repos/doctrine/collections/zipball/2eb07e5953eed811ce1b309a7478a3b236f2273d",
+ "reference": "2eb07e5953eed811ce1b309a7478a3b236f2273d",
"shasum": ""
},
"require": {
- "doctrine/deprecations": "^0.5.3 || ^1",
- "php": "^7.1.3 || ^8.0"
+ "doctrine/deprecations": "^1",
+ "php": "^8.1",
+ "symfony/polyfill-php84": "^1.30"
},
"require-dev": {
- "doctrine/coding-standard": "^9.0 || ^10.0",
- "phpstan/phpstan": "^1.4.8",
- "phpunit/phpunit": "^7.5 || ^8.5 || ^9.1.5",
- "vimeo/psalm": "^4.22"
+ "doctrine/coding-standard": "^12",
+ "ext-json": "*",
+ "phpstan/phpstan": "^1.8",
+ "phpstan/phpstan-phpunit": "^1.0",
+ "phpunit/phpunit": "^10.5"
},
- "time": "2022-09-01T20:12:10+00:00",
+ "time": "2025-03-22T10:17:19+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-4": {
- "Doctrine\\Common\\Collections\\": "lib/Doctrine/Common/Collections"
+ "Doctrine\\Common\\Collections\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
@@ -183,8 +134,22 @@
],
"support": {
"issues": "https://github.com/doctrine/collections/issues",
- "source": "https://github.com/doctrine/collections/tree/1.8.0"
+ "source": "https://github.com/doctrine/collections/tree/2.3.0"
},
+ "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%2Fcollections",
+ "type": "tidelift"
+ }
+ ],
"install-path": "../doctrine/collections"
},
{
@@ -525,17 +490,17 @@
},
{
"name": "ipl/html",
- "version": "v0.8.2",
- "version_normalized": "0.8.2.0",
+ "version": "dev-main",
+ "version_normalized": "dev-main",
"source": {
"type": "git",
"url": "https://github.com/Icinga/ipl-html.git",
- "reference": "e18bdf11abca5e477100e2c7d190ef5f424d0d98"
+ "reference": "9f698b99cab6bd0ab36ea56022c53ac89a7150fc"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Icinga/ipl-html/zipball/e18bdf11abca5e477100e2c7d190ef5f424d0d98",
- "reference": "e18bdf11abca5e477100e2c7d190ef5f424d0d98",
+ "url": "https://api.github.com/repos/Icinga/ipl-html/zipball/9f698b99cab6bd0ab36ea56022c53ac89a7150fc",
+ "reference": "9f698b99cab6bd0ab36ea56022c53ac89a7150fc",
"shasum": ""
},
"require": {
@@ -543,14 +508,16 @@
"guzzlehttp/psr7": "^2.5",
"ipl/stdlib": ">=0.12.0",
"ipl/validator": ">=0.5.0",
- "php": ">=7.2",
+ "php": ">=8.2",
"psr/http-message": "^1.1"
},
"require-dev": {
+ "ext-dom": "*",
"ipl/stdlib": "dev-main",
"ipl/validator": "dev-main"
},
- "time": "2025-05-21T09:00:03+00:00",
+ "time": "2025-10-02T13:04:12+00:00",
+ "default-branch": true,
"type": "library",
"installation-source": "dist",
"autoload": {
@@ -569,23 +536,23 @@
],
"support": {
"issues": "https://github.com/Icinga/ipl-html/issues",
- "source": "https://github.com/Icinga/ipl-html/tree/v0.8.2"
+ "source": "https://github.com/Icinga/ipl-html/tree/main"
},
"install-path": "../ipl/html"
},
{
"name": "ipl/i18n",
- "version": "v0.2.2",
- "version_normalized": "0.2.2.0",
+ "version": "dev-main",
+ "version_normalized": "dev-main",
"source": {
"type": "git",
"url": "https://github.com/Icinga/ipl-i18n.git",
- "reference": "a2b6109c5a93f86ce46d5dc351dbe75e8502cf8c"
+ "reference": "692c33cf46fb8a4511da613dbf97c6216c345cc5"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Icinga/ipl-i18n/zipball/a2b6109c5a93f86ce46d5dc351dbe75e8502cf8c",
- "reference": "a2b6109c5a93f86ce46d5dc351dbe75e8502cf8c",
+ "url": "https://api.github.com/repos/Icinga/ipl-i18n/zipball/692c33cf46fb8a4511da613dbf97c6216c345cc5",
+ "reference": "692c33cf46fb8a4511da613dbf97c6216c345cc5",
"shasum": ""
},
"require": {
@@ -597,7 +564,8 @@
"require-dev": {
"ipl/stdlib": "dev-main"
},
- "time": "2024-04-08T12:28:47+00:00",
+ "time": "2025-06-12T11:57:41+00:00",
+ "default-branch": true,
"type": "library",
"installation-source": "dist",
"autoload": {
@@ -623,37 +591,38 @@
],
"support": {
"issues": "https://github.com/Icinga/ipl-i18n/issues",
- "source": "https://github.com/Icinga/ipl-i18n/tree/v0.2.2"
+ "source": "https://github.com/Icinga/ipl-i18n/tree/main"
},
"install-path": "../ipl/i18n"
},
{
"name": "ipl/orm",
- "version": "v0.6.3",
- "version_normalized": "0.6.3.0",
+ "version": "dev-main",
+ "version_normalized": "dev-main",
"source": {
"type": "git",
"url": "https://github.com/Icinga/ipl-orm.git",
- "reference": "a775a2745764a8dc7f28618cce69dcd7bbfd7915"
+ "reference": "2a0b72d21e2444501a940975f869297998c6cdfe"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Icinga/ipl-orm/zipball/a775a2745764a8dc7f28618cce69dcd7bbfd7915",
- "reference": "a775a2745764a8dc7f28618cce69dcd7bbfd7915",
+ "url": "https://api.github.com/repos/Icinga/ipl-orm/zipball/2a0b72d21e2444501a940975f869297998c6cdfe",
+ "reference": "2a0b72d21e2444501a940975f869297998c6cdfe",
"shasum": ""
},
"require": {
"ext-pdo": "*",
"ipl/sql": ">=0.7.0",
"ipl/stdlib": ">=0.12.0",
- "php": ">=7.2"
+ "php": ">=8.2"
},
"require-dev": {
"ext-pdo_sqlite": "*",
"ipl/sql": "dev-main",
"ipl/stdlib": "dev-main"
},
- "time": "2025-06-12T11:57:55+00:00",
+ "time": "2025-10-15T11:46:22+00:00",
+ "default-branch": true,
"type": "library",
"installation-source": "dist",
"autoload": {
@@ -674,23 +643,23 @@
],
"support": {
"issues": "https://github.com/Icinga/ipl-orm/issues",
- "source": "https://github.com/Icinga/ipl-orm/tree/v0.6.3"
+ "source": "https://github.com/Icinga/ipl-orm/tree/main"
},
"install-path": "../ipl/orm"
},
{
"name": "ipl/scheduler",
- "version": "v0.1.2",
- "version_normalized": "0.1.2.0",
+ "version": "dev-main",
+ "version_normalized": "dev-main",
"source": {
"type": "git",
"url": "https://github.com/Icinga/ipl-scheduler.git",
- "reference": "6119afdea07b1390bd728e350e0d80b26ec8d6ba"
+ "reference": "3e4e8db870239d213b1dfd5d79d59fc7784b4c34"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Icinga/ipl-scheduler/zipball/6119afdea07b1390bd728e350e0d80b26ec8d6ba",
- "reference": "6119afdea07b1390bd728e350e0d80b26ec8d6ba",
+ "url": "https://api.github.com/repos/Icinga/ipl-scheduler/zipball/3e4e8db870239d213b1dfd5d79d59fc7784b4c34",
+ "reference": "3e4e8db870239d213b1dfd5d79d59fc7784b4c34",
"shasum": ""
},
"require": {
@@ -710,7 +679,8 @@
"suggest": {
"ext-ev": "Improves performance, efficiency and avoids system limitations. Highly recommended! (See https://www.php.net/manual/en/intro.ev.php for details)"
},
- "time": "2023-08-30T14:14:23+00:00",
+ "time": "2025-06-12T11:58:09+00:00",
+ "default-branch": true,
"type": "library",
"installation-source": "dist",
"autoload": {
@@ -735,23 +705,23 @@
],
"support": {
"issues": "https://github.com/Icinga/ipl-scheduler/issues",
- "source": "https://github.com/Icinga/ipl-scheduler/tree/v0.1.2"
+ "source": "https://github.com/Icinga/ipl-scheduler/tree/main"
},
"install-path": "../ipl/scheduler"
},
{
"name": "ipl/sql",
- "version": "v0.7.1",
- "version_normalized": "0.7.1.0",
+ "version": "dev-main",
+ "version_normalized": "dev-main",
"source": {
"type": "git",
"url": "https://github.com/Icinga/ipl-sql.git",
- "reference": "e80f1b712c4b96099b0bf9096e6efe317a165e3b"
+ "reference": "6f4258c4e3b20655db57d248e26edf7b54c04729"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Icinga/ipl-sql/zipball/e80f1b712c4b96099b0bf9096e6efe317a165e3b",
- "reference": "e80f1b712c4b96099b0bf9096e6efe317a165e3b",
+ "url": "https://api.github.com/repos/Icinga/ipl-sql/zipball/6f4258c4e3b20655db57d248e26edf7b54c04729",
+ "reference": "6f4258c4e3b20655db57d248e26edf7b54c04729",
"shasum": ""
},
"require": {
@@ -762,7 +732,8 @@
"require-dev": {
"ipl/stdlib": "dev-main"
},
- "time": "2024-06-25T09:55:43+00:00",
+ "time": "2025-10-08T07:03:38+00:00",
+ "default-branch": true,
"type": "library",
"installation-source": "dist",
"autoload": {
@@ -782,23 +753,23 @@
],
"support": {
"issues": "https://github.com/Icinga/ipl-sql/issues",
- "source": "https://github.com/Icinga/ipl-sql/tree/v0.7.1"
+ "source": "https://github.com/Icinga/ipl-sql/tree/main"
},
"install-path": "../ipl/sql"
},
{
"name": "ipl/stdlib",
- "version": "v0.14.0",
- "version_normalized": "0.14.0.0",
+ "version": "dev-main",
+ "version_normalized": "dev-main",
"source": {
"type": "git",
"url": "https://github.com/Icinga/ipl-stdlib.git",
- "reference": "bf5fc8f40b86bd90337db6f3be389be2a93fa64a"
+ "reference": "9b7a903fbfc341da59f242149ac333594e4a6fa3"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Icinga/ipl-stdlib/zipball/bf5fc8f40b86bd90337db6f3be389be2a93fa64a",
- "reference": "bf5fc8f40b86bd90337db6f3be389be2a93fa64a",
+ "url": "https://api.github.com/repos/Icinga/ipl-stdlib/zipball/9b7a903fbfc341da59f242149ac333594e4a6fa3",
+ "reference": "9b7a903fbfc341da59f242149ac333594e4a6fa3",
"shasum": ""
},
"require": {
@@ -806,7 +777,8 @@
"ext-openssl": "*",
"php": ">=7.2"
},
- "time": "2024-04-22T08:47:08+00:00",
+ "time": "2025-09-05T12:07:21+00:00",
+ "default-branch": true,
"type": "library",
"installation-source": "dist",
"autoload": {
@@ -824,23 +796,23 @@
"description": "ipl Standard Library",
"support": {
"issues": "https://github.com/Icinga/ipl-stdlib/issues",
- "source": "https://github.com/Icinga/ipl-stdlib/tree/v0.14.0"
+ "source": "https://github.com/Icinga/ipl-stdlib/tree/main"
},
"install-path": "../ipl/stdlib"
},
{
"name": "ipl/validator",
- "version": "v0.5.0",
- "version_normalized": "0.5.0.0",
+ "version": "dev-main",
+ "version_normalized": "dev-main",
"source": {
"type": "git",
"url": "https://github.com/Icinga/ipl-validator.git",
- "reference": "a601fae0ed330e63cea50e4a2a6659ca1ad97bde"
+ "reference": "eac5c6c114d8007db5c24ae159fe6f55e89a946b"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Icinga/ipl-validator/zipball/a601fae0ed330e63cea50e4a2a6659ca1ad97bde",
- "reference": "a601fae0ed330e63cea50e4a2a6659ca1ad97bde",
+ "url": "https://api.github.com/repos/Icinga/ipl-validator/zipball/eac5c6c114d8007db5c24ae159fe6f55e89a946b",
+ "reference": "eac5c6c114d8007db5c24ae159fe6f55e89a946b",
"shasum": ""
},
"require": {
@@ -849,12 +821,15 @@
"ipl/i18n": ">=0.2.0",
"ipl/stdlib": ">=0.12.0",
"php": ">=7.2",
- "psr/http-message": "~1.0"
+ "psr/http-message": "^1.1"
},
"require-dev": {
- "guzzlehttp/psr7": "^1"
+ "guzzlehttp/psr7": "^1",
+ "ipl/i18n": "dev-main",
+ "ipl/stdlib": "dev-main"
},
- "time": "2023-03-21T15:59:00+00:00",
+ "time": "2025-06-12T11:59:27+00:00",
+ "default-branch": true,
"type": "library",
"installation-source": "dist",
"autoload": {
@@ -870,34 +845,34 @@
"homepage": "https://github.com/Icinga/ipl-validator",
"support": {
"issues": "https://github.com/Icinga/ipl-validator/issues",
- "source": "https://github.com/Icinga/ipl-validator/tree/v0.5.0"
+ "source": "https://github.com/Icinga/ipl-validator/tree/main"
},
"install-path": "../ipl/validator"
},
{
"name": "ipl/web",
- "version": "v0.10.2",
- "version_normalized": "0.10.2.0",
+ "version": "dev-main",
+ "version_normalized": "dev-main",
"source": {
"type": "git",
"url": "https://github.com/Icinga/ipl-web.git",
- "reference": "a3d134c0d67aa51a9b186519c76e718603fda835"
+ "reference": "1fdd7aa977f8da19e17cc4535b023c0760aa442a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Icinga/ipl-web/zipball/a3d134c0d67aa51a9b186519c76e718603fda835",
- "reference": "a3d134c0d67aa51a9b186519c76e718603fda835",
+ "url": "https://api.github.com/repos/Icinga/ipl-web/zipball/1fdd7aa977f8da19e17cc4535b023c0760aa442a",
+ "reference": "1fdd7aa977f8da19e17cc4535b023c0760aa442a",
"shasum": ""
},
"require": {
"ext-json": "*",
"fortawesome/font-awesome": "^6",
- "ipl/html": ">=0.8.0",
+ "ipl/html": ">=0.9.0",
"ipl/i18n": ">=0.2.0",
"ipl/orm": ">=0.5.2",
"ipl/scheduler": ">=0.1.0",
"ipl/stdlib": ">=0.13.0",
- "php": ">=7.2",
+ "php": ">=8.2",
"psr/http-message": "^1.1",
"wikimedia/less.php": "^3.2.1"
},
@@ -909,7 +884,8 @@
"ipl/stdlib": "dev-main",
"shardj/zf1-future": "^1.22"
},
- "time": "2025-03-26T07:49:58+00:00",
+ "time": "2025-10-17T12:11:07+00:00",
+ "default-branch": true,
"type": "library",
"installation-source": "dist",
"autoload": {
@@ -928,7 +904,7 @@
],
"support": {
"issues": "https://github.com/Icinga/ipl-web/issues",
- "source": "https://github.com/Icinga/ipl-web/tree/v0.10.2"
+ "source": "https://github.com/Icinga/ipl-web/tree/main"
},
"install-path": "../ipl/web"
},
@@ -1148,45 +1124,49 @@
},
{
"name": "ramsey/collection",
- "version": "1.1.4",
- "version_normalized": "1.1.4.0",
+ "version": "2.1.1",
+ "version_normalized": "2.1.1.0",
"source": {
"type": "git",
"url": "https://github.com/ramsey/collection.git",
- "reference": "ab2237657ad99667a5143e32ba2683c8029563d4"
+ "reference": "344572933ad0181accbf4ba763e85a0306a8c5e2"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/ramsey/collection/zipball/ab2237657ad99667a5143e32ba2683c8029563d4",
- "reference": "ab2237657ad99667a5143e32ba2683c8029563d4",
+ "url": "https://api.github.com/repos/ramsey/collection/zipball/344572933ad0181accbf4ba763e85a0306a8c5e2",
+ "reference": "344572933ad0181accbf4ba763e85a0306a8c5e2",
"shasum": ""
},
"require": {
- "php": "^7.2 || ^8"
+ "php": "^8.1"
},
"require-dev": {
- "captainhook/captainhook": "^5.3",
- "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
- "ergebnis/composer-normalize": "^2.6",
- "fakerphp/faker": "^1.5",
- "hamcrest/hamcrest-php": "^2",
- "jangregor/phpstan-prophecy": "^0.8",
- "mockery/mockery": "^1.3",
- "phpstan/extension-installer": "^1",
- "phpstan/phpstan": "^0.12.32",
- "phpstan/phpstan-mockery": "^0.12.5",
- "phpstan/phpstan-phpunit": "^0.12.11",
- "phpunit/phpunit": "^8.5 || ^9",
- "psy/psysh": "^0.10.4",
- "slevomat/coding-standard": "^6.3",
- "squizlabs/php_codesniffer": "^3.5",
- "vimeo/psalm": "^4.4"
+ "captainhook/plugin-composer": "^5.3",
+ "ergebnis/composer-normalize": "^2.45",
+ "fakerphp/faker": "^1.24",
+ "hamcrest/hamcrest-php": "^2.0",
+ "jangregor/phpstan-prophecy": "^2.1",
+ "mockery/mockery": "^1.6",
+ "php-parallel-lint/php-console-highlighter": "^1.0",
+ "php-parallel-lint/php-parallel-lint": "^1.4",
+ "phpspec/prophecy-phpunit": "^2.3",
+ "phpstan/extension-installer": "^1.4",
+ "phpstan/phpstan": "^2.1",
+ "phpstan/phpstan-mockery": "^2.0",
+ "phpstan/phpstan-phpunit": "^2.0",
+ "phpunit/phpunit": "^10.5",
+ "ramsey/coding-standard": "^2.3",
+ "ramsey/conventional-commits": "^1.6",
+ "roave/security-advisories": "dev-latest"
},
- "time": "2021-07-30T00:58:27+00:00",
+ "time": "2025-03-22T05:38:12+00:00",
"type": "library",
"extra": {
- "patches_applied": {
- "Collection: Add PHP 8.1 support": "patches/ramsey-collection.patch"
+ "captainhook": {
+ "force-install": true
+ },
+ "ramsey/conventional-commits": {
+ "configFile": "conventional-commits.json"
}
},
"installation-source": "dist",
@@ -1206,7 +1186,7 @@
"homepage": "https://benramsey.com"
}
],
- "description": "A PHP 7.2+ library for representing and manipulating collections.",
+ "description": "A PHP library for representing and manipulating collections.",
"keywords": [
"array",
"collection",
@@ -1217,84 +1197,64 @@
],
"support": {
"issues": "https://github.com/ramsey/collection/issues",
- "source": "https://github.com/ramsey/collection/tree/1.1.4"
+ "source": "https://github.com/ramsey/collection/tree/2.1.1"
},
- "funding": [
- {
- "url": "https://github.com/ramsey",
- "type": "github"
- },
- {
- "url": "https://tidelift.com/funding/github/packagist/ramsey/collection",
- "type": "tidelift"
- }
- ],
"install-path": "../ramsey/collection"
},
{
"name": "ramsey/uuid",
- "version": "4.2.3",
- "version_normalized": "4.2.3.0",
+ "version": "4.9.1",
+ "version_normalized": "4.9.1.0",
"source": {
"type": "git",
"url": "https://github.com/ramsey/uuid.git",
- "reference": "fc9bb7fb5388691fd7373cd44dcb4d63bbcf24df"
+ "reference": "81f941f6f729b1e3ceea61d9d014f8b6c6800440"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/ramsey/uuid/zipball/fc9bb7fb5388691fd7373cd44dcb4d63bbcf24df",
- "reference": "fc9bb7fb5388691fd7373cd44dcb4d63bbcf24df",
+ "url": "https://api.github.com/repos/ramsey/uuid/zipball/81f941f6f729b1e3ceea61d9d014f8b6c6800440",
+ "reference": "81f941f6f729b1e3ceea61d9d014f8b6c6800440",
"shasum": ""
},
"require": {
- "brick/math": "^0.8 || ^0.9",
- "ext-json": "*",
- "php": "^7.2 || ^8.0",
- "ramsey/collection": "^1.0",
- "symfony/polyfill-ctype": "^1.8",
- "symfony/polyfill-php80": "^1.14"
+ "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12 || ^0.13 || ^0.14",
+ "php": "^8.0",
+ "ramsey/collection": "^1.2 || ^2.0"
},
"replace": {
"rhumsaa/uuid": "self.version"
},
"require-dev": {
- "captainhook/captainhook": "^5.10",
+ "captainhook/captainhook": "^5.25",
"captainhook/plugin-composer": "^5.3",
- "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
- "doctrine/annotations": "^1.8",
- "ergebnis/composer-normalize": "^2.15",
- "mockery/mockery": "^1.3",
- "moontoast/math": "^1.1",
+ "dealerdirect/phpcodesniffer-composer-installer": "^1.0",
+ "ergebnis/composer-normalize": "^2.47",
+ "mockery/mockery": "^1.6",
"paragonie/random-lib": "^2",
- "php-mock/php-mock": "^2.2",
- "php-mock/php-mock-mockery": "^1.3",
- "php-parallel-lint/php-parallel-lint": "^1.1",
- "phpbench/phpbench": "^1.0",
- "phpstan/extension-installer": "^1.0",
- "phpstan/phpstan": "^0.12",
- "phpstan/phpstan-mockery": "^0.12",
- "phpstan/phpstan-phpunit": "^0.12",
- "phpunit/phpunit": "^8.5 || ^9",
- "slevomat/coding-standard": "^7.0",
- "squizlabs/php_codesniffer": "^3.5",
- "vimeo/psalm": "^4.9"
+ "php-mock/php-mock": "^2.6",
+ "php-mock/php-mock-mockery": "^1.5",
+ "php-parallel-lint/php-parallel-lint": "^1.4.0",
+ "phpbench/phpbench": "^1.2.14",
+ "phpstan/extension-installer": "^1.4",
+ "phpstan/phpstan": "^2.1",
+ "phpstan/phpstan-mockery": "^2.0",
+ "phpstan/phpstan-phpunit": "^2.0",
+ "phpunit/phpunit": "^9.6",
+ "slevomat/coding-standard": "^8.18",
+ "squizlabs/php_codesniffer": "^3.13"
},
"suggest": {
"ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.",
- "ext-ctype": "Enables faster processing of character classification using ctype functions.",
"ext-gmp": "Enables faster math with arbitrary-precision integers using GMP.",
"ext-uuid": "Enables the use of PeclUuidTimeGenerator and PeclUuidRandomGenerator.",
"paragonie/random-lib": "Provides RandomLib for use with the RandomLibAdapter",
"ramsey/uuid-doctrine": "Allows the use of Ramsey\\Uuid\\Uuid as Doctrine field type."
},
- "time": "2021-09-25T23:10:38+00:00",
+ "time": "2025-09-04T20:59:21+00:00",
"type": "library",
"extra": {
"captainhook": {
"force-install": true
- },
- "branch-alias": {
- "dev-main": "4.x-dev"
}
},
"installation-source": "dist",
@@ -1318,18 +1278,8 @@
],
"support": {
"issues": "https://github.com/ramsey/uuid/issues",
- "source": "https://github.com/ramsey/uuid/tree/4.2.3"
+ "source": "https://github.com/ramsey/uuid/tree/4.9.1"
},
- "funding": [
- {
- "url": "https://github.com/ramsey",
- "type": "github"
- },
- {
- "url": "https://tidelift.com/funding/github/packagist/ramsey/uuid",
- "type": "tidelift"
- }
- ],
"install-path": "../ramsey/uuid"
},
{
@@ -1545,30 +1495,24 @@
"install-path": "../simshaun/recurr"
},
{
- "name": "symfony/polyfill-ctype",
+ "name": "symfony/polyfill-php84",
"version": "v1.33.0",
"version_normalized": "1.33.0.0",
"source": {
"type": "git",
- "url": "https://github.com/symfony/polyfill-ctype.git",
- "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638"
+ "url": "https://github.com/symfony/polyfill-php84.git",
+ "reference": "d8ced4d875142b6a7426000426b8abc631d6b191"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638",
- "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638",
+ "url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/d8ced4d875142b6a7426000426b8abc631d6b191",
+ "reference": "d8ced4d875142b6a7426000426b8abc631d6b191",
"shasum": ""
},
"require": {
"php": ">=7.2"
},
- "provide": {
- "ext-ctype": "*"
- },
- "suggest": {
- "ext-ctype": "For best performance"
- },
- "time": "2024-09-09T11:45:10+00:00",
+ "time": "2025-06-24T13:30:11+00:00",
"type": "library",
"extra": {
"thanks": {
@@ -1582,87 +1526,7 @@
"bootstrap.php"
],
"psr-4": {
- "Symfony\\Polyfill\\Ctype\\": ""
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Gert de Pagter",
- "email": "BackEndTea@gmail.com"
- },
- {
- "name": "Symfony Community",
- "homepage": "https://symfony.com/contributors"
- }
- ],
- "description": "Symfony polyfill for ctype functions",
- "homepage": "https://symfony.com",
- "keywords": [
- "compatibility",
- "ctype",
- "polyfill",
- "portable"
- ],
- "support": {
- "source": "https://github.com/symfony/polyfill-ctype/tree/v1.33.0"
- },
- "funding": [
- {
- "url": "https://symfony.com/sponsor",
- "type": "custom"
- },
- {
- "url": "https://github.com/fabpot",
- "type": "github"
- },
- {
- "url": "https://github.com/nicolas-grekas",
- "type": "github"
- },
- {
- "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
- "type": "tidelift"
- }
- ],
- "install-path": "../symfony/polyfill-ctype"
- },
- {
- "name": "symfony/polyfill-php80",
- "version": "v1.33.0",
- "version_normalized": "1.33.0.0",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/polyfill-php80.git",
- "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/0cc9dd0f17f61d8131e7df6b84bd344899fe2608",
- "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608",
- "shasum": ""
- },
- "require": {
- "php": ">=7.2"
- },
- "time": "2025-01-02T08:10:11+00:00",
- "type": "library",
- "extra": {
- "thanks": {
- "url": "https://github.com/symfony/polyfill",
- "name": "symfony/polyfill"
- }
- },
- "installation-source": "dist",
- "autoload": {
- "files": [
- "bootstrap.php"
- ],
- "psr-4": {
- "Symfony\\Polyfill\\Php80\\": ""
+ "Symfony\\Polyfill\\Php84\\": ""
},
"classmap": [
"Resources/stubs"
@@ -1673,10 +1537,6 @@
"MIT"
],
"authors": [
- {
- "name": "Ion Bazan",
- "email": "ion.bazan@gmail.com"
- },
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
@@ -1686,7 +1546,7 @@
"homepage": "https://symfony.com/contributors"
}
],
- "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions",
+ "description": "Symfony polyfill backporting some PHP 8.4+ features to lower PHP versions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
@@ -1695,7 +1555,7 @@
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-php80/tree/v1.33.0"
+ "source": "https://github.com/symfony/polyfill-php84/tree/v1.33.0"
},
"funding": [
{
@@ -1715,7 +1575,7 @@
"type": "tidelift"
}
],
- "install-path": "../symfony/polyfill-php80"
+ "install-path": "../symfony/polyfill-php84"
},
{
"name": "webmozart/assert",
diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php
index 4d20577..a02cdd1 100644
--- a/vendor/composer/installed.php
+++ b/vendor/composer/installed.php
@@ -3,7 +3,7 @@
'name' => 'icinga/icinga-php-library',
'pretty_version' => 'dev-main',
'version' => 'dev-main',
- 'reference' => 'a7944e40e1b1c5f88dcb04c253e07001cb9ddb4b',
+ 'reference' => '37ba112cf2652c85b744c0e5ae88971ca4867929',
'type' => 'project',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
@@ -11,27 +11,18 @@
),
'versions' => array(
'brick/math' => array(
- 'pretty_version' => '0.9.3',
- 'version' => '0.9.3.0',
- 'reference' => 'ca57d18f028f84f777b2168cd1911b0dee2343ae',
+ 'pretty_version' => '0.14.0',
+ 'version' => '0.14.0.0',
+ 'reference' => '113a8ee2656b882d4c3164fa31aa6e12cbb7aaa2',
'type' => 'library',
'install_path' => __DIR__ . '/../brick/math',
'aliases' => array(),
'dev_requirement' => false,
),
- 'cweagans/composer-patches' => array(
- 'pretty_version' => '1.7.3',
- 'version' => '1.7.3.0',
- 'reference' => 'e190d4466fe2b103a55467dfa83fc2fecfcaf2db',
- 'type' => 'composer-plugin',
- 'install_path' => __DIR__ . '/../cweagans/composer-patches',
- 'aliases' => array(),
- 'dev_requirement' => false,
- ),
'doctrine/collections' => array(
- 'pretty_version' => '1.8.0',
- 'version' => '1.8.0.0',
- 'reference' => '2b44dd4cbca8b5744327de78bafef5945c7e7b5e',
+ 'pretty_version' => '2.3.0',
+ 'version' => '2.3.0.0',
+ 'reference' => '2eb07e5953eed811ce1b309a7478a3b236f2273d',
'type' => 'library',
'install_path' => __DIR__ . '/../doctrine/collections',
'aliases' => array(),
@@ -85,82 +76,106 @@
'icinga/icinga-php-library' => array(
'pretty_version' => 'dev-main',
'version' => 'dev-main',
- 'reference' => 'a7944e40e1b1c5f88dcb04c253e07001cb9ddb4b',
+ 'reference' => '37ba112cf2652c85b744c0e5ae88971ca4867929',
'type' => 'project',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
'dev_requirement' => false,
),
'ipl/html' => array(
- 'pretty_version' => 'v0.8.2',
- 'version' => '0.8.2.0',
- 'reference' => 'e18bdf11abca5e477100e2c7d190ef5f424d0d98',
+ 'pretty_version' => 'dev-main',
+ 'version' => 'dev-main',
+ 'reference' => '9f698b99cab6bd0ab36ea56022c53ac89a7150fc',
'type' => 'library',
'install_path' => __DIR__ . '/../ipl/html',
- 'aliases' => array(),
+ 'aliases' => array(
+ 0 => '99.x-dev',
+ 1 => '9999999-dev',
+ ),
'dev_requirement' => false,
),
'ipl/i18n' => array(
- 'pretty_version' => 'v0.2.2',
- 'version' => '0.2.2.0',
- 'reference' => 'a2b6109c5a93f86ce46d5dc351dbe75e8502cf8c',
+ 'pretty_version' => 'dev-main',
+ 'version' => 'dev-main',
+ 'reference' => '692c33cf46fb8a4511da613dbf97c6216c345cc5',
'type' => 'library',
'install_path' => __DIR__ . '/../ipl/i18n',
- 'aliases' => array(),
+ 'aliases' => array(
+ 0 => '99.x-dev',
+ 1 => '9999999-dev',
+ ),
'dev_requirement' => false,
),
'ipl/orm' => array(
- 'pretty_version' => 'v0.6.3',
- 'version' => '0.6.3.0',
- 'reference' => 'a775a2745764a8dc7f28618cce69dcd7bbfd7915',
+ 'pretty_version' => 'dev-main',
+ 'version' => 'dev-main',
+ 'reference' => '2a0b72d21e2444501a940975f869297998c6cdfe',
'type' => 'library',
'install_path' => __DIR__ . '/../ipl/orm',
- 'aliases' => array(),
+ 'aliases' => array(
+ 0 => '99.x-dev',
+ 1 => '9999999-dev',
+ ),
'dev_requirement' => false,
),
'ipl/scheduler' => array(
- 'pretty_version' => 'v0.1.2',
- 'version' => '0.1.2.0',
- 'reference' => '6119afdea07b1390bd728e350e0d80b26ec8d6ba',
+ 'pretty_version' => 'dev-main',
+ 'version' => 'dev-main',
+ 'reference' => '3e4e8db870239d213b1dfd5d79d59fc7784b4c34',
'type' => 'library',
'install_path' => __DIR__ . '/../ipl/scheduler',
- 'aliases' => array(),
+ 'aliases' => array(
+ 0 => '99.x-dev',
+ 1 => '9999999-dev',
+ ),
'dev_requirement' => false,
),
'ipl/sql' => array(
- 'pretty_version' => 'v0.7.1',
- 'version' => '0.7.1.0',
- 'reference' => 'e80f1b712c4b96099b0bf9096e6efe317a165e3b',
+ 'pretty_version' => 'dev-main',
+ 'version' => 'dev-main',
+ 'reference' => '6f4258c4e3b20655db57d248e26edf7b54c04729',
'type' => 'library',
'install_path' => __DIR__ . '/../ipl/sql',
- 'aliases' => array(),
+ 'aliases' => array(
+ 0 => '99.x-dev',
+ 1 => '9999999-dev',
+ ),
'dev_requirement' => false,
),
'ipl/stdlib' => array(
- 'pretty_version' => 'v0.14.0',
- 'version' => '0.14.0.0',
- 'reference' => 'bf5fc8f40b86bd90337db6f3be389be2a93fa64a',
+ 'pretty_version' => 'dev-main',
+ 'version' => 'dev-main',
+ 'reference' => '9b7a903fbfc341da59f242149ac333594e4a6fa3',
'type' => 'library',
'install_path' => __DIR__ . '/../ipl/stdlib',
- 'aliases' => array(),
+ 'aliases' => array(
+ 0 => '99.x-dev',
+ 1 => '9999999-dev',
+ ),
'dev_requirement' => false,
),
'ipl/validator' => array(
- 'pretty_version' => 'v0.5.0',
- 'version' => '0.5.0.0',
- 'reference' => 'a601fae0ed330e63cea50e4a2a6659ca1ad97bde',
+ 'pretty_version' => 'dev-main',
+ 'version' => 'dev-main',
+ 'reference' => 'eac5c6c114d8007db5c24ae159fe6f55e89a946b',
'type' => 'library',
'install_path' => __DIR__ . '/../ipl/validator',
- 'aliases' => array(),
+ 'aliases' => array(
+ 0 => '99.x-dev',
+ 1 => '9999999-dev',
+ ),
'dev_requirement' => false,
),
'ipl/web' => array(
- 'pretty_version' => 'v0.10.2',
- 'version' => '0.10.2.0',
- 'reference' => 'a3d134c0d67aa51a9b186519c76e718603fda835',
+ 'pretty_version' => 'dev-main',
+ 'version' => 'dev-main',
+ 'reference' => '1fdd7aa977f8da19e17cc4535b023c0760aa442a',
'type' => 'library',
'install_path' => __DIR__ . '/../ipl/web',
- 'aliases' => array(),
+ 'aliases' => array(
+ 0 => '99.x-dev',
+ 1 => '9999999-dev',
+ ),
'dev_requirement' => false,
),
'mtdowling/cron-expression' => array(
@@ -218,18 +233,18 @@
'dev_requirement' => false,
),
'ramsey/collection' => array(
- 'pretty_version' => '1.1.4',
- 'version' => '1.1.4.0',
- 'reference' => 'ab2237657ad99667a5143e32ba2683c8029563d4',
+ 'pretty_version' => '2.1.1',
+ 'version' => '2.1.1.0',
+ 'reference' => '344572933ad0181accbf4ba763e85a0306a8c5e2',
'type' => 'library',
'install_path' => __DIR__ . '/../ramsey/collection',
'aliases' => array(),
'dev_requirement' => false,
),
'ramsey/uuid' => array(
- 'pretty_version' => '4.2.3',
- 'version' => '4.2.3.0',
- 'reference' => 'fc9bb7fb5388691fd7373cd44dcb4d63bbcf24df',
+ 'pretty_version' => '4.9.1',
+ 'version' => '4.9.1.0',
+ 'reference' => '81f941f6f729b1e3ceea61d9d014f8b6c6800440',
'type' => 'library',
'install_path' => __DIR__ . '/../ramsey/uuid',
'aliases' => array(),
@@ -256,7 +271,7 @@
'rhumsaa/uuid' => array(
'dev_requirement' => false,
'replaced' => array(
- 0 => '4.2.3',
+ 0 => '4.9.1',
),
),
'simshaun/recurr' => array(
@@ -268,21 +283,12 @@
'aliases' => array(),
'dev_requirement' => false,
),
- 'symfony/polyfill-ctype' => array(
+ 'symfony/polyfill-php84' => array(
'pretty_version' => 'v1.33.0',
'version' => '1.33.0.0',
- 'reference' => 'a3cc8b044a6ea513310cbd48ef7333b384945638',
+ 'reference' => 'd8ced4d875142b6a7426000426b8abc631d6b191',
'type' => 'library',
- 'install_path' => __DIR__ . '/../symfony/polyfill-ctype',
- 'aliases' => array(),
- 'dev_requirement' => false,
- ),
- 'symfony/polyfill-php80' => array(
- 'pretty_version' => 'v1.33.0',
- 'version' => '1.33.0.0',
- 'reference' => '0cc9dd0f17f61d8131e7df6b84bd344899fe2608',
- 'type' => 'library',
- 'install_path' => __DIR__ . '/../symfony/polyfill-php80',
+ 'install_path' => __DIR__ . '/../symfony/polyfill-php84',
'aliases' => array(),
'dev_requirement' => false,
),
diff --git a/vendor/composer/platform_check.php b/vendor/composer/platform_check.php
index 5da86a6..14bf88d 100644
--- a/vendor/composer/platform_check.php
+++ b/vendor/composer/platform_check.php
@@ -4,8 +4,8 @@
$issues = array();
-if (!(PHP_VERSION_ID >= 70209)) {
- $issues[] = 'Your Composer dependencies require a PHP version ">= 7.2.9". You are running ' . PHP_VERSION . '.';
+if (!(PHP_VERSION_ID >= 80200)) {
+ $issues[] = 'Your Composer dependencies require a PHP version ">= 8.2.0". You are running ' . PHP_VERSION . '.';
}
if ($issues) {
@@ -19,8 +19,7 @@ if ($issues) {
echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL;
}
}
- trigger_error(
- 'Composer detected issues in your platform: ' . implode(' ', $issues),
- E_USER_ERROR
+ throw new \RuntimeException(
+ 'Composer detected issues in your platform: ' . implode(' ', $issues)
);
}
diff --git a/vendor/cweagans/composer-patches/composer.json b/vendor/cweagans/composer-patches/composer.json
deleted file mode 100644
index 1565b02..0000000
--- a/vendor/cweagans/composer-patches/composer.json
+++ /dev/null
@@ -1,30 +0,0 @@
-{
- "name": "cweagans/composer-patches",
- "description": "Provides a way to patch Composer packages.",
- "minimum-stability": "dev",
- "license": "BSD-3-Clause",
- "type": "composer-plugin",
- "extra": {
- "class": "cweagans\\Composer\\Patches"
- },
- "authors": [
- {
- "name": "Cameron Eagans",
- "email": "me@cweagans.net"
- }
- ],
- "require": {
- "php": ">=5.3.0",
- "composer-plugin-api": "^1.0 || ^2.0"
- },
- "require-dev": {
- "composer/composer": "~1.0 || ~2.0",
- "phpunit/phpunit": "~4.6"
- },
- "autoload": {
- "psr-4": {"cweagans\\Composer\\": "src"}
- },
- "autoload-dev": {
- "psr-4": {"cweagans\\Composer\\Tests\\": "tests"}
- }
-}
diff --git a/vendor/cweagans/composer-patches/src/PatchEvent.php b/vendor/cweagans/composer-patches/src/PatchEvent.php
deleted file mode 100644
index 31d36f8..0000000
--- a/vendor/cweagans/composer-patches/src/PatchEvent.php
+++ /dev/null
@@ -1,70 +0,0 @@
-package = $package;
- $this->url = $url;
- $this->description = $description;
- }
-
- /**
- * Returns the package that is patched.
- *
- * @return PackageInterface
- */
- public function getPackage() {
- return $this->package;
- }
-
- /**
- * Returns the url of the patch.
- *
- * @return string
- */
- public function getUrl() {
- return $this->url;
- }
-
- /**
- * Returns the description of the patch.
- *
- * @return string
- */
- public function getDescription() {
- return $this->description;
- }
-
-}
diff --git a/vendor/cweagans/composer-patches/src/PatchEvents.php b/vendor/cweagans/composer-patches/src/PatchEvents.php
deleted file mode 100644
index ecee947..0000000
--- a/vendor/cweagans/composer-patches/src/PatchEvents.php
+++ /dev/null
@@ -1,30 +0,0 @@
-composer = $composer;
- $this->io = $io;
- $this->eventDispatcher = $composer->getEventDispatcher();
- $this->executor = new ProcessExecutor($this->io);
- $this->patches = array();
- $this->installedPatches = array();
- }
-
- /**
- * Returns an array of event names this subscriber wants to listen to.
- */
- public static function getSubscribedEvents() {
- return array(
- ScriptEvents::PRE_INSTALL_CMD => array('checkPatches'),
- ScriptEvents::PRE_UPDATE_CMD => array('checkPatches'),
- PackageEvents::PRE_PACKAGE_INSTALL => array('gatherPatches'),
- PackageEvents::PRE_PACKAGE_UPDATE => array('gatherPatches'),
- // The following is a higher weight for compatibility with
- // https://github.com/AydinHassan/magento-core-composer-installer and more generally for compatibility with
- // every Composer plugin which deploys downloaded packages to other locations.
- // In such cases you want that those plugins deploy patched files so they have to run after
- // the "composer-patches" plugin.
- // @see: https://github.com/cweagans/composer-patches/pull/153
- PackageEvents::POST_PACKAGE_INSTALL => array('postInstall', 10),
- PackageEvents::POST_PACKAGE_UPDATE => array('postInstall', 10),
- );
- }
-
- /**
- * Before running composer install,
- * @param Event $event
- */
- public function checkPatches(Event $event) {
- if (!$this->isPatchingEnabled()) {
- return;
- }
-
- try {
- $repositoryManager = $this->composer->getRepositoryManager();
- $localRepository = $repositoryManager->getLocalRepository();
- $installationManager = $this->composer->getInstallationManager();
- $packages = $localRepository->getPackages();
-
- $extra = $this->composer->getPackage()->getExtra();
- $patches_ignore = isset($extra['patches-ignore']) ? $extra['patches-ignore'] : array();
-
- $tmp_patches = $this->grabPatches();
- foreach ($packages as $package) {
- $extra = $package->getExtra();
- if (isset($extra['patches'])) {
- if (isset($patches_ignore[$package->getName()])) {
- foreach ($patches_ignore[$package->getName()] as $package_name => $patches) {
- if (isset($extra['patches'][$package_name])) {
- $extra['patches'][$package_name] = array_diff($extra['patches'][$package_name], $patches);
- }
- }
- }
- $this->installedPatches[$package->getName()] = $extra['patches'];
- }
- $patches = isset($extra['patches']) ? $extra['patches'] : array();
- $tmp_patches = $this->arrayMergeRecursiveDistinct($tmp_patches, $patches);
- }
-
- if ($tmp_patches == FALSE) {
- $this->io->write('No patches supplied.');
- return;
- }
-
- // Remove packages for which the patch set has changed.
- $promises = array();
- foreach ($packages as $package) {
- if (!($package instanceof AliasPackage)) {
- $package_name = $package->getName();
- $extra = $package->getExtra();
- $has_patches = isset($tmp_patches[$package_name]);
- $has_applied_patches = isset($extra['patches_applied']) && count($extra['patches_applied']) > 0;
- if (($has_patches && !$has_applied_patches)
- || (!$has_patches && $has_applied_patches)
- || ($has_patches && $has_applied_patches && $tmp_patches[$package_name] !== $extra['patches_applied'])) {
- $uninstallOperation = new UninstallOperation($package, 'Removing package so it can be re-installed and re-patched.');
- $this->io->write('Removing package ' . $package_name . ' so that it can be re-installed and re-patched.');
- $promises[] = $installationManager->uninstall($localRepository, $uninstallOperation);
- }
- }
- }
- $promises = array_filter($promises);
- if ($promises) {
- $this->composer->getLoop()->wait($promises);
- }
- }
- // If the Locker isn't available, then we don't need to do this.
- // It's the first time packages have been installed.
- catch (\LogicException $e) {
- return;
- }
- }
-
- /**
- * Gather patches from dependencies and store them for later use.
- *
- * @param PackageEvent $event
- */
- public function gatherPatches(PackageEvent $event) {
- // If we've already done this, then don't do it again.
- if (isset($this->patches['_patchesGathered'])) {
- $this->io->write('Patches already gathered. Skipping', TRUE, IOInterface::VERBOSE);
- return;
- }
- // If patching has been disabled, bail out here.
- elseif (!$this->isPatchingEnabled()) {
- $this->io->write('Patching is disabled. Skipping.', TRUE, IOInterface::VERBOSE);
- return;
- }
-
- $this->patches = $this->grabPatches();
- if (empty($this->patches)) {
- $this->io->write('No patches supplied.');
- }
-
- $extra = $this->composer->getPackage()->getExtra();
- $patches_ignore = isset($extra['patches-ignore']) ? $extra['patches-ignore'] : array();
-
- // Now add all the patches from dependencies that will be installed.
- $operations = $event->getOperations();
- $this->io->write('Gathering patches for dependencies. This might take a minute.');
- foreach ($operations as $operation) {
- if ($operation instanceof InstallOperation || $operation instanceof UpdateOperation) {
- $package = $this->getPackageFromOperation($operation);
- $extra = $package->getExtra();
- if (isset($extra['patches'])) {
- if (isset($patches_ignore[$package->getName()])) {
- foreach ($patches_ignore[$package->getName()] as $package_name => $patches) {
- if (isset($extra['patches'][$package_name])) {
- $extra['patches'][$package_name] = array_diff($extra['patches'][$package_name], $patches);
- }
- }
- }
- $this->patches = $this->arrayMergeRecursiveDistinct($this->patches, $extra['patches']);
- }
- // Unset installed patches for this package
- if(isset($this->installedPatches[$package->getName()])) {
- unset($this->installedPatches[$package->getName()]);
- }
- }
- }
-
- // Merge installed patches from dependencies that did not receive an update.
- foreach ($this->installedPatches as $patches) {
- $this->patches = $this->arrayMergeRecursiveDistinct($this->patches, $patches);
- }
-
- // If we're in verbose mode, list the projects we're going to patch.
- if ($this->io->isVerbose()) {
- foreach ($this->patches as $package => $patches) {
- $number = count($patches);
- $this->io->write('Found ' . $number . ' patches for ' . $package . '.');
- }
- }
-
- // Make sure we don't gather patches again. Extra keys in $this->patches
- // won't hurt anything, so we'll just stash it there.
- $this->patches['_patchesGathered'] = TRUE;
- }
-
- /**
- * Get the patches from root composer or external file
- * @return Patches
- * @throws \Exception
- */
- public function grabPatches() {
- // First, try to get the patches from the root composer.json.
- $extra = $this->composer->getPackage()->getExtra();
- if (isset($extra['patches'])) {
- $this->io->write('Gathering patches for root package.');
- $patches = $extra['patches'];
- return $patches;
- }
- // If it's not specified there, look for a patches-file definition.
- elseif (isset($extra['patches-file'])) {
- $this->io->write('Gathering patches from patch file.');
- $patches = file_get_contents($extra['patches-file']);
- $patches = json_decode($patches, TRUE);
- $error = json_last_error();
- if ($error != 0) {
- switch ($error) {
- case JSON_ERROR_DEPTH:
- $msg = ' - Maximum stack depth exceeded';
- break;
- case JSON_ERROR_STATE_MISMATCH:
- $msg = ' - Underflow or the modes mismatch';
- break;
- case JSON_ERROR_CTRL_CHAR:
- $msg = ' - Unexpected control character found';
- break;
- case JSON_ERROR_SYNTAX:
- $msg = ' - Syntax error, malformed JSON';
- break;
- case JSON_ERROR_UTF8:
- $msg = ' - Malformed UTF-8 characters, possibly incorrectly encoded';
- break;
- default:
- $msg = ' - Unknown error';
- break;
- }
- throw new \Exception('There was an error in the supplied patches file:' . $msg);
- }
- if (isset($patches['patches'])) {
- $patches = $patches['patches'];
- return $patches;
- }
- elseif(!$patches) {
- throw new \Exception('There was an error in the supplied patch file');
- }
- }
- else {
- return array();
- }
- }
-
- /**
- * @param PackageEvent $event
- * @throws \Exception
- */
- public function postInstall(PackageEvent $event) {
-
- // Check if we should exit in failure.
- $extra = $this->composer->getPackage()->getExtra();
- $exitOnFailure = getenv('COMPOSER_EXIT_ON_PATCH_FAILURE') || !empty($extra['composer-exit-on-patch-failure']);
- $skipReporting = getenv('COMPOSER_PATCHES_SKIP_REPORTING') || !empty($extra['composer-patches-skip-reporting']);
-
- // Get the package object for the current operation.
- $operation = $event->getOperation();
- /** @var PackageInterface $package */
- $package = $this->getPackageFromOperation($operation);
- $package_name = $package->getName();
-
- if (!isset($this->patches[$package_name])) {
- if ($this->io->isVerbose()) {
- $this->io->write('No patches found for ' . $package_name . '.');
- }
- return;
- }
- $this->io->write(' - Applying patches for ' . $package_name . '');
-
- // Get the install path from the package object.
- $manager = $event->getComposer()->getInstallationManager();
- $install_path = $manager->getInstaller($package->getType())->getInstallPath($package);
-
- // Set up a downloader.
- $downloader = new RemoteFilesystem($this->io, $this->composer->getConfig());
-
- // Track applied patches in the package info in installed.json
- $localRepository = $this->composer->getRepositoryManager()->getLocalRepository();
- $localPackage = $localRepository->findPackage($package_name, $package->getVersion());
- $extra = $localPackage->getExtra();
- $extra['patches_applied'] = array();
-
- foreach ($this->patches[$package_name] as $description => $url) {
- $this->io->write(' ' . $url . ' (' . $description. ')');
- try {
- $this->eventDispatcher->dispatch(NULL, new PatchEvent(PatchEvents::PRE_PATCH_APPLY, $package, $url, $description));
- $this->getAndApplyPatch($downloader, $install_path, $url, $package);
- $this->eventDispatcher->dispatch(NULL, new PatchEvent(PatchEvents::POST_PATCH_APPLY, $package, $url, $description));
- $extra['patches_applied'][$description] = $url;
- }
- catch (\Exception $e) {
- $this->io->write(' Could not apply patch! Skipping. The error was: ' . $e->getMessage() . '');
- if ($exitOnFailure) {
- throw new \Exception("Cannot apply patch $description ($url)!");
- }
- }
- }
- $localPackage->setExtra($extra);
-
- $this->io->write('');
-
- if (true !== $skipReporting) {
- $this->writePatchReport($this->patches[$package_name], $install_path);
- }
- }
-
- /**
- * Get a Package object from an OperationInterface object.
- *
- * @param OperationInterface $operation
- * @return PackageInterface
- * @throws \Exception
- */
- protected function getPackageFromOperation(OperationInterface $operation) {
- if ($operation instanceof InstallOperation) {
- $package = $operation->getPackage();
- }
- elseif ($operation instanceof UpdateOperation) {
- $package = $operation->getTargetPackage();
- }
- else {
- throw new \Exception('Unknown operation: ' . get_class($operation));
- }
-
- return $package;
- }
-
- /**
- * Apply a patch on code in the specified directory.
- *
- * @param RemoteFilesystem $downloader
- * @param $install_path
- * @param $patch_url
- * @param PackageInterface $package
- * @throws \Exception
- */
- protected function getAndApplyPatch(RemoteFilesystem $downloader, $install_path, $patch_url, PackageInterface $package) {
-
- // Local patch file.
- if (file_exists($patch_url)) {
- $filename = realpath($patch_url);
- }
- else {
- // Generate random (but not cryptographically so) filename.
- $filename = uniqid(sys_get_temp_dir().'/') . ".patch";
-
- // Download file from remote filesystem to this location.
- $hostname = parse_url($patch_url, PHP_URL_HOST);
-
- try {
- $downloader->copy($hostname, $patch_url, $filename, false);
- } catch (\Exception $e) {
- // In case of an exception, retry once as the download might
- // have failed due to intermittent network issues.
- $downloader->copy($hostname, $patch_url, $filename, false);
- }
- }
-
- // The order here is intentional. p1 is most likely to apply with git apply.
- // p0 is next likely. p2 is extremely unlikely, but for some special cases,
- // it might be useful. p4 is useful for Magento 2 patches
- $patch_levels = array('-p1', '-p0', '-p2', '-p4');
-
- // Check for specified patch level for this package.
- $extra = $this->composer->getPackage()->getExtra();
- if (!empty($extra['patchLevel'][$package->getName()])){
- $patch_levels = array($extra['patchLevel'][$package->getName()]);
- }
- // Attempt to apply with git apply.
- $patched = $this->applyPatchWithGit($install_path, $patch_levels, $filename);
-
- // In some rare cases, git will fail to apply a patch, fallback to using
- // the 'patch' command.
- if (!$patched) {
- foreach ($patch_levels as $patch_level) {
- // --no-backup-if-mismatch here is a hack that fixes some
- // differences between how patch works on windows and unix.
- if ($patched = $this->executeCommand("patch %s --no-backup-if-mismatch -d %s < %s", $patch_level, $install_path, $filename)) {
- break;
- }
- }
- }
-
- // Clean up the temporary patch file.
- if (isset($hostname)) {
- unlink($filename);
- }
- // If the patch *still* isn't applied, then give up and throw an Exception.
- // Otherwise, let the user know it worked.
- if (!$patched) {
- throw new \Exception("Cannot apply patch $patch_url");
- }
- }
-
- /**
- * Checks if the root package enables patching.
- *
- * @return bool
- * Whether patching is enabled. Defaults to TRUE.
- */
- protected function isPatchingEnabled() {
- $extra = $this->composer->getPackage()->getExtra();
-
- if (empty($extra['patches']) && empty($extra['patches-ignore']) && !isset($extra['patches-file'])) {
- // The root package has no patches of its own, so only allow patching if
- // it has specifically opted in.
- return isset($extra['enable-patching']) ? $extra['enable-patching'] : FALSE;
- }
- else {
- return TRUE;
- }
- }
-
- /**
- * Writes a patch report to the target directory.
- *
- * @param array $patches
- * @param string $directory
- */
- protected function writePatchReport($patches, $directory) {
- $output = "This file was automatically generated by Composer Patches (https://github.com/cweagans/composer-patches)\n";
- $output .= "Patches applied to this directory:\n\n";
- foreach ($patches as $description => $url) {
- $output .= $description . "\n";
- $output .= 'Source: ' . $url . "\n\n\n";
- }
- file_put_contents($directory . "/PATCHES.txt", $output);
- }
-
- /**
- * Executes a shell command with escaping.
- *
- * @param string $cmd
- * @return bool
- */
- protected function executeCommand($cmd) {
- // Shell-escape all arguments except the command.
- $args = func_get_args();
- foreach ($args as $index => $arg) {
- if ($index !== 0) {
- $args[$index] = escapeshellarg($arg);
- }
- }
-
- // And replace the arguments.
- $command = call_user_func_array('sprintf', $args);
- $output = '';
- if ($this->io->isVerbose()) {
- $this->io->write('' . $command . '');
- $io = $this->io;
- $output = function ($type, $data) use ($io) {
- if ($type == Process::ERR) {
- $io->write('' . $data . '');
- }
- else {
- $io->write('' . $data . '');
- }
- };
- }
- return ($this->executor->execute($command, $output) == 0);
- }
-
- /**
- * Recursively merge arrays without changing data types of values.
- *
- * Does not change the data types of the values in the arrays. Matching keys'
- * values in the second array overwrite those in the first array, as is the
- * case with array_merge.
- *
- * @param array $array1
- * The first array.
- * @param array $array2
- * The second array.
- * @return array
- * The merged array.
- *
- * @see http://php.net/manual/en/function.array-merge-recursive.php#92195
- */
- protected function arrayMergeRecursiveDistinct(array $array1, array $array2) {
- $merged = $array1;
-
- foreach ($array2 as $key => &$value) {
- if (is_array($value) && isset($merged[$key]) && is_array($merged[$key])) {
- $merged[$key] = $this->arrayMergeRecursiveDistinct($merged[$key], $value);
- }
- else {
- $merged[$key] = $value;
- }
- }
-
- return $merged;
- }
-
- /**
- * Attempts to apply a patch with git apply.
- *
- * @param $install_path
- * @param $patch_levels
- * @param $filename
- *
- * @return bool
- * TRUE if patch was applied, FALSE otherwise.
- */
- protected function applyPatchWithGit($install_path, $patch_levels, $filename) {
- // Do not use git apply unless the install path is itself a git repo
- // @see https://stackoverflow.com/a/27283285
- if (!is_dir($install_path . '/.git')) {
- return FALSE;
- }
-
- $patched = FALSE;
- foreach ($patch_levels as $patch_level) {
- if ($this->io->isVerbose()) {
- $comment = 'Testing ability to patch with git apply.';
- $comment .= ' This command may produce errors that can be safely ignored.';
- $this->io->write('' . $comment . '');
- }
- $checked = $this->executeCommand('git -C %s apply --check -v %s %s', $install_path, $patch_level, $filename);
- $output = $this->executor->getErrorOutput();
- if (substr($output, 0, 7) == 'Skipped') {
- // Git will indicate success but silently skip patches in some scenarios.
- //
- // @see https://github.com/cweagans/composer-patches/pull/165
- $checked = FALSE;
- }
- if ($checked) {
- // Apply the first successful style.
- $patched = $this->executeCommand('git -C %s apply %s %s', $install_path, $patch_level, $filename);
- break;
- }
- }
- return $patched;
- }
-
- /**
- * Indicates if a package has been patched.
- *
- * @param \Composer\Package\PackageInterface $package
- * The package to check.
- *
- * @return bool
- * TRUE if the package has been patched.
- */
- public static function isPackagePatched(PackageInterface $package) {
- return array_key_exists('patches_applied', $package->getExtra());
- }
-
- /**
- * {@inheritDoc}
- */
- public function deactivate(Composer $composer, IOInterface $io)
- {
- }
-
- /**
- * {@inheritDoc}
- */
- public function uninstall(Composer $composer, IOInterface $io)
- {
- }
-
-}
diff --git a/vendor/doctrine/collections/.doctrine-project.json b/vendor/doctrine/collections/.doctrine-project.json
deleted file mode 100644
index 9c89e50..0000000
--- a/vendor/doctrine/collections/.doctrine-project.json
+++ /dev/null
@@ -1,32 +0,0 @@
-{
- "active": true,
- "name": "Collections",
- "slug": "collections",
- "docsSlug": "doctrine-collections",
- "versions": [
- {
- "name": "2.0",
- "branchName": "2.0.x",
- "slug": "latest",
- "upcoming": true
- },
- {
- "name": "1.8",
- "branchName": "1.8.x",
- "slug": "1.8",
- "upcoming": true
- },
- {
- "name": "1.7",
- "branchName": "1.7.x",
- "slug": "1.7",
- "current": true
- },
- {
- "name": "1.6",
- "branchName": "1.6.x",
- "slug": "1.6",
- "maintained": false
- }
- ]
-}
diff --git a/vendor/doctrine/collections/composer.json b/vendor/doctrine/collections/composer.json
index d9422dd..cf5ee1a 100644
--- a/vendor/doctrine/collections/composer.json
+++ b/vendor/doctrine/collections/composer.json
@@ -33,23 +33,25 @@
],
"homepage": "https://www.doctrine-project.org/projects/collections.html",
"require": {
- "php": "^7.1.3 || ^8.0",
- "doctrine/deprecations": "^0.5.3 || ^1"
+ "php": "^8.1",
+ "doctrine/deprecations": "^1",
+ "symfony/polyfill-php84": "^1.30"
},
"require-dev": {
- "doctrine/coding-standard": "^9.0 || ^10.0",
- "phpstan/phpstan": "^1.4.8",
- "phpunit/phpunit": "^7.5 || ^8.5 || ^9.1.5",
- "vimeo/psalm": "^4.22"
+ "ext-json": "*",
+ "doctrine/coding-standard": "^12",
+ "phpstan/phpstan": "^1.8",
+ "phpstan/phpstan-phpunit": "^1.0",
+ "phpunit/phpunit": "^10.5"
},
"autoload": {
"psr-4": {
- "Doctrine\\Common\\Collections\\": "lib/Doctrine/Common/Collections"
+ "Doctrine\\Common\\Collections\\": "src"
}
},
"autoload-dev": {
"psr-4": {
- "Doctrine\\Tests\\": "tests/Doctrine/Tests"
+ "Doctrine\\Tests\\Common\\Collections\\": "tests"
}
},
"config": {
diff --git a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/ClosureExpressionVisitor.php b/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/ClosureExpressionVisitor.php
deleted file mode 100644
index c10b8d5..0000000
--- a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/ClosureExpressionVisitor.php
+++ /dev/null
@@ -1,269 +0,0 @@
-$accessor();
- }
- }
-
- if (preg_match('/^is[A-Z]+/', $field) === 1 && method_exists($object, $field)) {
- return $object->$field();
- }
-
- // __call should be triggered for get.
- $accessor = $accessors[0] . $field;
-
- if (method_exists($object, '__call')) {
- return $object->$accessor();
- }
-
- if ($object instanceof ArrayAccess) {
- return $object[$field];
- }
-
- if (isset($object->$field)) {
- return $object->$field;
- }
-
- // camelcase field name to support different variable naming conventions
- $ccField = preg_replace_callback('/_(.?)/', static function ($matches) {
- return strtoupper($matches[1]);
- }, $field);
-
- foreach ($accessors as $accessor) {
- $accessor .= $ccField;
-
- if (method_exists($object, $accessor)) {
- return $object->$accessor();
- }
- }
-
- return $object->$field;
- }
-
- /**
- * Helper for sorting arrays of objects based on multiple fields + orientations.
- *
- * @param string $name
- * @param int $orientation
- *
- * @return Closure
- */
- public static function sortByField($name, $orientation = 1, ?Closure $next = null)
- {
- if (! $next) {
- $next = static function (): int {
- return 0;
- };
- }
-
- return static function ($a, $b) use ($name, $next, $orientation): int {
- $aValue = ClosureExpressionVisitor::getObjectFieldValue($a, $name);
-
- $bValue = ClosureExpressionVisitor::getObjectFieldValue($b, $name);
-
- if ($aValue === $bValue) {
- return $next($a, $b);
- }
-
- return ($aValue > $bValue ? 1 : -1) * $orientation;
- };
- }
-
- /**
- * {@inheritDoc}
- */
- public function walkComparison(Comparison $comparison)
- {
- $field = $comparison->getField();
- $value = $comparison->getValue()->getValue(); // shortcut for walkValue()
-
- switch ($comparison->getOperator()) {
- case Comparison::EQ:
- return static function ($object) use ($field, $value): bool {
- return ClosureExpressionVisitor::getObjectFieldValue($object, $field) === $value;
- };
-
- case Comparison::NEQ:
- return static function ($object) use ($field, $value): bool {
- return ClosureExpressionVisitor::getObjectFieldValue($object, $field) !== $value;
- };
-
- case Comparison::LT:
- return static function ($object) use ($field, $value): bool {
- return ClosureExpressionVisitor::getObjectFieldValue($object, $field) < $value;
- };
-
- case Comparison::LTE:
- return static function ($object) use ($field, $value): bool {
- return ClosureExpressionVisitor::getObjectFieldValue($object, $field) <= $value;
- };
-
- case Comparison::GT:
- return static function ($object) use ($field, $value): bool {
- return ClosureExpressionVisitor::getObjectFieldValue($object, $field) > $value;
- };
-
- case Comparison::GTE:
- return static function ($object) use ($field, $value): bool {
- return ClosureExpressionVisitor::getObjectFieldValue($object, $field) >= $value;
- };
-
- case Comparison::IN:
- return static function ($object) use ($field, $value): bool {
- $fieldValue = ClosureExpressionVisitor::getObjectFieldValue($object, $field);
-
- return in_array($fieldValue, $value, is_scalar($fieldValue));
- };
-
- case Comparison::NIN:
- return static function ($object) use ($field, $value): bool {
- $fieldValue = ClosureExpressionVisitor::getObjectFieldValue($object, $field);
-
- return ! in_array($fieldValue, $value, is_scalar($fieldValue));
- };
-
- case Comparison::CONTAINS:
- return static function ($object) use ($field, $value) {
- return strpos(ClosureExpressionVisitor::getObjectFieldValue($object, $field), $value) !== false;
- };
-
- case Comparison::MEMBER_OF:
- return static function ($object) use ($field, $value): bool {
- $fieldValues = ClosureExpressionVisitor::getObjectFieldValue($object, $field);
-
- if (! is_array($fieldValues)) {
- $fieldValues = iterator_to_array($fieldValues);
- }
-
- return in_array($value, $fieldValues, true);
- };
-
- case Comparison::STARTS_WITH:
- return static function ($object) use ($field, $value): bool {
- return strpos(ClosureExpressionVisitor::getObjectFieldValue($object, $field), $value) === 0;
- };
-
- case Comparison::ENDS_WITH:
- return static function ($object) use ($field, $value): bool {
- return $value === substr(ClosureExpressionVisitor::getObjectFieldValue($object, $field), -strlen($value));
- };
-
- default:
- throw new RuntimeException('Unknown comparison operator: ' . $comparison->getOperator());
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public function walkValue(Value $value)
- {
- return $value->getValue();
- }
-
- /**
- * {@inheritDoc}
- */
- public function walkCompositeExpression(CompositeExpression $expr)
- {
- $expressionList = [];
-
- foreach ($expr->getExpressionList() as $child) {
- $expressionList[] = $this->dispatch($child);
- }
-
- switch ($expr->getType()) {
- case CompositeExpression::TYPE_AND:
- return $this->andExpressions($expressionList);
-
- case CompositeExpression::TYPE_OR:
- return $this->orExpressions($expressionList);
-
- default:
- throw new RuntimeException('Unknown composite ' . $expr->getType());
- }
- }
-
- /** @param callable[] $expressions */
- private function andExpressions(array $expressions): callable
- {
- return static function ($object) use ($expressions): bool {
- foreach ($expressions as $expression) {
- if (! $expression($object)) {
- return false;
- }
- }
-
- return true;
- };
- }
-
- /** @param callable[] $expressions */
- private function orExpressions(array $expressions): callable
- {
- return static function ($object) use ($expressions): bool {
- foreach ($expressions as $expression) {
- if ($expression($object)) {
- return true;
- }
- }
-
- return false;
- };
- }
-}
diff --git a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/Comparison.php b/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/Comparison.php
deleted file mode 100644
index 6762b8b..0000000
--- a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/Comparison.php
+++ /dev/null
@@ -1,74 +0,0 @@
-';
- public const LT = '<';
- public const LTE = '<=';
- public const GT = '>';
- public const GTE = '>=';
- public const IS = '='; // no difference with EQ
- public const IN = 'IN';
- public const NIN = 'NIN';
- public const CONTAINS = 'CONTAINS';
- public const MEMBER_OF = 'MEMBER_OF';
- public const STARTS_WITH = 'STARTS_WITH';
- public const ENDS_WITH = 'ENDS_WITH';
-
- /** @var string */
- private $field;
-
- /** @var string */
- private $op;
-
- /** @var Value */
- private $value;
-
- /**
- * @param string $field
- * @param string $operator
- * @param mixed $value
- */
- public function __construct($field, $operator, $value)
- {
- if (! ($value instanceof Value)) {
- $value = new Value($value);
- }
-
- $this->field = $field;
- $this->op = $operator;
- $this->value = $value;
- }
-
- /** @return string */
- public function getField()
- {
- return $this->field;
- }
-
- /** @return Value */
- public function getValue()
- {
- return $this->value;
- }
-
- /** @return string */
- public function getOperator()
- {
- return $this->op;
- }
-
- /**
- * {@inheritDoc}
- */
- public function visit(ExpressionVisitor $visitor)
- {
- return $visitor->walkComparison($this);
- }
-}
diff --git a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/ExpressionBuilder.php b/vendor/doctrine/collections/lib/Doctrine/Common/Collections/ExpressionBuilder.php
deleted file mode 100644
index ebb21ca..0000000
--- a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/ExpressionBuilder.php
+++ /dev/null
@@ -1,181 +0,0 @@
-
*/
abstract class AbstractLazyCollection implements Collection
@@ -19,13 +21,12 @@ abstract class AbstractLazyCollection implements Collection
/**
* The backed collection to use
*
- * @psalm-var Collection|null
+ * @phpstan-var Collection|null
* @var Collection|null
*/
- protected $collection;
+ protected Collection|null $collection;
- /** @var bool */
- protected $initialized = false;
+ protected bool $initialized = false;
/**
* {@inheritDoc}
@@ -43,11 +44,11 @@ abstract class AbstractLazyCollection implements Collection
/**
* {@inheritDoc}
*/
- public function add($element)
+ public function add(mixed $element)
{
$this->initialize();
- return $this->collection->add($element);
+ $this->collection->add($element);
}
/**
@@ -61,10 +62,8 @@ abstract class AbstractLazyCollection implements Collection
/**
* {@inheritDoc}
- *
- * @template TMaybeContained
*/
- public function contains($element)
+ public function contains(mixed $element)
{
$this->initialize();
@@ -84,7 +83,7 @@ abstract class AbstractLazyCollection implements Collection
/**
* {@inheritDoc}
*/
- public function remove($key)
+ public function remove(string|int $key)
{
$this->initialize();
@@ -94,7 +93,7 @@ abstract class AbstractLazyCollection implements Collection
/**
* {@inheritDoc}
*/
- public function removeElement($element)
+ public function removeElement(mixed $element)
{
$this->initialize();
@@ -104,7 +103,7 @@ abstract class AbstractLazyCollection implements Collection
/**
* {@inheritDoc}
*/
- public function containsKey($key)
+ public function containsKey(string|int $key)
{
$this->initialize();
@@ -114,7 +113,7 @@ abstract class AbstractLazyCollection implements Collection
/**
* {@inheritDoc}
*/
- public function get($key)
+ public function get(string|int $key)
{
$this->initialize();
@@ -144,7 +143,7 @@ abstract class AbstractLazyCollection implements Collection
/**
* {@inheritDoc}
*/
- public function set($key, $value)
+ public function set(string|int $key, mixed $value)
{
$this->initialize();
$this->collection->set($key, $value);
@@ -220,6 +219,16 @@ abstract class AbstractLazyCollection implements Collection
return $this->collection->exists($p);
}
+ /**
+ * {@inheritDoc}
+ */
+ public function findFirst(Closure $p)
+ {
+ $this->initialize();
+
+ return $this->collection->findFirst($p);
+ }
+
/**
* {@inheritDoc}
*/
@@ -250,6 +259,16 @@ abstract class AbstractLazyCollection implements Collection
return $this->collection->map($func);
}
+ /**
+ * {@inheritDoc}
+ */
+ public function reduce(Closure $func, mixed $initial = null)
+ {
+ $this->initialize();
+
+ return $this->collection->reduce($func, $initial);
+ }
+
/**
* {@inheritDoc}
*/
@@ -265,7 +284,7 @@ abstract class AbstractLazyCollection implements Collection
*
* @template TMaybeContained
*/
- public function indexOf($element)
+ public function indexOf(mixed $element)
{
$this->initialize();
@@ -275,7 +294,7 @@ abstract class AbstractLazyCollection implements Collection
/**
* {@inheritDoc}
*/
- public function slice($offset, $length = null)
+ public function slice(int $offset, int|null $length = null)
{
$this->initialize();
@@ -286,7 +305,7 @@ abstract class AbstractLazyCollection implements Collection
* {@inheritDoc}
*
* @return Traversable
- * @psalm-return Traversable
+ * @phpstan-return Traversable
*/
#[ReturnTypeWillChange]
public function getIterator()
@@ -297,12 +316,14 @@ abstract class AbstractLazyCollection implements Collection
}
/**
+ * {@inheritDoc}
+ *
* @param TKey $offset
*
* @return bool
*/
#[ReturnTypeWillChange]
- public function offsetExists($offset)
+ public function offsetExists(mixed $offset)
{
$this->initialize();
@@ -310,12 +331,14 @@ abstract class AbstractLazyCollection implements Collection
}
/**
+ * {@inheritDoc}
+ *
* @param TKey $offset
*
- * @return mixed
+ * @return T|null
*/
#[ReturnTypeWillChange]
- public function offsetGet($offset)
+ public function offsetGet(mixed $offset)
{
$this->initialize();
@@ -323,13 +346,15 @@ abstract class AbstractLazyCollection implements Collection
}
/**
+ * {@inheritDoc}
+ *
* @param TKey|null $offset
* @param T $value
*
* @return void
*/
#[ReturnTypeWillChange]
- public function offsetSet($offset, $value)
+ public function offsetSet(mixed $offset, mixed $value)
{
$this->initialize();
$this->collection->offsetSet($offset, $value);
@@ -341,7 +366,7 @@ abstract class AbstractLazyCollection implements Collection
* @return void
*/
#[ReturnTypeWillChange]
- public function offsetUnset($offset)
+ public function offsetUnset(mixed $offset)
{
$this->initialize();
$this->collection->offsetUnset($offset);
@@ -352,7 +377,7 @@ abstract class AbstractLazyCollection implements Collection
*
* @return bool
*
- * @psalm-assert-if-true Collection $this->collection
+ * @phpstan-assert-if-true Collection $this->collection
*/
public function isInitialized()
{
@@ -364,7 +389,7 @@ abstract class AbstractLazyCollection implements Collection
*
* @return void
*
- * @psalm-assert Collection $this->collection
+ * @phpstan-assert Collection $this->collection
*/
protected function initialize()
{
diff --git a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/ArrayCollection.php b/vendor/doctrine/collections/src/ArrayCollection.php
similarity index 74%
rename from vendor/doctrine/collections/lib/Doctrine/Common/Collections/ArrayCollection.php
rename to vendor/doctrine/collections/src/ArrayCollection.php
index 186f6ec..af81fa8 100644
--- a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/ArrayCollection.php
+++ b/vendor/doctrine/collections/src/ArrayCollection.php
@@ -1,17 +1,24 @@
* @template-implements Selectable
- * @psalm-consistent-constructor
+ * @phpstan-consistent-constructor
*/
-class ArrayCollection implements Collection, Selectable
+class ArrayCollection implements Collection, Selectable, Stringable
{
/**
* An array containing the entries of this collection.
*
- * @psalm-var array
+ * @phpstan-var array
* @var mixed[]
*/
- private $elements;
+ private array $elements = [];
/**
* Initializes a new ArrayCollection.
*
- * @param array $elements
- * @psalm-param array $elements
+ * @phpstan-param array $elements
*/
public function __construct(array $elements = [])
{
@@ -86,13 +92,13 @@ class ArrayCollection implements Collection, Selectable
* instance should be created when constructor semantics have changed.
*
* @param array $elements Elements.
- * @psalm-param array $elements
+ * @phpstan-param array $elements
*
* @return static
- * @psalm-return static
+ * @phpstan-return static
*
- * @psalm-template K of array-key
- * @psalm-template V
+ * @phpstan-template K of array-key
+ * @phpstan-template V
*/
protected function createFrom(array $elements)
{
@@ -134,7 +140,7 @@ class ArrayCollection implements Collection, Selectable
/**
* {@inheritDoc}
*/
- public function remove($key)
+ public function remove(string|int $key)
{
if (! isset($this->elements[$key]) && ! array_key_exists($key, $this->elements)) {
return null;
@@ -149,7 +155,7 @@ class ArrayCollection implements Collection, Selectable
/**
* {@inheritDoc}
*/
- public function removeElement($element)
+ public function removeElement(mixed $element)
{
$key = array_search($element, $this->elements, true);
@@ -170,7 +176,7 @@ class ArrayCollection implements Collection, Selectable
* @return bool
*/
#[ReturnTypeWillChange]
- public function offsetExists($offset)
+ public function offsetExists(mixed $offset)
{
return $this->containsKey($offset);
}
@@ -180,10 +186,10 @@ class ArrayCollection implements Collection, Selectable
*
* @param TKey $offset
*
- * @return mixed
+ * @return T|null
*/
#[ReturnTypeWillChange]
- public function offsetGet($offset)
+ public function offsetGet(mixed $offset)
{
return $this->get($offset);
}
@@ -197,9 +203,9 @@ class ArrayCollection implements Collection, Selectable
* @return void
*/
#[ReturnTypeWillChange]
- public function offsetSet($offset, $value)
+ public function offsetSet(mixed $offset, mixed $value)
{
- if (! isset($offset)) {
+ if ($offset === null) {
$this->add($value);
return;
@@ -216,7 +222,7 @@ class ArrayCollection implements Collection, Selectable
* @return void
*/
#[ReturnTypeWillChange]
- public function offsetUnset($offset)
+ public function offsetUnset(mixed $offset)
{
$this->remove($offset);
}
@@ -224,17 +230,15 @@ class ArrayCollection implements Collection, Selectable
/**
* {@inheritDoc}
*/
- public function containsKey($key)
+ public function containsKey(string|int $key)
{
return isset($this->elements[$key]) || array_key_exists($key, $this->elements);
}
/**
* {@inheritDoc}
- *
- * @template TMaybeContained
*/
- public function contains($element)
+ public function contains(mixed $element)
{
return in_array($element, $this->elements, true);
}
@@ -244,21 +248,19 @@ class ArrayCollection implements Collection, Selectable
*/
public function exists(Closure $p)
{
- foreach ($this->elements as $key => $element) {
- if ($p($key, $element)) {
- return true;
- }
- }
-
- return false;
+ return array_any(
+ $this->elements,
+ static fn (mixed $element, mixed $key): bool => (bool) $p($key, $element),
+ );
}
/**
* {@inheritDoc}
*
- * @psalm-param TMaybeContained $element
+ * @phpstan-param TMaybeContained $element
*
- * @psalm-return (TMaybeContained is T ? TKey|false : false)
+ * @return int|string|false
+ * @phpstan-return (TMaybeContained is T ? TKey|false : false)
*
* @template TMaybeContained
*/
@@ -270,7 +272,7 @@ class ArrayCollection implements Collection, Selectable
/**
* {@inheritDoc}
*/
- public function get($key)
+ public function get(string|int $key)
{
return $this->elements[$key] ?? null;
}
@@ -294,7 +296,7 @@ class ArrayCollection implements Collection, Selectable
/**
* {@inheritDoc}
*
- * @return int
+ * @return int<0, max>
*/
#[ReturnTypeWillChange]
public function count()
@@ -305,7 +307,7 @@ class ArrayCollection implements Collection, Selectable
/**
* {@inheritDoc}
*/
- public function set($key, $value)
+ public function set(string|int $key, mixed $value)
{
$this->elements[$key] = $value;
}
@@ -313,16 +315,12 @@ class ArrayCollection implements Collection, Selectable
/**
* {@inheritDoc}
*
- * @psalm-suppress InvalidPropertyAssignmentValue
- *
* This breaks assumptions about the template type, but it would
* be a backwards-incompatible change to remove this method
*/
- public function add($element)
+ public function add(mixed $element)
{
$this->elements[] = $element;
-
- return true;
}
/**
@@ -337,7 +335,7 @@ class ArrayCollection implements Collection, Selectable
* {@inheritDoc}
*
* @return Traversable
- * @psalm-return Traversable
+ * @phpstan-return Traversable
*/
#[ReturnTypeWillChange]
public function getIterator()
@@ -348,12 +346,12 @@ class ArrayCollection implements Collection, Selectable
/**
* {@inheritDoc}
*
- * @psalm-param Closure(T):U $func
+ * @phpstan-param Closure(T):U $func
*
* @return static
- * @psalm-return static
+ * @phpstan-return static
*
- * @psalm-template U
+ * @phpstan-template U
*/
public function map(Closure $func)
{
@@ -362,27 +360,45 @@ class ArrayCollection implements Collection, Selectable
/**
* {@inheritDoc}
+ */
+ public function reduce(Closure $func, $initial = null)
+ {
+ return array_reduce($this->elements, $func, $initial);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @phpstan-param Closure(T, TKey):bool $p
*
* @return static
- * @psalm-return static
+ * @phpstan-return static
*/
public function filter(Closure $p)
{
return $this->createFrom(array_filter($this->elements, $p, ARRAY_FILTER_USE_BOTH));
}
+ /**
+ * {@inheritDoc}
+ */
+ public function findFirst(Closure $p)
+ {
+ return array_find(
+ $this->elements,
+ static fn (mixed $element, mixed $key): bool => (bool) $p($key, $element),
+ );
+ }
+
/**
* {@inheritDoc}
*/
public function forAll(Closure $p)
{
- foreach ($this->elements as $key => $element) {
- if (! $p($key, $element)) {
- return false;
- }
- }
-
- return true;
+ return array_all(
+ $this->elements,
+ static fn (mixed $element, mixed $key): bool => (bool) $p($key, $element),
+ );
}
/**
@@ -405,9 +421,11 @@ class ArrayCollection implements Collection, Selectable
/**
* Returns a string representation of this object.
+ * {@inheritDoc}
*
* @return string
*/
+ #[ReturnTypeWillChange]
public function __toString()
{
return self::class . '@' . spl_object_hash($this);
@@ -424,14 +442,12 @@ class ArrayCollection implements Collection, Selectable
/**
* {@inheritDoc}
*/
- public function slice($offset, $length = null)
+ public function slice(int $offset, int|null $length = null)
{
return array_slice($this->elements, $offset, $length, true);
}
- /**
- * {@inheritDoc}
- */
+ /** @phpstan-return Collection&Selectable */
public function matching(Criteria $criteria)
{
$expr = $criteria->getWhereExpression();
@@ -443,12 +459,12 @@ class ArrayCollection implements Collection, Selectable
$filtered = array_filter($filtered, $filter);
}
- $orderings = $criteria->getOrderings();
+ $orderings = $criteria->orderings();
if ($orderings) {
$next = null;
foreach (array_reverse($orderings) as $field => $ordering) {
- $next = ClosureExpressionVisitor::sortByField($field, $ordering === Criteria::DESC ? -1 : 1, $next);
+ $next = ClosureExpressionVisitor::sortByField($field, $ordering === Order::Descending ? -1 : 1, $next);
}
uasort($filtered, $next);
@@ -457,8 +473,8 @@ class ArrayCollection implements Collection, Selectable
$offset = $criteria->getFirstResult();
$length = $criteria->getMaxResults();
- if ($offset || $length) {
- $filtered = array_slice($filtered, (int) $offset, $length);
+ if ($offset !== null && $offset > 0 || $length !== null && $length > 0) {
+ $filtered = array_slice($filtered, (int) $offset, $length, true);
}
return $this->createFrom($filtered);
diff --git a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Collection.php b/vendor/doctrine/collections/src/Collection.php
similarity index 71%
rename from vendor/doctrine/collections/lib/Doctrine/Common/Collections/Collection.php
rename to vendor/doctrine/collections/src/Collection.php
index fb09192..265d9d8 100644
--- a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Collection.php
+++ b/vendor/doctrine/collections/src/Collection.php
@@ -1,5 +1,7 @@
* @template-extends ArrayAccess
*/
@@ -33,11 +35,11 @@ interface Collection extends ReadableCollection, ArrayAccess
* Adds an element at the end of the collection.
*
* @param mixed $element The element to add.
- * @psalm-param T $element
+ * @phpstan-param T $element
*
- * @return true Always TRUE.
+ * @return void we will require a native return type declaration in 3.0
*/
- public function add($element);
+ public function add(mixed $element);
/**
* Clears the collection, removing all elements.
@@ -50,50 +52,66 @@ interface Collection extends ReadableCollection, ArrayAccess
* Removes the element at the specified index from the collection.
*
* @param string|int $key The key/index of the element to remove.
- * @psalm-param TKey $key
+ * @phpstan-param TKey $key
*
* @return mixed The removed element or NULL, if the collection did not contain the element.
- * @psalm-return T|null
+ * @phpstan-return T|null
*/
- public function remove($key);
+ public function remove(string|int $key);
/**
* Removes the specified element from the collection, if it is found.
*
* @param mixed $element The element to remove.
- * @psalm-param T $element
+ * @phpstan-param T $element
*
* @return bool TRUE if this collection contained the specified element, FALSE otherwise.
*/
- public function removeElement($element);
+ public function removeElement(mixed $element);
/**
* Sets an element in the collection at the specified key/index.
*
* @param string|int $key The key/index of the element to set.
* @param mixed $value The element to set.
- * @psalm-param TKey $key
- * @psalm-param T $value
+ * @phpstan-param TKey $key
+ * @phpstan-param T $value
*
* @return void
*/
- public function set($key, $value);
+ public function set(string|int $key, mixed $value);
/**
- * {@inheritdoc}
+ * {@inheritDoc}
+ *
+ * @phpstan-param Closure(T):U $func
+ *
+ * @return Collection
+ * @phpstan-return Collection
+ *
+ * @phpstan-template U
+ */
+ public function map(Closure $func);
+
+ /**
+ * {@inheritDoc}
+ *
+ * @phpstan-param Closure(T, TKey):bool $p
*
* @return Collection A collection with the results of the filter operation.
- * @psalm-return Collection
+ * @phpstan-return Collection
*/
public function filter(Closure $p);
/**
- * {@inheritdoc}
+ * {@inheritDoc}
+ *
+ * @phpstan-param Closure(TKey, T):bool $p
*
* @return Collection[] An array with two elements. The first element contains the collection
* of elements where the predicate returned TRUE, the second element
* contains the collection of elements where the predicate returned FALSE.
- * @psalm-return array{0: Collection, 1: Collection}
+ * @phpstan-return array{0: Collection, 1: Collection}
*/
public function partition(Closure $p);
}
diff --git a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Criteria.php b/vendor/doctrine/collections/src/Criteria.php
similarity index 62%
rename from vendor/doctrine/collections/lib/Doctrine/Common/Collections/Criteria.php
rename to vendor/doctrine/collections/src/Criteria.php
index c1639d3..7e690b4 100644
--- a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Criteria.php
+++ b/vendor/doctrine/collections/src/Criteria.php
@@ -1,5 +1,7 @@
*/
+ private array $orderings = [];
- /** @var string[] */
- private $orderings = [];
-
- /** @var int|null */
- private $firstResult;
-
- /** @var int|null */
- private $maxResults;
+ private int|null $firstResult = null;
+ private int|null $maxResults = null;
/**
* Creates an instance of the class.
*
- * @return Criteria
+ * @return static
*/
public static function create()
{
@@ -63,12 +60,14 @@ class Criteria
/**
* Construct a new Criteria.
*
- * @param string[]|null $orderings
- * @param int|null $firstResult
- * @param int|null $maxResults
+ * @param array|null $orderings
*/
- public function __construct(?Expression $expression = null, ?array $orderings = null, $firstResult = null, $maxResults = null)
- {
+ public function __construct(
+ private Expression|null $expression = null,
+ array|null $orderings = null,
+ int|null $firstResult = null,
+ int|null $maxResults = null,
+ ) {
$this->expression = $expression;
if ($firstResult === null && func_num_args() > 2) {
@@ -76,7 +75,7 @@ class Criteria
'doctrine/collections',
'https://github.com/doctrine/collections/pull/311',
'Passing null as $firstResult to the constructor of %s is deprecated. Pass 0 instead or omit the argument.',
- self::class
+ self::class,
);
}
@@ -116,7 +115,7 @@ class Criteria
$this->expression = new CompositeExpression(
CompositeExpression::TYPE_AND,
- [$this->expression, $expression]
+ [$this->expression, $expression],
);
return $this;
@@ -136,7 +135,7 @@ class Criteria
$this->expression = new CompositeExpression(
CompositeExpression::TYPE_OR,
- [$this->expression, $expression]
+ [$this->expression, $expression],
);
return $this;
@@ -155,9 +154,32 @@ class Criteria
/**
* Gets the current orderings of this Criteria.
*
- * @return string[]
+ * @deprecated use orderings() instead
+ *
+ * @return array
*/
public function getOrderings()
+ {
+ Deprecation::trigger(
+ 'doctrine/collections',
+ 'https://github.com/doctrine/collections/pull/389',
+ 'Calling %s() is deprecated. Use %s::orderings() instead.',
+ __METHOD__,
+ self::class,
+ );
+
+ return array_map(
+ static fn (Order $ordering): string => $ordering->value,
+ $this->orderings,
+ );
+ }
+
+ /**
+ * Gets the current orderings of this Criteria.
+ *
+ * @return array
+ */
+ public function orderings(): array
{
return $this->orderings;
}
@@ -165,22 +187,40 @@ class Criteria
/**
* Sets the ordering of the result of this Criteria.
*
- * Keys are field and values are the order, being either ASC or DESC.
+ * Keys are field and values are the order, being a valid Order enum case.
*
- * @see Criteria::ASC
- * @see Criteria::DESC
+ * @see Order::Ascending
+ * @see Order::Descending
*
- * @param string[] $orderings
+ * @param array $orderings
*
* @return $this
*/
public function orderBy(array $orderings)
{
+ $method = __METHOD__;
$this->orderings = array_map(
- static function (string $ordering): string {
- return strtoupper($ordering) === Criteria::ASC ? Criteria::ASC : Criteria::DESC;
+ static function (string|Order $ordering) use ($method): Order {
+ if ($ordering instanceof Order) {
+ return $ordering;
+ }
+
+ static $triggered = false;
+
+ if (! $triggered) {
+ Deprecation::trigger(
+ 'doctrine/collections',
+ 'https://github.com/doctrine/collections/pull/389',
+ 'Passing non-Order enum values to %s() is deprecated. Pass Order enum values instead.',
+ $method,
+ );
+ }
+
+ $triggered = true;
+
+ return strtoupper($ordering) === Order::Ascending->value ? Order::Ascending : Order::Descending;
},
- $orderings
+ $orderings,
);
return $this;
@@ -203,14 +243,14 @@ class Criteria
*
* @return $this
*/
- public function setFirstResult($firstResult)
+ public function setFirstResult(int|null $firstResult)
{
if ($firstResult === null) {
Deprecation::triggerIfCalledFromOutside(
'doctrine/collections',
'https://github.com/doctrine/collections/pull/311',
'Passing null to %s() is deprecated, pass 0 instead.',
- __METHOD__
+ __METHOD__,
);
}
@@ -236,7 +276,7 @@ class Criteria
*
* @return $this
*/
- public function setMaxResults($maxResults)
+ public function setMaxResults(int|null $maxResults)
{
$this->maxResults = $maxResults;
diff --git a/vendor/doctrine/collections/src/Expr/ClosureExpressionVisitor.php b/vendor/doctrine/collections/src/Expr/ClosureExpressionVisitor.php
new file mode 100644
index 0000000..5240e30
--- /dev/null
+++ b/vendor/doctrine/collections/src/Expr/ClosureExpressionVisitor.php
@@ -0,0 +1,214 @@
+$accessor();
+ }
+ }
+
+ if (preg_match('/^is[A-Z]+/', $field) === 1 && method_exists($object, $field)) {
+ return $object->$field();
+ }
+
+ // __call should be triggered for get.
+ $accessor = $accessors[0] . $field;
+
+ if (method_exists($object, '__call')) {
+ return $object->$accessor();
+ }
+
+ if ($object instanceof ArrayAccess) {
+ return $object[$field];
+ }
+
+ if (isset($object->$field)) {
+ return $object->$field;
+ }
+
+ // camelcase field name to support different variable naming conventions
+ $ccField = preg_replace_callback('/_(.?)/', static fn ($matches) => strtoupper((string) $matches[1]), $field);
+
+ foreach ($accessors as $accessor) {
+ $accessor .= $ccField;
+
+ if (method_exists($object, $accessor)) {
+ return $object->$accessor();
+ }
+ }
+
+ return $object->$field;
+ }
+
+ /**
+ * Helper for sorting arrays of objects based on multiple fields + orientations.
+ *
+ * @return Closure
+ */
+ public static function sortByField(string $name, int $orientation = 1, Closure|null $next = null)
+ {
+ if (! $next) {
+ $next = static fn (): int => 0;
+ }
+
+ return static function ($a, $b) use ($name, $next, $orientation): int {
+ $aValue = ClosureExpressionVisitor::getObjectFieldValue($a, $name);
+
+ $bValue = ClosureExpressionVisitor::getObjectFieldValue($b, $name);
+
+ if ($aValue === $bValue) {
+ return $next($a, $b);
+ }
+
+ return ($aValue > $bValue ? 1 : -1) * $orientation;
+ };
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function walkComparison(Comparison $comparison)
+ {
+ $field = $comparison->getField();
+ $value = $comparison->getValue()->getValue();
+
+ return match ($comparison->getOperator()) {
+ Comparison::EQ => static fn ($object): bool => self::getObjectFieldValue($object, $field) === $value,
+ Comparison::NEQ => static fn ($object): bool => self::getObjectFieldValue($object, $field) !== $value,
+ Comparison::LT => static fn ($object): bool => self::getObjectFieldValue($object, $field) < $value,
+ Comparison::LTE => static fn ($object): bool => self::getObjectFieldValue($object, $field) <= $value,
+ Comparison::GT => static fn ($object): bool => self::getObjectFieldValue($object, $field) > $value,
+ Comparison::GTE => static fn ($object): bool => self::getObjectFieldValue($object, $field) >= $value,
+ Comparison::IN => static function ($object) use ($field, $value): bool {
+ $fieldValue = ClosureExpressionVisitor::getObjectFieldValue($object, $field);
+
+ return in_array($fieldValue, $value, is_scalar($fieldValue));
+ },
+ Comparison::NIN => static function ($object) use ($field, $value): bool {
+ $fieldValue = ClosureExpressionVisitor::getObjectFieldValue($object, $field);
+
+ return ! in_array($fieldValue, $value, is_scalar($fieldValue));
+ },
+ Comparison::CONTAINS => static fn ($object): bool => str_contains((string) self::getObjectFieldValue($object, $field), (string) $value),
+ Comparison::MEMBER_OF => static function ($object) use ($field, $value): bool {
+ $fieldValues = ClosureExpressionVisitor::getObjectFieldValue($object, $field);
+
+ if (! is_array($fieldValues)) {
+ $fieldValues = iterator_to_array($fieldValues);
+ }
+
+ return in_array($value, $fieldValues, true);
+ },
+ Comparison::STARTS_WITH => static fn ($object): bool => str_starts_with((string) self::getObjectFieldValue($object, $field), (string) $value),
+ Comparison::ENDS_WITH => static fn ($object): bool => str_ends_with((string) self::getObjectFieldValue($object, $field), (string) $value),
+ default => throw new RuntimeException('Unknown comparison operator: ' . $comparison->getOperator()),
+ };
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function walkValue(Value $value)
+ {
+ return $value->getValue();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function walkCompositeExpression(CompositeExpression $expr)
+ {
+ $expressionList = [];
+
+ foreach ($expr->getExpressionList() as $child) {
+ $expressionList[] = $this->dispatch($child);
+ }
+
+ return match ($expr->getType()) {
+ CompositeExpression::TYPE_AND => $this->andExpressions($expressionList),
+ CompositeExpression::TYPE_OR => $this->orExpressions($expressionList),
+ CompositeExpression::TYPE_NOT => $this->notExpression($expressionList),
+ default => throw new RuntimeException('Unknown composite ' . $expr->getType()),
+ };
+ }
+
+ /** @param callable[] $expressions */
+ private function andExpressions(array $expressions): Closure
+ {
+ return static fn ($object): bool => array_all(
+ $expressions,
+ static fn (callable $expression): bool => (bool) $expression($object),
+ );
+ }
+
+ /** @param callable[] $expressions */
+ private function orExpressions(array $expressions): Closure
+ {
+ return static fn ($object): bool => array_any(
+ $expressions,
+ static fn (callable $expression): bool => (bool) $expression($object),
+ );
+ }
+
+ /** @param callable[] $expressions */
+ private function notExpression(array $expressions): Closure
+ {
+ return static fn ($object) => ! $expressions[0]($object);
+ }
+}
diff --git a/vendor/doctrine/collections/src/Expr/Comparison.php b/vendor/doctrine/collections/src/Expr/Comparison.php
new file mode 100644
index 0000000..f1ea07f
--- /dev/null
+++ b/vendor/doctrine/collections/src/Expr/Comparison.php
@@ -0,0 +1,62 @@
+';
+ final public const LT = '<';
+ final public const LTE = '<=';
+ final public const GT = '>';
+ final public const GTE = '>=';
+ final public const IS = '='; // no difference with EQ
+ final public const IN = 'IN';
+ final public const NIN = 'NIN';
+ final public const CONTAINS = 'CONTAINS';
+ final public const MEMBER_OF = 'MEMBER_OF';
+ final public const STARTS_WITH = 'STARTS_WITH';
+ final public const ENDS_WITH = 'ENDS_WITH';
+
+ private readonly Value $value;
+
+ public function __construct(private readonly string $field, private readonly string $op, mixed $value)
+ {
+ if (! ($value instanceof Value)) {
+ $value = new Value($value);
+ }
+
+ $this->value = $value;
+ }
+
+ /** @return string */
+ public function getField()
+ {
+ return $this->field;
+ }
+
+ /** @return Value */
+ public function getValue()
+ {
+ return $this->value;
+ }
+
+ /** @return string */
+ public function getOperator()
+ {
+ return $this->op;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function visit(ExpressionVisitor $visitor)
+ {
+ return $visitor->walkComparison($this);
+ }
+}
diff --git a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/CompositeExpression.php b/vendor/doctrine/collections/src/Expr/CompositeExpression.php
similarity index 66%
rename from vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/CompositeExpression.php
rename to vendor/doctrine/collections/src/Expr/CompositeExpression.php
index 174b21b..b7b4544 100644
--- a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/CompositeExpression.php
+++ b/vendor/doctrine/collections/src/Expr/CompositeExpression.php
@@ -1,33 +1,32 @@
*/
+ private array $expressions = [];
/**
- * @param string $type
- * @param mixed[] $expressions
+ * @param Expression[] $expressions
*
* @throws RuntimeException
*/
- public function __construct($type, array $expressions)
+ public function __construct(private readonly string $type, array $expressions)
{
- $this->type = $type;
-
foreach ($expressions as $expr) {
if ($expr instanceof Value) {
throw new RuntimeException('Values are not supported expressions as children of and/or expressions.');
@@ -39,12 +38,16 @@ class CompositeExpression implements Expression
$this->expressions[] = $expr;
}
+
+ if ($type === self::TYPE_NOT && count($this->expressions) !== 1) {
+ throw new RuntimeException('Not expression only allows one expression as child.');
+ }
}
/**
* Returns the list of expressions nested in this composite.
*
- * @return Expression[]
+ * @return list
*/
public function getExpressionList()
{
diff --git a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/Expression.php b/vendor/doctrine/collections/src/Expr/Expression.php
similarity index 89%
rename from vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/Expression.php
rename to vendor/doctrine/collections/src/Expr/Expression.php
index 566d6d5..70ad45f 100644
--- a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/Expression.php
+++ b/vendor/doctrine/collections/src/Expr/Expression.php
@@ -1,5 +1,7 @@
walkComparison($expr);
-
- case $expr instanceof Value:
- return $this->walkValue($expr);
-
- case $expr instanceof CompositeExpression:
- return $this->walkCompositeExpression($expr);
-
- default:
- throw new RuntimeException('Unknown Expression ' . get_class($expr));
- }
+ return match (true) {
+ $expr instanceof Comparison => $this->walkComparison($expr),
+ $expr instanceof Value => $this->walkValue($expr),
+ $expr instanceof CompositeExpression => $this->walkCompositeExpression($expr),
+ default => throw new RuntimeException('Unknown Expression ' . $expr::class),
+ };
}
}
diff --git a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/Value.php b/vendor/doctrine/collections/src/Expr/Value.php
similarity index 70%
rename from vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/Value.php
rename to vendor/doctrine/collections/src/Expr/Value.php
index 693d345..776770d 100644
--- a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/Value.php
+++ b/vendor/doctrine/collections/src/Expr/Value.php
@@ -1,16 +1,13 @@
value = $value;
}
/** @return mixed */
diff --git a/vendor/doctrine/collections/src/ExpressionBuilder.php b/vendor/doctrine/collections/src/ExpressionBuilder.php
new file mode 100644
index 0000000..7bf5a09
--- /dev/null
+++ b/vendor/doctrine/collections/src/ExpressionBuilder.php
@@ -0,0 +1,128 @@
+
*/
@@ -18,14 +20,14 @@ interface ReadableCollection extends Countable, IteratorAggregate
* This is an O(n) operation, where n is the size of the collection.
*
* @param mixed $element The element to search for.
- * @psalm-param TMaybeContained $element
+ * @phpstan-param TMaybeContained $element
*
* @return bool TRUE if the collection contains the element, FALSE otherwise.
- * @psalm-return (TMaybeContained is T ? bool : false)
+ * @phpstan-return (TMaybeContained is T ? bool : false)
*
* @template TMaybeContained
*/
- public function contains($element);
+ public function contains(mixed $element);
/**
* Checks whether the collection is empty (contains no elements).
@@ -38,30 +40,30 @@ interface ReadableCollection extends Countable, IteratorAggregate
* Checks whether the collection contains an element with the specified key/index.
*
* @param string|int $key The key/index to check for.
- * @psalm-param TKey $key
+ * @phpstan-param TKey $key
*
* @return bool TRUE if the collection contains an element with the specified key/index,
* FALSE otherwise.
*/
- public function containsKey($key);
+ public function containsKey(string|int $key);
/**
* Gets the element at the specified key/index.
*
* @param string|int $key The key/index of the element to retrieve.
- * @psalm-param TKey $key
+ * @phpstan-param TKey $key
*
* @return mixed
- * @psalm-return T|null
+ * @phpstan-return T|null
*/
- public function get($key);
+ public function get(string|int $key);
/**
* Gets all keys/indices of the collection.
*
* @return int[]|string[] The keys/indices of the collection, in the order of the corresponding
* elements in the collection.
- * @psalm-return list
+ * @phpstan-return list
*/
public function getKeys();
@@ -70,7 +72,7 @@ interface ReadableCollection extends Countable, IteratorAggregate
*
* @return mixed[] The values of all elements in the collection, in the
* order they appear in the collection.
- * @psalm-return list
+ * @phpstan-return list
*/
public function getValues();
@@ -78,7 +80,7 @@ interface ReadableCollection extends Countable, IteratorAggregate
* Gets a native PHP array representation of the collection.
*
* @return mixed[]
- * @psalm-return array
+ * @phpstan-return array
*/
public function toArray();
@@ -86,7 +88,7 @@ interface ReadableCollection extends Countable, IteratorAggregate
* Sets the internal iterator to the first element in the collection and returns this element.
*
* @return mixed
- * @psalm-return T|false
+ * @phpstan-return T|false
*/
public function first();
@@ -94,7 +96,7 @@ interface ReadableCollection extends Countable, IteratorAggregate
* Sets the internal iterator to the last element in the collection and returns this element.
*
* @return mixed
- * @psalm-return T|false
+ * @phpstan-return T|false
*/
public function last();
@@ -102,7 +104,7 @@ interface ReadableCollection extends Countable, IteratorAggregate
* Gets the key/index of the element at the current iterator position.
*
* @return int|string|null
- * @psalm-return TKey|null
+ * @phpstan-return TKey|null
*/
public function key();
@@ -110,7 +112,7 @@ interface ReadableCollection extends Countable, IteratorAggregate
* Gets the element of the collection at the current iterator position.
*
* @return mixed
- * @psalm-return T|false
+ * @phpstan-return T|false
*/
public function current();
@@ -118,7 +120,7 @@ interface ReadableCollection extends Countable, IteratorAggregate
* Moves the internal iterator position to the next element and returns this element.
*
* @return mixed
- * @psalm-return T|false
+ * @phpstan-return T|false
*/
public function next();
@@ -133,15 +135,15 @@ interface ReadableCollection extends Countable, IteratorAggregate
* @param int|null $length The maximum number of elements to return, or null for no limit.
*
* @return mixed[]
- * @psalm-return array
+ * @phpstan-return array
*/
- public function slice($offset, $length = null);
+ public function slice(int $offset, int|null $length = null);
/**
* Tests for the existence of an element that satisfies the given predicate.
*
* @param Closure $p The predicate.
- * @psalm-param Closure(TKey, T):bool $p
+ * @phpstan-param Closure(TKey, T):bool $p
*
* @return bool TRUE if the predicate is TRUE for at least one element, FALSE otherwise.
*/
@@ -152,10 +154,10 @@ interface ReadableCollection extends Countable, IteratorAggregate
* The order of the elements is preserved.
*
* @param Closure $p The predicate used for filtering.
- * @psalm-param Closure(T):bool $p
+ * @phpstan-param Closure(T, TKey):bool $p
*
* @return ReadableCollection A collection with the results of the filter operation.
- * @psalm-return ReadableCollection
+ * @phpstan-return ReadableCollection
*/
public function filter(Closure $p);
@@ -163,12 +165,12 @@ interface ReadableCollection extends Countable, IteratorAggregate
* Applies the given function to each element in the collection and returns
* a new collection with the elements returned by the function.
*
- * @psalm-param Closure(T):U $func
+ * @phpstan-param Closure(T):U $func
*
- * @return Collection
- * @psalm-return Collection
+ * @return ReadableCollection
+ * @phpstan-return ReadableCollection
*
- * @psalm-template U
+ * @phpstan-template U
*/
public function map(Closure $func);
@@ -177,12 +179,12 @@ interface ReadableCollection extends Countable, IteratorAggregate
* Keys are preserved in the resulting collections.
*
* @param Closure $p The predicate on which to partition.
- * @psalm-param Closure(TKey, T):bool $p
+ * @phpstan-param Closure(TKey, T):bool $p
*
* @return ReadableCollection[] An array with two elements. The first element contains the collection
* of elements where the predicate returned TRUE, the second element
* contains the collection of elements where the predicate returned FALSE.
- * @psalm-return array{0: ReadableCollection, 1: ReadableCollection}
+ * @phpstan-return array{0: ReadableCollection, 1: ReadableCollection}
*/
public function partition(Closure $p);
@@ -190,7 +192,7 @@ interface ReadableCollection extends Countable, IteratorAggregate
* Tests whether the given predicate p holds for all elements of this collection.
*
* @param Closure $p The predicate.
- * @psalm-param Closure(TKey, T):bool $p
+ * @phpstan-param Closure(TKey, T):bool $p
*
* @return bool TRUE, if the predicate yields TRUE for all elements, FALSE otherwise.
*/
@@ -202,12 +204,39 @@ interface ReadableCollection extends Countable, IteratorAggregate
* For objects this means reference equality.
*
* @param mixed $element The element to search for.
- * @psalm-param TMaybeContained $element
+ * @phpstan-param TMaybeContained $element
*
* @return int|string|bool The key/index of the element or FALSE if the element was not found.
- * @psalm-return (TMaybeContained is T ? TKey|false : false)
+ * @phpstan-return (TMaybeContained is T ? TKey|false : false)
*
* @template TMaybeContained
*/
- public function indexOf($element);
+ public function indexOf(mixed $element);
+
+ /**
+ * Returns the first element of this collection that satisfies the predicate p.
+ *
+ * @param Closure $p The predicate.
+ * @phpstan-param Closure(TKey, T):bool $p
+ *
+ * @return mixed The first element respecting the predicate,
+ * null if no element respects the predicate.
+ * @phpstan-return T|null
+ */
+ public function findFirst(Closure $p);
+
+ /**
+ * Applies iteratively the given function to each element in the collection,
+ * so as to reduce the collection to a single value.
+ *
+ * @phpstan-param Closure(TReturn|TInitial, T):TReturn $func
+ * @phpstan-param TInitial $initial
+ *
+ * @return mixed
+ * @phpstan-return TReturn|TInitial
+ *
+ * @phpstan-template TReturn
+ * @phpstan-template TInitial
+ */
+ public function reduce(Closure $func, mixed $initial = null);
}
diff --git a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Selectable.php b/vendor/doctrine/collections/src/Selectable.php
similarity index 72%
rename from vendor/doctrine/collections/lib/Doctrine/Common/Collections/Selectable.php
rename to vendor/doctrine/collections/src/Selectable.php
index 9f7586d..eb11c93 100644
--- a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Selectable.php
+++ b/vendor/doctrine/collections/src/Selectable.php
@@ -1,5 +1,7 @@
&Selectable
- * @psalm-return Collection&Selectable
+ * @return ReadableCollection&Selectable
+ * @phpstan-return ReadableCollection&Selectable
*/
public function matching(Criteria $criteria);
}
diff --git a/vendor/ipl/html/composer.json b/vendor/ipl/html/composer.json
index 99c5525..7dc6f09 100644
--- a/vendor/ipl/html/composer.json
+++ b/vendor/ipl/html/composer.json
@@ -9,7 +9,7 @@
"sort-packages": true
},
"require": {
- "php": ">=7.2",
+ "php": ">=8.2",
"ext-fileinfo": "*",
"ipl/stdlib": ">=0.12.0",
"ipl/validator": ">=0.5.0",
@@ -17,6 +17,7 @@
"guzzlehttp/psr7": "^2.5"
},
"require-dev": {
+ "ext-dom": "*",
"ipl/stdlib": "dev-main",
"ipl/validator": "dev-main"
},
diff --git a/vendor/ipl/html/src/Attribute.php b/vendor/ipl/html/src/Attribute.php
index c42485a..04405d4 100644
--- a/vendor/ipl/html/src/Attribute.php
+++ b/vendor/ipl/html/src/Attribute.php
@@ -12,6 +12,9 @@ use InvalidArgumentException;
*
* Usually attributes are not instantiated directly, but created through an HTML
* element's exposed methods.
+ *
+ * @phpstan-type _AttributeScalar string|bool|null
+ * @phpstan-type AttributeValue _AttributeScalar|array<_AttributeScalar>
*/
class Attribute
{
@@ -21,14 +24,14 @@ class Attribute
/** @var string The separator used if value is an array */
protected $separator = ' ';
- /** @var string|array|bool|null */
+ /** @var AttributeValue */
protected $value;
/**
* Create a new HTML attribute from the given name and value
*
- * @param string $name The name of the attribute
- * @param string|bool|array|null $value The value of the attribute
+ * @param string $name The name of the attribute
+ * @param AttributeValue $value The value of the attribute
*
* @throws InvalidArgumentException If the name of the attribute contains special characters
*/
@@ -40,8 +43,8 @@ class Attribute
/**
* Create a new HTML attribute from the given name and value
*
- * @param string $name The name of the attribute
- * @param string|bool|array|null $value The value of the attribute
+ * @param string $name The name of the attribute
+ * @param AttributeValue $value The value of the attribute
*
* @return static
*
@@ -68,6 +71,28 @@ class Attribute
return new static($name, null);
}
+ /**
+ * Sanitize the given ID
+ *
+ * Removes all characters that are not alphanumeric, underscore or hyphen. Additionally,
+ * the result is enforced to not start with a number by prepending the letter 'a'.
+ * Use it if you need to ensure that an ID is safe to use in CSS selectors.
+ *
+ * @param non-empty-string $id
+ *
+ * @return string
+ *
+ * @throws InvalidArgumentException If the ID is an empty string
+ */
+ public static function sanitizeId(string $id): string
+ {
+ if (empty($id)) {
+ throw new InvalidArgumentException('ID must not be empty');
+ }
+
+ return 'a' . preg_replace('/[^a-z0-9_\-]/i', '', $id);
+ }
+
/**
* Escape the name of an attribute
*
@@ -91,8 +116,8 @@ class Attribute
* Values are escaped according to the HTML5 double-quoted attribute value syntax:
* {@link https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 }.
*
- * @param string|array $value
- * @param string $glue Glue string to join elements if value is an array
+ * @param string|string[] $value
+ * @param string $glue Glue string to join elements if value is an array
*
* @return string
*/
@@ -184,7 +209,7 @@ class Attribute
/**
* Get the value of the attribute
*
- * @return string|bool|array|null
+ * @return AttributeValue
*/
public function getValue()
{
@@ -194,7 +219,7 @@ class Attribute
/**
* Set the value of the attribute
*
- * @param string|bool|array|null $value
+ * @param AttributeValue $value
*
* @return $this
*/
@@ -208,7 +233,7 @@ class Attribute
/**
* Add the given value(s) to the attribute
*
- * @param string|array $value The value(s) to add
+ * @param AttributeValue $value The value(s) to add
*
* @return $this
*/
@@ -230,7 +255,7 @@ class Attribute
*
* Does nothing if there is no such value to remove.
*
- * @param string|array $value The value(s) to remove
+ * @param AttributeValue $value The value(s) to remove
*
* @return $this
*/
diff --git a/vendor/ipl/html/src/Attributes.php b/vendor/ipl/html/src/Attributes.php
index 8df9bbd..ed7e668 100644
--- a/vendor/ipl/html/src/Attributes.php
+++ b/vendor/ipl/html/src/Attributes.php
@@ -17,6 +17,9 @@ use function ipl\Stdlib\get_php_type;
* behavior in various ways.
*
* Attributes usually come in name-value pairs and are rendered as name="value".
+ *
+ * @phpstan-import-type AttributeValue from Attribute
+ * @phpstan-type AttributesType array
*/
class Attributes implements ArrayAccess, IteratorAggregate
{
@@ -35,7 +38,7 @@ class Attributes implements ArrayAccess, IteratorAggregate
/**
* Create new HTML attributes
*
- * @param array $attributes
+ * @param AttributesType $attributes
*/
public function __construct(array $attributes = null)
{
@@ -57,7 +60,7 @@ class Attributes implements ArrayAccess, IteratorAggregate
/**
* Create new HTML attributes
*
- * @param array $attributes
+ * @param AttributesType $attributes
*
* @return static
*/
@@ -76,7 +79,7 @@ class Attributes implements ArrayAccess, IteratorAggregate
* construct and return a new Attributes instance.
* If the attributes are null, an empty new instance of Attributes is returned.
*
- * @param array|static|null $attributes
+ * @param AttributesType|static|null $attributes
*
* @return static
*
@@ -174,8 +177,8 @@ class Attributes implements ArrayAccess, IteratorAggregate
*
* If the attribute with the given name already exists, it gets overridden.
*
- * @param string|array|Attribute|self $attribute The attribute(s) to add
- * @param string|bool|array $value The value of the attribute
+ * @param string|AttributesType|Attribute|self $attribute The attribute(s) to add
+ * @param AttributeValue $value The value of the attribute
*
* @return $this
*
@@ -224,8 +227,8 @@ class Attributes implements ArrayAccess, IteratorAggregate
* If an attribute with the same name already exists, the attribute's value will be added to the current value of
* the attribute.
*
- * @param string|array|Attribute|self $attribute The attribute(s) to add
- * @param string|bool|array $value The value of the attribute
+ * @param string|AttributesType|Attribute|self $attribute The attribute(s) to add
+ * @param AttributeValue $value The value of the attribute
*
* @return $this
*
@@ -246,6 +249,7 @@ class Attributes implements ArrayAccess, IteratorAggregate
}
if (is_array($attribute)) {
+ // TODO: Handle if $attribute = [new Attribute('class', 'bar')]
foreach ($attribute as $name => $value) {
$this->add($name, $value);
}
@@ -280,7 +284,7 @@ class Attributes implements ArrayAccess, IteratorAggregate
* Remove the attribute with the given name or remove the given value from the attribute
*
* @param string $name The name of the attribute
- * @param null|string|array $value The value to remove if specified
+ * @param AttributeValue $value The value to remove if specified
*
* @return ?Attribute The removed or changed attribute, if any, otherwise null
*/
@@ -479,8 +483,8 @@ class Attributes implements ArrayAccess, IteratorAggregate
*
* If the attribute with the given name already exists, it gets overridden.
*
- * @param string $name Name of the attribute
- * @param mixed $value Value of the attribute
+ * @param string $name Name of the attribute
+ * @param AttributeValue $value Value of the attribute
*
* @throws InvalidArgumentException If the attribute name contains special characters
*/
diff --git a/vendor/ipl/html/src/BaseHtmlElement.php b/vendor/ipl/html/src/BaseHtmlElement.php
index 5dc01ce..0325186 100644
--- a/vendor/ipl/html/src/BaseHtmlElement.php
+++ b/vendor/ipl/html/src/BaseHtmlElement.php
@@ -2,7 +2,7 @@
namespace ipl\Html;
-use InvalidArgumentException;
+use ipl\Html\Contract\HtmlElementInterface;
use RuntimeException;
/**
@@ -32,7 +32,7 @@ use RuntimeException;
* }
* ```
*/
-abstract class BaseHtmlElement extends HtmlDocument
+abstract class BaseHtmlElement extends HtmlDocument implements HtmlElementInterface
{
/**
* List of void elements which must not contain end tags or content
@@ -76,11 +76,6 @@ abstract class BaseHtmlElement extends HtmlDocument
/** @var string Tag of element. Set this property in order to provide the element's tag when extending this class */
protected $tag;
- /**
- * Get the attributes of the element
- *
- * @return Attributes
- */
public function getAttributes()
{
if ($this->attributes === null) {
@@ -97,6 +92,13 @@ abstract class BaseHtmlElement extends HtmlDocument
return $this->attributes;
}
+ public function addAttributes($attributes)
+ {
+ $this->getAttributes()->add($attributes);
+
+ return $this;
+ }
+
/**
* Set the attributes of the element
*
@@ -114,44 +116,16 @@ abstract class BaseHtmlElement extends HtmlDocument
return $this;
}
- /**
- * Return true if the attribute with the given name exists, false otherwise
- *
- * @param string $name
- *
- * @return bool
- */
public function hasAttribute(string $name): bool
{
return $this->getAttributes()->has($name);
}
- /**
- * Get the attribute with the given name
- *
- * If the attribute does not already exist, an empty one is automatically created and added to the attributes.
- *
- * @param string $name
- *
- * @return Attribute
- *
- * @throws InvalidArgumentException If the attribute does not yet exist and its name contains special characters
- */
public function getAttribute(string $name): Attribute
{
return $this->getAttributes()->get($name);
}
- /**
- * Set the attribute with the given name and value
- *
- * If the attribute with the given name already exists, it gets overridden.
- *
- * @param string $name The name of the attribute
- * @param string|bool|array $value The value of the attribute
- *
- * @return $this
- */
public function setAttribute($name, $value)
{
$this->getAttributes()->set($name, $value);
@@ -159,33 +133,11 @@ abstract class BaseHtmlElement extends HtmlDocument
return $this;
}
- /**
- * Remove the attribute with the given name or remove the given value from the attribute
- *
- * @param string $name The name of the attribute
- * @param null|string|array $value The value to remove if specified
- *
- * @return ?Attribute The removed or changed attribute, if any, otherwise null
- */
public function removeAttribute(string $name, $value = null): ?Attribute
{
return $this->getAttributes()->remove($name, $value);
}
- /**
- * Add the given attributes
- *
- * @param Attributes|array $attributes
- *
- * @return $this
- */
- public function addAttributes($attributes)
- {
- $this->getAttributes()->add($attributes);
-
- return $this;
- }
-
/**
* Get the default attributes of the element
*
diff --git a/vendor/ipl/html/src/Contract/DecorableFormElement.php b/vendor/ipl/html/src/Contract/DecorableFormElement.php
new file mode 100644
index 0000000..18e688f
--- /dev/null
+++ b/vendor/ipl/html/src/Contract/DecorableFormElement.php
@@ -0,0 +1,32 @@
+
+ */
+ public function getDecorators(): DecoratorChain;
+
+ /**
+ * Get whether the element has any decorators
+ *
+ * @return bool
+ */
+ public function hasDecorators(): bool;
+
+ /**
+ * Decorate the element using its decorators
+ *
+ * @return void
+ */
+ public function applyDecoration(): void;
+}
diff --git a/vendor/ipl/html/src/Contract/DecorationResult.php b/vendor/ipl/html/src/Contract/DecorationResult.php
new file mode 100644
index 0000000..9cc71f5
--- /dev/null
+++ b/vendor/ipl/html/src/Contract/DecorationResult.php
@@ -0,0 +1,35 @@
+attributes === null) {
+ $this->attributes = new Attributes();
+ $this->registerAttributeCallbacks($this->attributes);
+ }
+
+ return $this->attributes;
+ }
+
+ /**
+ * Register attribute callbacks
+ *
+ * Override this method in order to register attribute callbacks in concrete classes.
+ *
+ * @param Attributes $attributes
+ */
+ abstract protected function registerAttributeCallbacks(Attributes $attributes): void;
+}
diff --git a/vendor/ipl/html/src/Contract/DecoratorOptionsInterface.php b/vendor/ipl/html/src/Contract/DecoratorOptionsInterface.php
new file mode 100644
index 0000000..55279da
--- /dev/null
+++ b/vendor/ipl/html/src/Contract/DecoratorOptionsInterface.php
@@ -0,0 +1,18 @@
+
+ */
+interface DefaultFormElementDecoration
+{
+ /**
+ * Set the default element decorators.
+ *
+ * The default decorators will be applied to all elements that do not have explicit decorators.
+ * The order of the decorators is important, as it determines the rendering order.
+ *
+ * Please see {@see DecoratorChain::addDecorators()} for the supported array formats.
+ *
+ * @param decoratorsFormat $decorators
+ *
+ * @return $this
+ */
+ public function setDefaultElementDecorators(array $decorators): static;
+
+ /**
+ * Add custom element decorator loader paths for the elements
+ *
+ * Each entry must be an array with index 0: class namespace, index 1: class name suffix (optional).
+ *
+ * @param loaderPaths $loaderPaths
+ *
+ * @return $this
+ */
+ public function addElementDecoratorLoaderPaths(array $loaderPaths): static;
+}
diff --git a/vendor/ipl/html/src/Contract/Form.php b/vendor/ipl/html/src/Contract/Form.php
new file mode 100644
index 0000000..1ababcd
--- /dev/null
+++ b/vendor/ipl/html/src/Contract/Form.php
@@ -0,0 +1,87 @@
+hasChanges()) {
+ * return;
+ * }
+ *
+ * $result->prepend(new HtmlElement('p', null, Text::create('You have unsaved changes.')));
+ * }
+ * ```
+ *
+ * @param DecorationResult $result
+ * @param Form $form
+ *
+ * @return void
+ */
+ public function decorateForm(DecorationResult $result, Form $form): void;
+}
diff --git a/vendor/ipl/html/src/Contract/FormElement.php b/vendor/ipl/html/src/Contract/FormElement.php
index 1467c50..da8adbd 100644
--- a/vendor/ipl/html/src/Contract/FormElement.php
+++ b/vendor/ipl/html/src/Contract/FormElement.php
@@ -7,6 +7,8 @@ use ipl\Html\Form;
/**
* Representation of form elements
+ *
+ * @phpstan-import-type AttributesType from Attributes
*/
interface FormElement extends Wrappable
{
@@ -20,7 +22,7 @@ interface FormElement extends Wrappable
/**
* Add attributes or options to the form element
*
- * @param iterable $attributes
+ * @param Attributes|AttributesType $attributes
*
* @return $this
*/
diff --git a/vendor/ipl/html/src/Contract/FormElementDecoration.php b/vendor/ipl/html/src/Contract/FormElementDecoration.php
new file mode 100644
index 0000000..1f92913
--- /dev/null
+++ b/vendor/ipl/html/src/Contract/FormElementDecoration.php
@@ -0,0 +1,43 @@
+getDescription();
+ *
+ * if ($description === null) {
+ * return;
+ * }
+ *
+ * $result->append(new HtmlElement('p', null, new Text($description)));
+ * }
+ * ```
+ *
+ * @param DecorationResult $result
+ * @param FormElement $formElement
+ *
+ * @return void
+ */
+ public function decorateFormElement(DecorationResult $result, FormElement $formElement): void;
+}
diff --git a/vendor/ipl/html/src/Contract/FormElementDecorator.php b/vendor/ipl/html/src/Contract/FormElementDecorator.php
index ca770ea..8e0b6b7 100644
--- a/vendor/ipl/html/src/Contract/FormElementDecorator.php
+++ b/vendor/ipl/html/src/Contract/FormElementDecorator.php
@@ -6,6 +6,8 @@ use ipl\Html\ValidHtml;
/**
* Representation of form element decorators
+ *
+ * @deprecated Use {@see FormElementDecoration} instead
*/
interface FormElementDecorator extends ValidHtml
{
diff --git a/vendor/ipl/html/src/Contract/FormElements.php b/vendor/ipl/html/src/Contract/FormElements.php
new file mode 100644
index 0000000..224a404
--- /dev/null
+++ b/vendor/ipl/html/src/Contract/FormElements.php
@@ -0,0 +1,103 @@
+ $options Element options as key-value pairs
+ *
+ * @return $this
+ *
+ * @throws InvalidArgumentException If the element is invalid (e.g., wrong type, no name)
+ */
+ public function addElement(string|FormElement $typeOrElement, ?string $name = null, ?array $options = null);
+
+ /**
+ * Register an element
+ *
+ * Registers the element for value and validation handling but does not add it to the render stack.
+ * Emits event {@see self::ON_ELEMENT_REGISTERED} with the element as parameter.
+ *
+ * @param FormElement $element
+ *
+ * @return $this
+ *
+ * @throws InvalidArgumentException If $element does not provide a name
+ */
+ public function registerElement(FormElement $element);
+
+ /**
+ * Remove an element
+ *
+ * @param string|FormElement $element
+ *
+ * @return $this
+ */
+ public function removeElement(string|FormElement $element);
+
+ /**
+ * Get the value of the element specified by name
+ *
+ * Returns $default if the element does not exist or has no value.
+ *
+ * @param string $name
+ * @param mixed $default
+ *
+ * @return mixed
+ */
+ public function getValue(string $name, mixed $default = null);
+
+ /**
+ * Get the values for all but ignored elements
+ *
+ * @return array Values as name-value pairs
+ */
+ public function getValues();
+
+ /**
+ * Populate values of registered elements
+ *
+ * @param iterable $values Values as name-value pairs
+ *
+ * @return $this
+ */
+ public function populate(iterable $values);
+}
diff --git a/vendor/ipl/html/src/Contract/HtmlElementInterface.php b/vendor/ipl/html/src/Contract/HtmlElementInterface.php
new file mode 100644
index 0000000..b3e4d00
--- /dev/null
+++ b/vendor/ipl/html/src/Contract/HtmlElementInterface.php
@@ -0,0 +1,90 @@
+ */
+ protected ?DecoratorChain $decorators = null;
+
+ /** @var bool Whether the form has been decorated */
+ protected bool $decorated = false;
+
protected $tag = 'form';
/**
@@ -59,10 +67,39 @@ class Form extends BaseHtmlElement
}
/**
- * Get the Form submission URL
+ * Escape reserved chars in the given string
*
- * @return string|null
+ * The characters '.', ' ' and optionally brackets are converted to unused control characters
+ * File Separator: ␜, Group Separator: ␝, Record Separator: ␝, and Unit Separator: ␟ respectively.
+ *
+ * This is done because:
+ * PHP converts dots and spaces in form element names to underscores by default in the request data.
+ * For example, becomes $_REQUEST["a_b"].
+ *
+ * And if an external variable name begins with a valid array syntax, trailing characters are silently ignored.
+ * For example, becomes $_REQUEST['foo']['bar'].
+ * See https://www.php.net/manual/en/language.variables.external.php
+ *
+ * @param string $string The string to escape
+ * @param bool $escapeBrackets Whether to escape brackets
+ *
+ * @return string
*/
+ public static function escapeReservedChars(string $string, bool $escapeBrackets = true): string
+ {
+ $escapeMap = [
+ '.' => chr(28), // File Separator
+ ' ' => chr(29) // Group Separator
+ ];
+
+ if ($escapeBrackets) {
+ $escapeMap['['] = chr(30); // Record Separator
+ $escapeMap[']'] = chr(31); // Unit Separator
+ }
+
+ return strtr($string, $escapeMap);
+ }
+
public function getAction()
{
return $this->action;
@@ -82,11 +119,6 @@ class Form extends BaseHtmlElement
return $this;
}
- /**
- * Get the HTTP method to submit the form with
- *
- * @return string
- */
public function getMethod()
{
return $this->method;
@@ -156,9 +188,6 @@ class Form extends BaseHtmlElement
return null;
}
- /**
- * @return ServerRequestInterface|null
- */
public function getRequest()
{
return $this->request;
@@ -167,7 +196,6 @@ class Form extends BaseHtmlElement
public function setRequest($request)
{
$this->request = $request;
- $this->emit(Form::ON_REQUEST, [$request]);
return $this;
}
@@ -197,15 +225,26 @@ class Form extends BaseHtmlElement
}
/**
- * @param ServerRequestInterface $request
+ * Get the decorators of this form
*
- * @return $this
+ * @return DecoratorChain
*/
+ public function getDecorators(): DecoratorChain
+ {
+ if ($this->decorators === null) {
+ $this->decorators = new DecoratorChain(FormDecoration::class);
+ }
+
+ return $this->decorators;
+ }
+
public function handleRequest(ServerRequestInterface $request)
{
$this->setRequest($request);
if (! $this->hasBeenSent()) {
+ $this->emit(Contract\Form::ON_REQUEST, [$request, $this]);
+
// Always assemble
$this->ensureAssembled();
@@ -234,32 +273,25 @@ class Form extends BaseHtmlElement
if ($this->hasBeenSubmitted()) {
if ($this->isValid()) {
try {
- $this->emit(Form::ON_SENT, [$this]);
+ $this->emit(Contract\Form::ON_SENT, [$this]);
$this->onSuccess();
- $this->emitOnce(Form::ON_SUCCESS, [$this]);
+ $this->emitOnce(Contract\Form::ON_SUBMIT, [$this]);
} catch (Throwable $e) {
$this->addMessage($e);
$this->onError();
- $this->emit(Form::ON_ERROR, [$e, $this]);
+ $this->emit(Contract\Form::ON_ERROR, [$e, $this]);
}
} else {
$this->onError();
}
} else {
$this->validatePartial();
- $this->emit(Form::ON_SENT, [$this]);
+ $this->emit(Contract\Form::ON_SENT, [$this]);
}
return $this;
}
- /**
- * Get whether the form has been sent
- *
- * A form is considered sent if the request's method equals the form's method.
- *
- * @return bool
- */
public function hasBeenSent()
{
if ($this->request === null) {
@@ -269,14 +301,6 @@ class Form extends BaseHtmlElement
return $this->request->getMethod() === $this->getMethod();
}
- /**
- * Get whether the form has been submitted
- *
- * A form is submitted when it has been sent and when the primary submit button, if set, has been pressed.
- * This method calls {@link hasBeenSent()} in order to detect whether the form has been sent.
- *
- * @return bool
- */
public function hasBeenSubmitted()
{
if (! $this->hasBeenSent()) {
@@ -290,19 +314,12 @@ class Form extends BaseHtmlElement
return true;
}
- /**
- * Get whether the form is valid
- *
- * {@link validate()} is called automatically if the form has not been validated before.
- *
- * @return bool
- */
public function isValid()
{
if ($this->isValid === null) {
$this->validate();
- $this->emit(self::ON_VALIDATE, [$this]);
+ $this->emit(Contract\Form::ON_VALIDATE, [$this]);
}
return $this->isValid;
@@ -348,17 +365,36 @@ class Form extends BaseHtmlElement
return $this;
}
- public function remove(ValidHtml $elementOrHtml)
+ public function remove(ValidHtml $content)
{
- if ($this->submitButton === $elementOrHtml) {
+ if ($this->submitButton === $content) {
$this->submitButton = null;
}
- $this->removeElement($elementOrHtml);
+ $this->baseRemove($content);
return $this;
}
+ /**
+ * Apply the form decoration
+ *
+ * @return void
+ */
+ protected function applyDecoration(): void
+ {
+ if ($this->decorated) {
+ return;
+ }
+
+ $result = new FormDecorationResult($this);
+ foreach ($this->getDecorators() as $decorator) {
+ $decorator->decorateForm($result, $this);
+ }
+
+ $this->decorated = true;
+ }
+
protected function onError()
{
$errors = Html::tag('ul', ['class' => 'errors']);
@@ -399,4 +435,11 @@ class Form extends BaseHtmlElement
->registerAttributeCallback('action', [$this, 'getAction'], [$this, 'setAction'])
->registerAttributeCallback('method', [$this, 'getMethod'], [$this, 'setMethod']);
}
+
+ protected function beforeRender(): void
+ {
+ $this->baseBeforeRender();
+
+ $this->applyDecoration();
+ }
}
diff --git a/vendor/ipl/html/src/FormDecoration/DecoratorChain.php b/vendor/ipl/html/src/FormDecoration/DecoratorChain.php
new file mode 100644
index 0000000..f2b2a1d
--- /dev/null
+++ b/vendor/ipl/html/src/FormDecoration/DecoratorChain.php
@@ -0,0 +1,280 @@
+
+ *
+ * @phpstan-type decoratorOptionsFormat array
+ * @phpstan-type _decoratorsFormat1 array
+ * @phpstan-type _decoratorsFormat2 array
+ * @phpstan-type decoratorsFormat _decoratorsFormat1 | _decoratorsFormat2
+ */
+class DecoratorChain implements IteratorAggregate
+{
+ use Plugins;
+
+ /** @var class-string The type of decorator to accept */
+ private string $decoratorType;
+
+ /** @var TDecorator[] All registered decorators */
+ private array $decorators = [];
+
+ /**
+ * Create a new decorator chain
+ *
+ * @param class-string $decoratorType The type of decorator to accept
+ */
+ public function __construct(string $decoratorType)
+ {
+ $this->decoratorType = $decoratorType;
+
+ $this->addDefaultPluginLoader('decorator', __NAMESPACE__, 'Decorator');
+ }
+
+ /**
+ * Add a decorator loader
+ *
+ * @param string $namespace Namespace of the decorator(s)
+ * @param string $suffix Decorator class name suffix, if any
+ *
+ * @return $this
+ */
+ public function addDecoratorLoader(string $namespace, string $suffix = ''): static
+ {
+ $this->addPluginLoader('decorator', $namespace, $suffix);
+
+ return $this;
+ }
+
+ /**
+ * Add a decorator to the chain.
+ *
+ * @param TDecorator|string $decorator
+ * @param decoratorOptionsFormat $options Only allowed if parameter 1 is a string
+ *
+ * @return $this
+ *
+ * @throws InvalidArgumentException If the decorator specification is invalid
+ */
+ public function addDecorator(object|string $decorator, array $options = []): static
+ {
+ if (! empty($options) && ! is_string($decorator)) {
+ throw new InvalidArgumentException('No options are allowed with parameter 1 of type Decorator');
+ }
+
+ if (is_string($decorator)) {
+ $decorator = $this->createDecorator($decorator, $options);
+ } elseif (! $decorator instanceof $this->decoratorType) {
+ throw new InvalidArgumentException(sprintf(
+ 'Expects parameter 1 to be a string or an instance of %s, got %s instead',
+ $this->decoratorType,
+ get_php_type($decorator)
+ ));
+ }
+
+ $this->decorators[] = $decorator;
+
+ return $this;
+ }
+
+ /**
+ * Add the decorators from the given decorator specification to the chain
+ *
+ * The order of the decorators is important, as it determines the rendering order.
+ *
+ * *The following array formats are supported:*
+ *
+ * ```
+ * // When no options are required or defaults are sufficient
+ * $decorators = [
+ * 'HtmlTag',
+ * 'Label'
+ * ];
+ *
+ * // Override default options by defining the option key and value
+ *
+ * // key: decorator name, value: options
+ * $decorators = [
+ * 'HtmlTag' => ['tag' => 'span', 'placement' => 'append'],
+ * 'Label' => ['class' => 'element-label']
+ * ];
+ *
+ * // or define the `name` and `options` key
+ * $decorators = [
+ * ['name' => 'HtmlTag', 'options' => ['tag' => 'span', 'placement' => 'append']],
+ * ['name' => 'Label', 'options' => ['class' => 'element-label']]
+ * ];
+ *
+ * // or add Decorator instances
+ * $decorators = [
+ * (new HtmlTagDecorator())->getAttributes()->add(['tag' => 'span', 'placement' => 'append']),
+ * (new LabelDecorator())->getAttributes()->add(['class' => 'element-label'])
+ * ];
+ * ```
+ *
+ * @param static|decoratorsFormat $decorators
+ *
+ * @return $this
+ *
+ * @throws InvalidArgumentException If the decorator specification is invalid
+ */
+ public function addDecorators(DecoratorChain|array $decorators): static
+ {
+ if ($decorators instanceof static) {
+ foreach ($decorators->decorators as $decorator) {
+ $this->addDecorator($decorator);
+ }
+
+ return $this;
+ }
+
+ foreach ($decorators as $decoratorName => $decoratorOptions) {
+ $position = $decoratorName;
+ if (is_int($decoratorName)) {
+ if (is_array($decoratorOptions)) {
+ if (! isset($decoratorOptions['name'])) {
+ throw new InvalidArgumentException("Key 'name' is missing");
+ }
+
+ $decoratorName = $decoratorOptions['name'];
+ unset($decoratorOptions['name']);
+
+ $options = [];
+ if (isset($decoratorOptions['options'])) {
+ $options = $decoratorOptions['options'];
+
+ unset($decoratorOptions['options']);
+ }
+
+ if (! empty($decoratorOptions)) {
+ throw new InvalidArgumentException(
+ sprintf(
+ "No other keys except 'name' and 'options' are allowed, got '%s'",
+ implode("', '", array_keys($decoratorOptions))
+ )
+ );
+ }
+
+ $decoratorOptions = $options;
+ } else {
+ $decoratorName = $decoratorOptions;
+ $decoratorOptions = [];
+ }
+ }
+
+ if (! is_array($decoratorOptions)) {
+ throw new InvalidArgumentException(sprintf(
+ "The key must be a decorator name and value must be an array of options, got value of type"
+ . " '%s' for key '%s'",
+ get_php_type($decoratorOptions),
+ $decoratorName,
+ ));
+ }
+
+ if (! is_string($decoratorName) && ! $decoratorName instanceof $this->decoratorType) {
+ throw new InvalidArgumentException(sprintf(
+ 'Expects array value at position %d to be a string or an instance of %s, got %s instead',
+ $position,
+ $this->decoratorType,
+ get_php_type($decoratorName)
+ ));
+ }
+
+ $this->addDecorator($decoratorName, $decoratorOptions);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Clear all decorators from the chain
+ *
+ * @return $this
+ */
+ public function clearDecorators(): static
+ {
+ $this->decorators = [];
+
+ return $this;
+ }
+
+ /**
+ * Create a decorator from the given name and options
+ *
+ * @param string $name
+ * @param decoratorOptionsFormat $options
+ *
+ * @return TDecorator
+ *
+ * @throws InvalidArgumentException If the given decorator is unknown
+ */
+ protected function createDecorator(string $name, array $options = []): object
+ {
+ $class = $this->loadPlugin('decorator', $name);
+
+ if (! $class) {
+ throw new InvalidArgumentException(sprintf(
+ "Can't load decorator '%s'. decorator unknown",
+ $name
+ ));
+ }
+
+ $decorator = new $class();
+
+ if (! $decorator instanceof $this->decoratorType) {
+ throw new UnexpectedValueException(sprintf(
+ "%s expects loader to return an instance of %s for decorator '%s', got %s instead",
+ __METHOD__,
+ $this->decoratorType,
+ $name,
+ get_php_type($decorator)
+ ));
+ }
+
+ if (! empty($options)) {
+ if (! $decorator instanceof DecoratorOptionsInterface) {
+ throw new InvalidArgumentException(sprintf("Decorator '%s' does not support options", $name));
+ }
+
+ $decorator->getAttributes()->add($options);
+ }
+
+ return $decorator;
+ }
+
+ /**
+ * Get whether the chain has decorators
+ *
+ * @return bool
+ */
+ public function hasDecorators(): bool
+ {
+ return ! empty($this->decorators);
+ }
+
+ /**
+ * Iterate over all decorators
+ *
+ * @return Generator
+ */
+ #[\Override]
+ public function getIterator(): Generator
+ {
+ foreach ($this->decorators as $decorator) {
+ yield $decorator;
+ }
+ }
+}
diff --git a/vendor/ipl/html/src/FormDecoration/DescriptionDecorator.php b/vendor/ipl/html/src/FormDecoration/DescriptionDecorator.php
new file mode 100644
index 0000000..ed134f9
--- /dev/null
+++ b/vendor/ipl/html/src/FormDecoration/DescriptionDecorator.php
@@ -0,0 +1,100 @@
+class;
+ }
+
+ /**
+ * Set the css class(es)
+ *
+ * @param string|string[] $class
+ *
+ * @return $this
+ */
+ public function setClass(string|array $class): static
+ {
+ $this->class = $class;
+
+ return $this;
+ }
+
+ public function decorateFormElement(DecorationResult $result, FormElement $formElement): void
+ {
+ $isHtmlElement = $formElement instanceof HtmlElementInterface;
+
+ if ($formElement->getDescription() === null || ($isHtmlElement && $formElement->getTag() === 'fieldset')) {
+ return;
+ }
+
+ $elementDescription = $this->getElementDescription($formElement);
+ if ($isHtmlElement) {
+ if ($formElement->getAttributes()->has('id')) {
+ $elementId = $formElement->getAttributes()->get('id')->getValue();
+ } else {
+ $elementId = uniqid('form-element-');
+
+ // RadioElement applies all its attributes to each of its options, so we cannot set a fallback
+ // id attribute here.
+ if (! $formElement instanceof RadioElement) {
+ $formElement->getAttributes()->set('id', $elementId);
+ }
+ }
+
+ $descriptionId = 'desc_' . $elementId;
+ $formElement->getAttributes()->set('aria-describedby', $descriptionId);
+
+ $elementDescription->getAttributes()->set('id', $descriptionId);
+ }
+
+ $elementDescription->getAttributes()->add('class', $this->getClass());
+
+ $result->append($elementDescription);
+ }
+
+ /**
+ * Get the element description as HTML
+ *
+ * @param FormElement $formElement
+ *
+ * @return HtmlElementInterface & ValidHtml
+ */
+ protected function getElementDescription(FormElement $formElement): HtmlElementInterface & ValidHtml
+ {
+ return new HtmlElement('p', content: new Text($formElement->getDescription()));
+ }
+
+ protected function registerAttributeCallbacks(Attributes $attributes): void
+ {
+ $attributes->registerAttributeCallback('class', null, $this->setClass(...));
+ }
+}
diff --git a/vendor/ipl/html/src/FormDecoration/ErrorsDecorator.php b/vendor/ipl/html/src/FormDecoration/ErrorsDecorator.php
new file mode 100644
index 0000000..76769bc
--- /dev/null
+++ b/vendor/ipl/html/src/FormDecoration/ErrorsDecorator.php
@@ -0,0 +1,64 @@
+class;
+ }
+
+ /**
+ * Set the css class(es)
+ *
+ * @param string|string[] $class
+ *
+ * @return $this
+ */
+ public function setClass(string|array $class): static
+ {
+ $this->class = $class;
+
+ return $this;
+ }
+
+ public function decorateFormElement(DecorationResult $result, FormElement $formElement): void
+ {
+ $errors = new HtmlElement('ul', new Attributes(['class' => $this->getClass()]));
+ foreach ($formElement->getMessages() as $message) {
+ $errors->addHtml(new HtmlElement('li', null, Text::create($message)));
+ }
+
+ if (! $errors->isEmpty()) {
+ $result->append($errors);
+ }
+ }
+
+ protected function registerAttributeCallbacks(Attributes $attributes): void
+ {
+ $attributes->registerAttributeCallback('class', null, $this->setClass(...));
+ }
+}
diff --git a/vendor/ipl/html/src/FormDecoration/FieldsetDecorator.php b/vendor/ipl/html/src/FormDecoration/FieldsetDecorator.php
new file mode 100644
index 0000000..701cdc3
--- /dev/null
+++ b/vendor/ipl/html/src/FormDecoration/FieldsetDecorator.php
@@ -0,0 +1,43 @@
+getTag() !== 'fieldset') {
+ return;
+ }
+
+ $description = $formElement->getDescription();
+ if ($description !== null) {
+ $attributes = null;
+ if ($formElement->getAttributes()->has('id')) {
+ $descriptionId = 'desc_' . $formElement->getAttributes()->get('id')->getValue();
+ $formElement->getAttributes()->set('aria-describedby', $descriptionId);
+ $attributes = new Attributes(['id' => $descriptionId]);
+ }
+
+ $formElement->prependHtml(new HtmlElement('p', $attributes, new Text($description)));
+ }
+
+ $label = $formElement->getLabel();
+ if ($label !== null) {
+ $formElement->prependHtml(new HtmlElement('legend', null, Text::create($label)));
+ }
+ }
+}
diff --git a/vendor/ipl/html/src/FormDecoration/FormDecorationResult.php b/vendor/ipl/html/src/FormDecoration/FormDecorationResult.php
new file mode 100644
index 0000000..27d6a8d
--- /dev/null
+++ b/vendor/ipl/html/src/FormDecoration/FormDecorationResult.php
@@ -0,0 +1,54 @@
+content = $form;
+ }
+
+ public function append(ValidHtml $html): static
+ {
+ $this->content->addHtml($html);
+
+ return $this;
+ }
+
+ public function prepend(ValidHtml $html): static
+ {
+ $this->content->prependHtml($html);
+
+ return $this;
+ }
+
+ public function wrap(MutableHtml $html): static
+ {
+ if (! $html instanceof Wrappable) {
+ // If it's not a wrappable, mimic what wrapping usually means
+ $html = (new HtmlDocument())->addHtml($html);
+ }
+
+ $this->content->addWrapper($html);
+ $html->addHtml($this->content);
+ $this->content = $html;
+
+ return $this;
+ }
+}
diff --git a/vendor/ipl/html/src/FormDecoration/FormElementDecorationResult.php b/vendor/ipl/html/src/FormDecoration/FormElementDecorationResult.php
new file mode 100644
index 0000000..3dcdc91
--- /dev/null
+++ b/vendor/ipl/html/src/FormDecoration/FormElementDecorationResult.php
@@ -0,0 +1,96 @@
+>
+ */
+class FormElementDecorationResult implements DecorationResult
+{
+ /** @var content The HTML content */
+ protected array $content = [];
+
+ public function append(ValidHtml $html): static
+ {
+ $this->content[] = $html;
+
+ return $this;
+ }
+
+ public function prepend(ValidHtml $html): static
+ {
+ array_unshift($this->content, $html);
+
+ return $this;
+ }
+
+ public function wrap(MutableHtml $html): static
+ {
+ $this->content = [[$html, $this->content]];
+
+ return $this;
+ }
+
+ /**
+ * Assemble the results
+ *
+ * @return HtmlDocument
+ */
+ public function assemble(): HtmlDocument
+ {
+ $content = new HtmlDocument();
+
+ if (empty($this->content)) {
+ return $content;
+ }
+
+ $this->resolveContent($content, $this->content);
+
+ return $content;
+ }
+
+ /**
+ * Resolve content
+ *
+ * @param MutableHtml $parent The parent element
+ * @param content $content The content to be added
+ *
+ * @return void
+ */
+ protected function resolveContent(MutableHtml $parent, array $content): void
+ {
+ foreach ($content as $item) {
+ if (is_array($item)) {
+ $item = $this->resolveWrappedContent($item[0], $item[1]);
+ }
+
+ $parent->addHtml($item);
+ }
+ }
+
+ /**
+ * Resolve wrapped content
+ *
+ * @param MutableHtml $parent The parent element
+ * @param ValidHtml|content $item The content to be added
+ *
+ * @return ValidHtml The resolved parent element with content added
+ */
+ protected function resolveWrappedContent(MutableHtml $parent, ValidHtml|array $item): ValidHtml
+ {
+ if ($item instanceof ValidHtml) {
+ $parent->addHtml($item);
+ } else {
+ $this->resolveContent($parent, $item);
+ }
+
+ return $parent;
+ }
+}
diff --git a/vendor/ipl/html/src/FormDecoration/HtmlTagDecorator.php b/vendor/ipl/html/src/FormDecoration/HtmlTagDecorator.php
new file mode 100644
index 0000000..a1b8bb0
--- /dev/null
+++ b/vendor/ipl/html/src/FormDecoration/HtmlTagDecorator.php
@@ -0,0 +1,184 @@
+tag)) {
+ throw new RuntimeException('Option "tag" must be set');
+ }
+
+ return $this->tag;
+ }
+
+ /**
+ * Set the HTML tag to use for the decoration
+ *
+ * @param string $tag
+ *
+ * @return $this
+ */
+ public function setTag(string $tag): static
+ {
+ $this->tag = $tag;
+
+ return $this;
+ }
+
+ /**
+ * Set the transformation type of the HTML tag
+ *
+ * @param Transformation $transformation
+ *
+ * @return $this
+ */
+ public function setTransformation(Transformation $transformation): static
+ {
+ $this->transformation = $transformation;
+
+ return $this;
+ }
+
+ /**
+ * Get the transformation type of the HTML tag
+ *
+ * @return Transformation
+ */
+ public function getTransformation(): Transformation
+ {
+ return $this->transformation;
+ }
+
+ /**
+ * Get the condition callable to decide whether to decorate the element
+ *
+ * @return ?callable(FormElement): bool
+ */
+ public function getCondition(): ?callable
+ {
+ return $this->condition;
+ }
+
+ /**
+ * Set the condition callable to decide whether to decorate the element
+ *
+ * @param callable(FormElement): bool $condition
+ *
+ * @return $this
+ */
+ public function setCondition(callable $condition): static
+ {
+ $this->condition = $condition;
+
+ return $this;
+ }
+
+ /**
+ * Get the css class(es)
+ *
+ * @return ?(string|string[])
+ */
+ public function getClass(): string|array|null
+ {
+ return $this->class;
+ }
+
+ /**
+ * Set the css class(es)
+ *
+ * @param string|string[] $class
+ *
+ * @return $this
+ */
+ public function setClass(string|array $class): static
+ {
+ $this->class = $class;
+
+ return $this;
+ }
+
+ /**
+ * @throws InvalidArgumentException if the condition callback does not return a boolean
+ * @throws RuntimeException if the condition callback throws an exception
+ */
+ public function decorateFormElement(DecorationResult $result, FormElement $formElement): void
+ {
+ $condition = $this->getCondition();
+ if ($condition !== null) {
+ try {
+ $shouldDecorate = $condition($formElement);
+ } catch (Throwable $e) {
+ throw new RuntimeException('Condition callback failed', previous: $e);
+ }
+
+ if (! is_bool($shouldDecorate)) {
+ throw new InvalidArgumentException(sprintf(
+ 'Condition callback must return a boolean, got %s',
+ get_php_type($shouldDecorate)
+ ));
+ }
+
+ if (! $shouldDecorate) {
+ return;
+ }
+ }
+
+ $class = $this->getClass();
+ $this->getTransformation()->apply(
+ $result,
+ new HtmlElement($this->getTag(), $class === null ? null : new Attributes(['class' => $class]))
+ );
+ }
+
+ protected function registerAttributeCallbacks(Attributes $attributes): void
+ {
+ $attributes
+ ->registerAttributeCallback('tag', null, $this->setTag(...))
+ ->registerAttributeCallback('transformation', null, $this->setTransformation(...))
+ ->registerAttributeCallback('condition', null, $this->setCondition(...))
+ ->registerAttributeCallback('class', null, $this->setClass(...));
+ }
+}
diff --git a/vendor/ipl/html/src/FormDecoration/LabelDecorator.php b/vendor/ipl/html/src/FormDecoration/LabelDecorator.php
new file mode 100644
index 0000000..02dc5cf
--- /dev/null
+++ b/vendor/ipl/html/src/FormDecoration/LabelDecorator.php
@@ -0,0 +1,105 @@
+class;
+ }
+
+ /**
+ * Set the css class(es)
+ *
+ * @param string|string[] $class
+ *
+ * @return $this
+ */
+ public function setClass(string|array $class): static
+ {
+ $this->class = $class;
+
+ return $this;
+ }
+
+ public function decorateFormElement(DecorationResult $result, FormElement $formElement): void
+ {
+ $isHtmlElement = $formElement instanceof HtmlElementInterface;
+
+ $elementLabel = $this->getElementLabel($formElement);
+ if (
+ $formElement instanceof FormSubmitElement
+ || $elementLabel === null
+ || ($isHtmlElement && $formElement->getTag() === 'fieldset')
+ ) {
+ return;
+ }
+
+ if ($elementLabel instanceof HtmlElementInterface) {
+ $attributes['class'] = $this->getClass();
+ // RadioElement applies all its attributes to each of its options, so we cannot set a fallback
+ // id and for attribute here.
+ if ($isHtmlElement && ! $formElement instanceof RadioElement) {
+ $elementAttributes = $formElement->getAttributes();
+ if (! $elementAttributes->has('id')) {
+ $elementAttributes->set('id', uniqid('form-element-'));
+ }
+
+ $attributes['for'] = $elementAttributes->get('id')->getValue();
+ }
+
+ $elementLabel->addAttributes($attributes);
+ }
+
+ $result->append($elementLabel);
+ }
+
+ /**
+ * Get the label element for the given form element
+ *
+ * @param FormElement $formElement
+ *
+ * @return ?ValidHtml The label element or null if no label is set
+ */
+ protected function getElementLabel(FormElement $formElement): ?ValidHtml
+ {
+ $label = $formElement->getLabel();
+ if ($label === null) {
+ return null;
+ }
+
+ return new HtmlElement('label', content: new Text($label));
+ }
+
+ protected function registerAttributeCallbacks(Attributes $attributes): void
+ {
+ $attributes->registerAttributeCallback('class', null, $this->setClass(...));
+ }
+}
diff --git a/vendor/ipl/html/src/FormDecoration/RenderElementDecorator.php b/vendor/ipl/html/src/FormDecoration/RenderElementDecorator.php
new file mode 100644
index 0000000..b66bae0
--- /dev/null
+++ b/vendor/ipl/html/src/FormDecoration/RenderElementDecorator.php
@@ -0,0 +1,18 @@
+append($formElement);
+ }
+}
diff --git a/vendor/ipl/html/src/FormDecoration/Transformation.php b/vendor/ipl/html/src/FormDecoration/Transformation.php
new file mode 100644
index 0000000..91e0e8b
--- /dev/null
+++ b/vendor/ipl/html/src/FormDecoration/Transformation.php
@@ -0,0 +1,39 @@
+ $result->append($html),
+ self::Prepend => $result->prepend($html),
+ self::Wrap => $result->wrap($html)
+ };
+ }
+}
diff --git a/vendor/ipl/html/src/FormDecorator/CallbackDecorator.php b/vendor/ipl/html/src/FormDecorator/CallbackDecorator.php
index 1048bfb..7a6c1b8 100644
--- a/vendor/ipl/html/src/FormDecorator/CallbackDecorator.php
+++ b/vendor/ipl/html/src/FormDecorator/CallbackDecorator.php
@@ -7,6 +7,9 @@ use ipl\Html\Contract\FormElement;
use ipl\Html\Contract\FormElementDecorator;
use ipl\Html\HtmlDocument;
+/**
+ * @deprecated Use one of the new {@see FormElementDecoration} decorators instead
+ */
class CallbackDecorator extends HtmlDocument implements FormElementDecorator
{
/** @var Closure The decorating callback */
diff --git a/vendor/ipl/html/src/FormDecorator/DdDtDecorator.php b/vendor/ipl/html/src/FormDecorator/DdDtDecorator.php
index 9cfec20..564b924 100644
--- a/vendor/ipl/html/src/FormDecorator/DdDtDecorator.php
+++ b/vendor/ipl/html/src/FormDecorator/DdDtDecorator.php
@@ -2,11 +2,15 @@
namespace ipl\Html\FormDecorator;
+use ipl\Html\Attributes;
use ipl\Html\BaseHtmlElement;
use ipl\Html\FormElement\BaseFormElement;
use ipl\Html\Html;
use ipl\Html\ValidHtml;
+/**
+ * @deprecated Use one of the new {@see FormElementDecoration} decorators instead
+ */
class DdDtDecorator extends BaseHtmlElement implements DecoratorInterface
{
protected $tag = 'dl';
@@ -92,7 +96,7 @@ class DdDtDecorator extends BaseHtmlElement implements DecoratorInterface
return null;
}
- public function addHtml(ValidHtml ...$content)
+ public function addHtml(ValidHtml ...$content): static
{
// TODO: is this required?
if (! in_array($this->wrappedElement, $content, true)) {
diff --git a/vendor/ipl/html/src/FormDecorator/DecoratorInterface.php b/vendor/ipl/html/src/FormDecorator/DecoratorInterface.php
index 1ed1a38..a9af63f 100644
--- a/vendor/ipl/html/src/FormDecorator/DecoratorInterface.php
+++ b/vendor/ipl/html/src/FormDecorator/DecoratorInterface.php
@@ -2,10 +2,10 @@
namespace ipl\Html\FormDecorator;
-use ipl\Html\Contract\FormElementDecorator;
+use ipl\Html\Contract\FormElementDecoration;
use ipl\Html\FormElement\BaseFormElement;
-/** @deprecated Use {@link FormElementDecorator} instead */
+/** @deprecated Use {@see FormElementDecoration} instead */
interface DecoratorInterface
{
/**
diff --git a/vendor/ipl/html/src/FormDecorator/DivDecorator.php b/vendor/ipl/html/src/FormDecorator/DivDecorator.php
index 4935f01..9553d9b 100644
--- a/vendor/ipl/html/src/FormDecorator/DivDecorator.php
+++ b/vendor/ipl/html/src/FormDecorator/DivDecorator.php
@@ -5,6 +5,7 @@ namespace ipl\Html\FormDecorator;
use ipl\Html\Attributes;
use ipl\Html\BaseHtmlElement;
use ipl\Html\Contract\FormElement;
+use ipl\Html\Contract\FormElementDecoration;
use ipl\Html\Contract\FormElementDecorator;
use ipl\Html\Contract\FormSubmitElement;
use ipl\Html\FormElement\FieldsetElement;
@@ -15,6 +16,8 @@ use ipl\Html\Text;
/**
* Form element decorator based on div elements
+ *
+ * @deprecated Use one of the new {@see FormElementDecoration} decorators instead
*/
class DivDecorator extends BaseHtmlElement implements FormElementDecorator
{
diff --git a/vendor/ipl/html/src/FormElement/BaseFormElement.php b/vendor/ipl/html/src/FormElement/BaseFormElement.php
index 837ac45..1e9a260 100644
--- a/vendor/ipl/html/src/FormElement/BaseFormElement.php
+++ b/vendor/ipl/html/src/FormElement/BaseFormElement.php
@@ -5,15 +5,24 @@ namespace ipl\Html\FormElement;
use ipl\Html\Attribute;
use ipl\Html\Attributes;
use ipl\Html\BaseHtmlElement;
+use ipl\Html\Contract\DecorableFormElement;
use ipl\Html\Contract\FormElement;
+use ipl\Html\Contract\FormElementDecoration;
use ipl\Html\Contract\ValueCandidates;
use ipl\Html\Form;
+use ipl\Html\FormDecoration\DecoratorChain;
+use ipl\Html\FormDecoration\FormElementDecorationResult;
use ipl\I18n\Translation;
use ipl\Stdlib\Messages;
use ipl\Validator\ValidatorChain;
use ReflectionProperty;
-abstract class BaseFormElement extends BaseHtmlElement implements FormElement, ValueCandidates
+/**
+ * Base implementation of a form element
+ *
+ * @phpstan-import-type decoratorsFormat from DecoratorChain
+ */
+abstract class BaseFormElement extends BaseHtmlElement implements FormElement, ValueCandidates, DecorableFormElement
{
use Messages;
use Translation;
@@ -27,6 +36,9 @@ abstract class BaseFormElement extends BaseHtmlElement implements FormElement, V
/** @var string Name of the element */
protected $name;
+ /** @var string Escaped name of the element */
+ protected string $escapedName;
+
/** @var bool Whether the element is ignored */
protected $ignored = false;
@@ -45,6 +57,9 @@ abstract class BaseFormElement extends BaseHtmlElement implements FormElement, V
/** @var array Value candidates of the element */
protected $valueCandidates = [];
+ /** @var ?DecoratorChain All registered decorators */
+ protected ?DecoratorChain $decorators = null;
+
/**
* Create a new form element
*
@@ -115,6 +130,9 @@ abstract class BaseFormElement extends BaseHtmlElement implements FormElement, V
{
$this->name = $name;
+ // Name is always escaped
+ $this->escapedName = Form::escapeReservedChars($name);
+
return $this;
}
@@ -137,6 +155,16 @@ abstract class BaseFormElement extends BaseHtmlElement implements FormElement, V
return $this;
}
+ /**
+ * Get the escaped name of the element
+ *
+ * @return string
+ */
+ public function getEscapedName(): string
+ {
+ return $this->escapedName;
+ }
+
public function isRequired()
{
return $this->required;
@@ -289,7 +317,7 @@ abstract class BaseFormElement extends BaseHtmlElement implements FormElement, V
*/
public function getNameAttribute()
{
- return $this->getName();
+ return $this->getEscapedName();
}
/**
@@ -351,7 +379,8 @@ abstract class BaseFormElement extends BaseHtmlElement implements FormElement, V
->registerAttributeCallback('description', null, [$this, 'setDescription'])
->registerAttributeCallback('validators', null, [$this, 'setValidators'])
->registerAttributeCallback('ignore', null, [$this, 'setIgnored'])
- ->registerAttributeCallback('required', [$this, 'getRequiredAttribute'], [$this, 'setRequired']);
+ ->registerAttributeCallback('required', [$this, 'getRequiredAttribute'], [$this, 'setRequired'])
+ ->registerAttributeCallback('decorators', null, [$this, 'setDecorators']);
$this->registerCallbacks();
}
@@ -385,6 +414,49 @@ abstract class BaseFormElement extends BaseHtmlElement implements FormElement, V
return $name;
}
- return $this->getName();
+ return $this->getEscapedName();
+ }
+
+ public function getDecorators(): DecoratorChain
+ {
+ if ($this->decorators === null) {
+ $this->decorators = new DecoratorChain(FormElementDecoration::class);
+ }
+
+ return $this->decorators;
+ }
+
+ /**
+ * Set the decorators
+ *
+ * @param decoratorsFormat $decorators
+ *
+ * @return $this
+ */
+ public function setDecorators(array $decorators): static
+ {
+ $this->getDecorators()
+ ->clearDecorators()
+ ->addDecorators($decorators);
+
+ return $this;
+ }
+
+ public function hasDecorators(): bool
+ {
+ return $this->getDecorators()->hasDecorators();
+ }
+
+ public function applyDecoration(): void
+ {
+ $results = new FormElementDecorationResult();
+ foreach ($this->getDecorators() as $decorator) {
+ $decorator->decorateFormElement($results, $this);
+ }
+
+ $wrapper = $results->assemble();
+ if (! $wrapper->isEmpty()) {
+ $this->addWrapper($wrapper);
+ }
}
}
diff --git a/vendor/ipl/html/src/FormElement/FieldsetElement.php b/vendor/ipl/html/src/FormElement/FieldsetElement.php
index c18d472..978745f 100644
--- a/vendor/ipl/html/src/FormElement/FieldsetElement.php
+++ b/vendor/ipl/html/src/FormElement/FieldsetElement.php
@@ -4,6 +4,7 @@ namespace ipl\Html\FormElement;
use InvalidArgumentException;
use ipl\Html\Common\MultipleAttribute;
+use ipl\Html\Contract\DefaultFormElementDecoration;
use ipl\Html\Contract\FormElement;
use ipl\Html\Contract\FormElementDecorator;
use ipl\Html\Contract\Wrappable;
@@ -11,7 +12,7 @@ use LogicException;
use function ipl\Stdlib\get_php_type;
-class FieldsetElement extends BaseFormElement
+class FieldsetElement extends BaseFormElement implements \ipl\Html\Contract\FormElements, DefaultFormElementDecoration
{
use FormElements {
FormElements::getValue as private getElementValue;
@@ -26,6 +27,8 @@ class FieldsetElement extends BaseFormElement
*/
public function hasValue()
{
+ $this->ensureAssembled();
+
foreach ($this->getElements() as $element) {
if ($element->hasValue()) {
return true;
@@ -113,6 +116,14 @@ class FieldsetElement extends BaseFormElement
$multiple = $element->isMultiple();
}
+ // This check is required as the getEscapedName method is not implemented in
+ // the FormElement interface
+ if ($element instanceof BaseFormElement) {
+ $name = $element->getEscapedName();
+ } else {
+ $name = $element->getName();
+ }
+
/**
* We don't change the {@see BaseFormElement::$name} property of the element,
* otherwise methods like {@see FormElements::populate() and {@see FormElements::getElement()} would fail,
@@ -121,7 +132,7 @@ class FieldsetElement extends BaseFormElement
return sprintf(
'%s[%s]%s',
$this->getValueOfNameAttribute(),
- $element->getName(),
+ $name,
$multiple ? '[]' : ''
);
});
diff --git a/vendor/ipl/html/src/FormElement/FileElement.php b/vendor/ipl/html/src/FormElement/FileElement.php
index d9ca8fd..c284368 100644
--- a/vendor/ipl/html/src/FormElement/FileElement.php
+++ b/vendor/ipl/html/src/FormElement/FileElement.php
@@ -93,7 +93,7 @@ class FileElement extends InputElement
public function getNameAttribute()
{
- $name = $this->getName();
+ $name = $this->getEscapedName();
return $this->isMultiple() ? ($name . '[]') : $name;
}
@@ -260,12 +260,12 @@ class FileElement extends InputElement
$form->setAttribute('enctype', 'multipart/form-data');
}
- $chosenFiles = (array) $form->getPopulatedValue('chosen_file_' . $this->getName(), []);
+ $chosenFiles = (array) $form->getPopulatedValue('chosen_file_' . $this->getEscapedName(), []);
foreach ($chosenFiles as $chosenFile) {
$this->files[$chosenFile] = null;
}
- $this->filesToRemove = (array) $form->getPopulatedValue('remove_file_' . $this->getName(), []);
+ $this->filesToRemove = (array) $form->getPopulatedValue('remove_file_' . $this->getEscapedName(), []);
}
protected function addDefaultValidators(ValidatorChain $chain): void
diff --git a/vendor/ipl/html/src/FormElement/FormElements.php b/vendor/ipl/html/src/FormElement/FormElements.php
index 4a2c598..6121b76 100644
--- a/vendor/ipl/html/src/FormElement/FormElements.php
+++ b/vendor/ipl/html/src/FormElement/FormElements.php
@@ -3,18 +3,29 @@
namespace ipl\Html\FormElement;
use InvalidArgumentException;
+use ipl\Html\Contract\DecorableFormElement;
+use ipl\Html\Contract\DefaultFormElementDecoration;
use ipl\Html\Contract\FormElement;
+use ipl\Html\Contract\FormElementDecoration;
use ipl\Html\Contract\FormElementDecorator;
use ipl\Html\Contract\ValueCandidates;
use ipl\Html\Form;
+use ipl\Html\FormDecoration\DecoratorChain;
use ipl\Html\FormDecorator\DecoratorInterface;
+use ipl\Html\HtmlDocument;
use ipl\Html\ValidHtml;
use ipl\Stdlib\Events;
use ipl\Stdlib\Plugins;
+use RuntimeException;
use UnexpectedValueException;
+use WeakMap;
use function ipl\Stdlib\get_php_type;
+/**
+ * @phpstan-import-type decoratorsFormat from DecoratorChain
+ * @phpstan-import-type loaderPaths from DefaultFormElementDecoration
+ */
trait FormElements
{
use Events;
@@ -29,6 +40,29 @@ trait FormElements
/** @var bool Whether the default element loader has been registered */
protected $defaultElementLoaderRegistered = false;
+ /** @var ?WeakMap The decorated elements */
+ private ?WeakMap $decoratedElements = null;
+
+ /**
+ * Custom Element decorator loader paths
+ *
+ * Override this property to add custom decorator loader paths.
+ *
+ * @var loaderPaths
+ */
+ protected array $elementDecoratorLoaderPaths = [];
+
+ /**
+ * Default element decorators
+ *
+ * Override this property to change the default decorators of the elements.
+ *
+ * Please see {@see DecoratorChain::addDecorators()} for the supported array formats.
+ *
+ * @var decoratorsFormat
+ */
+ protected array $defaultElementDecorators = [];
+
/** @var FormElement[] */
private $elements = [];
@@ -36,22 +70,42 @@ trait FormElements
private $populatedValues = [];
/**
- * Get all elements
+ * Get the default element decorators.
*
- * @return FormElement[]
+ * @return decoratorsFormat
*/
+ public function getDefaultElementDecorators(): array
+ {
+ return $this->defaultElementDecorators;
+ }
+
+ public function setDefaultElementDecorators(array $decorators): static
+ {
+ if ($this->hasDefaultElementDecorator()) {
+ throw new RuntimeException(sprintf(
+ 'Cannot use element decorators of type %s and legacy decorator of type %s together',
+ FormElementDecoration::class,
+ FormElementDecorator::class
+ ));
+ }
+
+ $this->defaultElementDecorators = $decorators;
+
+ return $this;
+ }
+
+ public function addElementDecoratorLoaderPaths(array $loaderPaths): static
+ {
+ $this->elementDecoratorLoaderPaths = $loaderPaths;
+
+ return $this;
+ }
+
public function getElements()
{
return $this->elements;
}
- /**
- * Get whether the given element exists
- *
- * @param string|FormElement $element
- *
- * @return bool
- */
public function hasElement($element)
{
if (is_string($element)) {
@@ -65,15 +119,6 @@ trait FormElements
return false;
}
- /**
- * Get the element by the given name
- *
- * @param string $name
- *
- * @return FormElement
- *
- * @throws InvalidArgumentException If no element with the given name exists
- */
public function getElement($name)
{
if (! array_key_exists($name, $this->elements)) {
@@ -86,20 +131,6 @@ trait FormElements
return $this->elements[$name];
}
- /**
- * Add an element
- *
- * @param string|FormElement $typeOrElement Type of the element as string or an instance of FormElement
- * @param string $name Name of the element
- * @param mixed $options Element options as key-value pairs
- *
- * @return $this
- *
- * @throws InvalidArgumentException If $typeOrElement is neither a string nor an instance of FormElement
- * or if $typeOrElement is a string and $name is not set
- * or if $typeOrElement is a string but type is unknown
- * or if $typeOrElement is an instance of FormElement but does not have a name
- */
public function addElement($typeOrElement, $name = null, $options = null)
{
if (is_string($typeOrElement)) {
@@ -157,6 +188,37 @@ trait FormElements
/** @var FormElement $element */
$element = new $class($name);
+ if ($element instanceof DecorableFormElement) {
+ $customDecoratorPaths = $this->elementDecoratorLoaderPaths;
+ $elementDecoratorChain = $element->getDecorators();
+ if (! empty($customDecoratorPaths)) {
+ if ($element instanceof DefaultFormElementDecoration) {
+ $element->addElementDecoratorLoaderPaths($customDecoratorPaths);
+ }
+
+ foreach ($customDecoratorPaths as $path) {
+ $elementDecoratorChain->addDecoratorLoader($path[0], $path[1] ?? '');
+ }
+ }
+
+ $defaultDecorators = $this->getDefaultElementDecorators();
+ if (
+ ! empty($defaultDecorators)
+ && ! $this->hasDefaultElementDecorator()
+ && empty($options['hidden'])
+ && ! $element instanceof HiddenElement
+ && $element->getAttributes()->get('hidden')->isEmpty()
+ ) {
+ if ($element instanceof DefaultFormElementDecoration) {
+ $element->setDefaultElementDecorators($defaultDecorators);
+ }
+
+ if (! isset($options['decorators'])) {
+ $elementDecoratorChain->addDecorators($defaultDecorators);
+ }
+ }
+ }
+
if ($options !== null) {
$element->addAttributes($options);
}
@@ -164,21 +226,18 @@ trait FormElements
return $element;
}
- /**
- * Register an element
- *
- * Registers the element for value and validation handling but does not add it to the render stack.
- *
- * @param FormElement $element
- *
- * @return $this
- *
- * @throws InvalidArgumentException If $element does not provide a name
- */
public function registerElement(FormElement $element)
{
$name = $element->getName();
+ // This check is required as the getEscapedName method is not implemented in
+ // the FormElement interface
+ if ($element instanceof BaseFormElement) {
+ $escapedName = $element->getEscapedName();
+ } else {
+ $escapedName = $name;
+ }
+
if ($name === null) {
throw new InvalidArgumentException(sprintf(
'%s expects the element to provide a name',
@@ -188,11 +247,13 @@ trait FormElements
$this->elements[$name] = $element;
- if (array_key_exists($name, $this->populatedValues)) {
- $element->setValue($this->populatedValues[$name][count($this->populatedValues[$name]) - 1]);
+ if (array_key_exists($escapedName, $this->populatedValues)) {
+ $element->setValue(
+ $this->populatedValues[$escapedName][count($this->populatedValues[$escapedName]) - 1]
+ );
if ($element instanceof ValueCandidates) {
- $element->setValueCandidates($this->populatedValues[$name]);
+ $element->setValueCandidates($this->populatedValues[$escapedName]);
}
}
@@ -206,6 +267,8 @@ trait FormElements
* Get whether a default element decorator exists
*
* @return bool
+ * @deprecated This is not of general use anymore. The new decorator implementation handles defaults entirely
+ * internally now. Use {@see getDefaultElementDecorators()} instead only if you absolutely have to.
*/
public function hasDefaultElementDecorator()
{
@@ -216,6 +279,7 @@ trait FormElements
* Get the default element decorator, if any
*
* @return FormElementDecorator|null
+ * @deprecated Use {@see getDefaultElementDecorators()} instead
*/
public function getDefaultElementDecorator()
{
@@ -233,12 +297,21 @@ trait FormElements
*
* @return $this
*
+ * @deprecated Use {@see setDefaultElementDecorators()} instead
* @throws InvalidArgumentException If $decorator is a string and can't be loaded from registered decorator loaders
* or if a decorator loader does not return an instance of
* {@link FormElementDecorator}
*/
public function setDefaultElementDecorator($decorator)
{
+ if (! empty($this->getDefaultElementDecorators())) {
+ throw new RuntimeException(sprintf(
+ 'Cannot use element decorators of type %s and legacy decorator of type %s together',
+ FormElementDecoration::class,
+ FormElementDecorator::class
+ ));
+ }
+
if ($decorator instanceof FormElementDecorator || $decorator instanceof DecoratorInterface) {
$this->defaultElementDecorator = $decorator;
} else {
@@ -269,16 +342,6 @@ trait FormElements
return $this;
}
- /**
- * Get the value of the element specified by name
- *
- * Returns $default if the element does not exist or has no value.
- *
- * @param string $name
- * @param mixed $default
- *
- * @return mixed
- */
public function getValue($name, $default = null)
{
if ($this->hasElement($name)) {
@@ -291,11 +354,6 @@ trait FormElements
return $default;
}
- /**
- * Get the values for all but ignored elements
- *
- * @return array Values as name-value pairs
- */
public function getValues()
{
$values = [];
@@ -308,17 +366,10 @@ trait FormElements
return $values;
}
- /**
- * Populate values of registered elements
- *
- * @param iterable $values Values as name-value pairs
- *
- * @return $this
- */
public function populate($values)
{
foreach ($values as $name => $value) {
- $this->populatedValues[$name][] = $value;
+ $this->populatedValues[Form::escapeReservedChars($name)][] = $value;
if ($this->hasElement($name)) {
$this->getElement($name)->setValue($value);
}
@@ -339,6 +390,7 @@ trait FormElements
*/
public function getPopulatedValue($name, $default = null)
{
+ $name = Form::escapeReservedChars($name);
return isset($this->populatedValues[$name])
? $this->populatedValues[$name][count($this->populatedValues[$name]) - 1]
: $default;
@@ -353,6 +405,7 @@ trait FormElements
*/
public function clearPopulatedValue($name)
{
+ $name = Form::escapeReservedChars($name);
if (isset($this->populatedValues[$name])) {
unset($this->populatedValues[$name]);
}
@@ -383,6 +436,7 @@ trait FormElements
* @param string $postfix Decorator name postfix, if any
*
* @return $this
+ * @deprecated Use {@see addElementDecoratorLoaderPaths()} instead
*/
public function addDecoratorLoader($namespace, $postfix = null)
{
@@ -454,6 +508,16 @@ trait FormElements
*/
protected function decorate(FormElement $element)
{
+ if ($element instanceof DecorableFormElement && $element->hasDecorators()) {
+ // new decorator implementation in use
+ $this->decoratedElements ??= new WeakMap();
+ if (! isset($this->decoratedElements[$element])) {
+ $this->decoratedElements[$element] = false;
+ }
+
+ return $this;
+ }
+
if ($this->hasDefaultElementDecorator()) {
$decorator = $this->getDefaultElementDecorator();
@@ -475,7 +539,7 @@ trait FormElements
public function isValidEvent($event)
{
return in_array($event, [
- Form::ON_SUCCESS,
+ Form::ON_SUBMIT,
Form::ON_SENT,
Form::ON_ERROR,
Form::ON_REQUEST,
@@ -484,18 +548,49 @@ trait FormElements
]);
}
- public function remove(ValidHtml $elementOrHtml)
+ public function removeElement(string|FormElement $element)
{
- if ($elementOrHtml instanceof FormElement) {
- if ($this->hasElement($elementOrHtml)) {
- $name = array_search($elementOrHtml, $this->elements, true);
+ if (is_string($element)) {
+ if (! $this->hasElement($element)) {
+ return $this;
+ }
+
+ $element = $this->getElement($element);
+ }
+
+ return $this->remove($element);
+ }
+
+ public function remove(ValidHtml $content)
+ {
+ if ($content instanceof FormElement) {
+ if ($this->hasElement($content)) {
+ if (isset($this->decoratedElements[$content])) {
+ unset($this->decoratedElements[$content]);
+ }
+
+ $name = array_search($content, $this->elements, true);
if ($name !== false) {
unset($this->elements[$name]);
}
}
}
- return parent::remove($elementOrHtml);
+ return parent::remove($content);
+ }
+
+ protected function beforeRender(): void
+ {
+ if ($this instanceof HtmlDocument) {
+ parent::beforeRender();
+ }
+
+ foreach ($this->decoratedElements ?? [] as $element => &$decorated) {
+ if (! $decorated) {
+ $element->applyDecoration();
+ $decorated = true;
+ }
+ }
}
/**
diff --git a/vendor/ipl/html/src/FormElement/RadioElement.php b/vendor/ipl/html/src/FormElement/RadioElement.php
index 831671c..39ce438 100644
--- a/vendor/ipl/html/src/FormElement/RadioElement.php
+++ b/vendor/ipl/html/src/FormElement/RadioElement.php
@@ -24,6 +24,14 @@ class RadioElement extends BaseFormElement
/** @var array Disabled radio options */
protected $disabledOptions = [];
+ protected function tag(): string
+ {
+ // In order to be able to decorate this element, we need to return a tag.
+ // If we'd have a distinct form element base implementation, that doesn't
+ // extend BaseHtmlElement, this wouldn't be necessary.
+ return 'bogus';
+ }
+
/**
* Set the options
*
@@ -101,6 +109,8 @@ class RadioElement extends BaseFormElement
protected function assemble()
{
+ // To avoid duplicate ids for options. Required for tests or if someone sets explicitly.
+ $this->getAttributes()->remove('id');
foreach ($this->options as $option) {
$radio = (new InputElement($this->getValueOfNameAttribute()))
->setType($this->type)
diff --git a/vendor/ipl/html/src/FormElement/SelectElement.php b/vendor/ipl/html/src/FormElement/SelectElement.php
index e6b4f21..cef7a8e 100644
--- a/vendor/ipl/html/src/FormElement/SelectElement.php
+++ b/vendor/ipl/html/src/FormElement/SelectElement.php
@@ -111,7 +111,7 @@ class SelectElement extends BaseFormElement
public function getNameAttribute()
{
- $name = $this->getName();
+ $name = $this->getEscapedName();
return $this->isMultiple() ? ($name . '[]') : $name;
}
diff --git a/vendor/ipl/html/src/FormElement/TextElement.php b/vendor/ipl/html/src/FormElement/TextElement.php
index 0e3423d..b650209 100644
--- a/vendor/ipl/html/src/FormElement/TextElement.php
+++ b/vendor/ipl/html/src/FormElement/TextElement.php
@@ -2,7 +2,43 @@
namespace ipl\Html\FormElement;
+use ipl\Html\Attributes;
+
class TextElement extends InputElement
{
protected $type = 'text';
+
+ /** @var ?string Placeholder text for the input */
+ protected ?string $placeholder = null;
+
+ /**
+ * Get the placeholder
+ *
+ * @return ?string
+ */
+ public function getPlaceholder(): ?string
+ {
+ return $this->placeholder;
+ }
+
+ /**
+ * Set the placeholder
+ *
+ * @param ?string $placeholder
+ *
+ * @return $this
+ */
+ public function setPlaceholder(?string $placeholder): self
+ {
+ $this->placeholder = $placeholder;
+
+ return $this;
+ }
+
+ protected function registerAttributeCallbacks(Attributes $attributes): void
+ {
+ parent::registerAttributeCallbacks($attributes);
+
+ $attributes->registerAttributeCallback('placeholder', [$this, 'getPlaceholder'], [$this, 'setPlaceholder']);
+ }
}
diff --git a/vendor/ipl/html/src/HtmlDocument.php b/vendor/ipl/html/src/HtmlDocument.php
index d9a153a..58fad73 100644
--- a/vendor/ipl/html/src/HtmlDocument.php
+++ b/vendor/ipl/html/src/HtmlDocument.php
@@ -4,6 +4,7 @@ namespace ipl\Html;
use Countable;
use InvalidArgumentException;
+use ipl\Html\Contract\MutableHtml;
use ipl\Html\Contract\Wrappable;
use ipl\Stdlib\Events;
use RuntimeException;
@@ -14,7 +15,7 @@ use Throwable;
*
* An HTML document is composed of a tree of HTML nodes, i.e. text nodes and HTML elements.
*/
-class HtmlDocument implements Countable, Wrappable
+class HtmlDocument implements Countable, Wrappable, MutableHtml
{
use Events;
@@ -27,14 +28,14 @@ class HtmlDocument implements Countable, Wrappable
/** @var bool Whether the document has been assembled */
protected $hasBeenAssembled = false;
- /** @var Wrappable Wrapper */
+ /** @var ?Wrappable Wrapper */
protected $wrapper;
- /** @var Wrappable Wrapped element */
- private $wrapped;
+ /** @var ?Wrappable Wrapped element */
+ private null|Wrappable $wrapped = null;
- /** @var HtmlDocument The currently responsible wrapper */
- private $renderedBy;
+ /** @var ?Wrappable The currently responsible wrapper */
+ private null|Wrappable $renderedBy = null;
/** @var ValidHtml[] Content */
private $content = [];
@@ -59,7 +60,7 @@ class HtmlDocument implements Countable, Wrappable
/**
* Consume the wrapped element
*
- * @return Wrappable
+ * @return ?Wrappable
*/
private function consumeWrapped()
{
@@ -69,11 +70,6 @@ class HtmlDocument implements Countable, Wrappable
return $wrapped;
}
- /**
- * Get the content
- *
- * return ValidHtml[]
- */
public function getContent()
{
return $this->content;
@@ -94,13 +90,6 @@ class HtmlDocument implements Countable, Wrappable
return $this;
}
- /**
- * Set content
- *
- * @param ValidHtml ...$content
- *
- * @return $this
- */
public function setHtmlContent(ValidHtml ...$content)
{
$this->content = [];
@@ -158,14 +147,6 @@ class HtmlDocument implements Countable, Wrappable
));
}
- /**
- * Insert Html after an existing Html node
- *
- * @param ValidHtml $newNode
- * @param ValidHtml $existingNode
- *
- * @return $this
- */
public function insertAfter(ValidHtml $newNode, ValidHtml $existingNode): self
{
$index = array_search($existingNode, $this->content, true);
@@ -180,14 +161,6 @@ class HtmlDocument implements Countable, Wrappable
return $this;
}
- /**
- * Insert Html after an existing Html node
- *
- * @param ValidHtml $newNode
- * @param ValidHtml $existingNode
- *
- * @return $this
- */
public function insertBefore(ValidHtml $newNode, ValidHtml $existingNode): self
{
$index = array_search($existingNode, $this->content);
@@ -216,13 +189,6 @@ class HtmlDocument implements Countable, Wrappable
return $this;
}
- /**
- * Add content
- *
- * @param ValidHtml ...$content
- *
- * @return $this
- */
public function addHtml(ValidHtml ...$content)
{
foreach ($content as $element) {
@@ -252,25 +218,15 @@ class HtmlDocument implements Countable, Wrappable
return $this;
}
- /**
- * Check whether the given element is a direct or indirect child of this document
- *
- * A direct child is one that is part of this document's content. An indirect child
- * is one that is part of a direct child's content (recursively).
- *
- * @param ValidHtml $element
- *
- * @return bool
- */
- public function contains(ValidHtml $element)
+ public function contains(ValidHtml $content)
{
- $key = spl_object_hash($element);
+ $key = spl_object_hash($content);
if (array_key_exists($key, $this->contentIndex)) {
return true;
}
foreach ($this->content as $child) {
- if ($child instanceof self && $child->contains($element)) {
+ if ($child instanceof self && $child->contains($content)) {
return true;
}
}
@@ -292,13 +248,6 @@ class HtmlDocument implements Countable, Wrappable
return $this;
}
- /**
- * Prepend content
- *
- * @param ValidHtml ...$content
- *
- * @return $this
- */
public function prependHtml(ValidHtml ...$content)
{
foreach (array_reverse($content) as $html) {
@@ -310,16 +259,9 @@ class HtmlDocument implements Countable, Wrappable
return $this;
}
- /**
- * Remove content
- *
- * @param ValidHtml $html
- *
- * @return $this
- */
- public function remove(ValidHtml $html)
+ public function remove(ValidHtml $content)
{
- $key = spl_object_hash($html);
+ $key = spl_object_hash($content);
if (array_key_exists($key, $this->contentIndex)) {
foreach ($this->contentIndex[$key] as $pos) {
unset($this->content[$pos]);
@@ -349,11 +291,6 @@ class HtmlDocument implements Countable, Wrappable
return $this;
}
- /**
- * Get whether the document is empty
- *
- * @return bool
- */
public function isEmpty()
{
$this->ensureAssembled();
@@ -442,7 +379,10 @@ class HtmlDocument implements Countable, Wrappable
$wrapper = $this->wrapper;
if (isset($this->renderedBy)) {
- if ($wrapper === $this->renderedBy || $wrapper->contains($this->renderedBy)) {
+ if (
+ $wrapper === $this->renderedBy
+ || ($wrapper instanceof self && $wrapper->contains($this->renderedBy))
+ ) {
// $this might be an intermediate wrapper that's already about to be rendered.
// In case of an element (referencing $this as a wrapper) that is a child of an
// outer wrapper, it is required to ignore $wrapper as otherwise it's a loop.
@@ -553,7 +493,7 @@ class HtmlDocument implements Countable, Wrappable
protected function isIntermediateWrapper(ValidHtml $element): bool
{
foreach ($this->content as $child) {
- if ($child instanceof self && $child->wrappedBy($element)) {
+ if ($child instanceof self && ($child->wrappedBy($element) || $child->isIntermediateWrapper($element))) {
return true;
}
}
@@ -561,9 +501,19 @@ class HtmlDocument implements Countable, Wrappable
return false;
}
+ /**
+ * Last call before rendering the document
+ *
+ * @return void
+ */
+ protected function beforeRender(): void
+ {
+ }
+
public function render()
{
$this->ensureAssembled();
+ $this->beforeRender();
if ($this->wrapper === null) {
return $this->renderUnwrapped();
} else {
diff --git a/vendor/ipl/orm/composer.json b/vendor/ipl/orm/composer.json
index 71f17de..83f7cde 100644
--- a/vendor/ipl/orm/composer.json
+++ b/vendor/ipl/orm/composer.json
@@ -10,7 +10,7 @@
],
"homepage": "https://github.com/Icinga/ipl-orm",
"require": {
- "php": ">=7.2",
+ "php": ">=8.2",
"ext-pdo": "*",
"ipl/sql": ">=0.7.0",
"ipl/stdlib": ">=0.12.0"
diff --git a/vendor/ipl/orm/src/Relation/BelongsToMany.php b/vendor/ipl/orm/src/Relation/BelongsToMany.php
index aad4f03..fa69245 100644
--- a/vendor/ipl/orm/src/Relation/BelongsToMany.php
+++ b/vendor/ipl/orm/src/Relation/BelongsToMany.php
@@ -22,6 +22,9 @@ class BelongsToMany extends Relation
/** @var string Name of the join table or junction model class */
protected $throughClass;
+ /** @var ?string Alias for the join table or junction model class */
+ protected ?string $throughAlias = null;
+
/** @var Model The junction model */
protected $through;
@@ -55,6 +58,30 @@ class BelongsToMany extends Relation
return $this;
}
+ /**
+ * Get the alias for the join table or junction model class
+ *
+ * @return string
+ */
+ public function getThroughAlias(): string
+ {
+ return $this->throughAlias ?? $this->getThrough()->getTableAlias();
+ }
+
+ /**
+ * Set the alias for the join table or junction model class
+ *
+ * @param string $throughAlias
+ *
+ * @return $this
+ */
+ public function setThroughAlias(string $throughAlias): self
+ {
+ $this->throughAlias = $throughAlias;
+
+ return $this;
+ }
+
/**
* Get the junction model
*
@@ -179,7 +206,7 @@ class BelongsToMany extends Relation
$junctionClass = static::RELATION_CLASS;
$toJunction = (new $junctionClass())
- ->setName($junction->getTableAlias())
+ ->setName($this->getThroughAlias())
->setSource($source)
->setTarget($junction)
->setCandidateKey($this->extractKey($possibleCandidateKey))
diff --git a/vendor/ipl/orm/src/Resolver.php b/vendor/ipl/orm/src/Resolver.php
index a3b99b3..fd4f658 100644
--- a/vendor/ipl/orm/src/Resolver.php
+++ b/vendor/ipl/orm/src/Resolver.php
@@ -567,10 +567,9 @@ class Resolver
$resolvedRelations[$relationPath] = $relation;
if ($relation instanceof BelongsToMany) {
- $through = $relation->getThrough();
- $this->setAlias($through, join('_', array_merge(
+ $this->setAlias($relation->getThrough(), join('_', array_merge(
array_slice($segments, 0, -1),
- [$through->getTableAlias()]
+ [$relation->getThroughAlias()]
)));
}
diff --git a/vendor/ipl/sql/src/Connection.php b/vendor/ipl/sql/src/Connection.php
index de84c72..9480fe7 100644
--- a/vendor/ipl/sql/src/Connection.php
+++ b/vendor/ipl/sql/src/Connection.php
@@ -8,6 +8,7 @@ use InvalidArgumentException;
use ipl\Sql\Contract\Adapter;
use ipl\Sql\Contract\Quoter;
use ipl\Stdlib\Plugins;
+use LogicException;
use PDO;
use PDOStatement;
@@ -438,6 +439,25 @@ class Connection implements Quoter
return $this->prepexec($insert);
}
+ /**
+ * Get the ID of the last inserted row
+ *
+ * @param ?string $name The name of the sequence object from which the ID should be returned.
+ *
+ * @throws LogicException If no connection to the database is established
+ * @return false|string
+ */
+ public function lastInsertId(?string $name = null): false|string
+ {
+ if ($this->pdo === null) {
+ throw new LogicException(
+ 'Cannot get last insert ID because no connection to the database is established.'
+ );
+ }
+
+ return $this->pdo->lastInsertId($name);
+ }
+
/**
* Update table rows with the specified data, optionally based on a given condition
*
diff --git a/vendor/ipl/sql/src/Test/SharedDatabases.php b/vendor/ipl/sql/src/Test/SharedDatabases.php
new file mode 100644
index 0000000..5c54fb2
--- /dev/null
+++ b/vendor/ipl/sql/src/Test/SharedDatabases.php
@@ -0,0 +1,175 @@
+
+ */
+ final public static function sharedDatabases(): array
+ {
+ self::initializeDatabases();
+
+ return self::$connections;
+ }
+
+ /**
+ * Get the current database connection
+ *
+ * @return Connection
+ * @throws RuntimeException if the connection cannot be retrieved
+ */
+ final protected function getConnection(): Connection
+ {
+ if (method_exists($this, 'getProvidedData')) {
+ $connections = $this->getProvidedData();
+ } elseif (method_exists($this, 'providedData')) {
+ $connections = $this->providedData();
+ } else {
+ throw new RuntimeException('Cannot get connection: Unsupported PHPUnit version?');
+ }
+
+ $connection = $connections[0];
+ if (! $connection instanceof Connection) {
+ throw new RuntimeException('Cannot get connection: Are all test cases using the same provider?');
+ }
+
+ return $connection;
+ }
+
+ /**
+ * Get the value of an environment variable
+ *
+ * @param string $name
+ *
+ * @return string
+ *
+ * @throws RuntimeException if the environment variable is not set
+ */
+ final protected static function getEnvironmentVariable(string $name): string
+ {
+ $value = getenv($name);
+ if ($value === false) {
+ throw new RuntimeException("Environment variable $name is not set");
+ }
+
+ return $value;
+ }
+
+ /**
+ * Get the connection configuration for the test database
+ *
+ * @param string $driver
+ *
+ * @return Config
+ */
+ final protected static function getConnectionConfig(string $driver): Config
+ {
+ return new Config([
+ 'db' => $driver,
+ 'host' => self::getEnvironmentVariable(strtoupper($driver) . '_TESTDB_HOST'),
+ 'port' => self::getEnvironmentVariable(strtoupper($driver) . '_TESTDB_PORT'),
+ 'username' => self::getEnvironmentVariable(strtoupper($driver) . '_TESTDB_USER'),
+ 'password' => self::getEnvironmentVariable(strtoupper($driver) . '_TESTDB_PASSWORD'),
+ 'dbname' => self::getEnvironmentVariable(strtoupper($driver) . '_TESTDB')
+ ]);
+ }
+
+ /**
+ * Create a database connection
+ *
+ * @param string $driver
+ *
+ * @return Connection
+ *
+ * @internal Only the trait itself should call this method
+ */
+ final protected static function connectToDatabase(string $driver): Connection
+ {
+ return new Connection(self::getConnectionConfig($driver));
+ }
+
+ /**
+ * Set up the database connections
+ *
+ * @return void
+ *
+ * @internal Only the trait itself should call this method
+ */
+ final protected static function initializeDatabases(): void
+ {
+ foreach (self::SUPPORTED_ADAPTERS as $driver) {
+ if (isset($_SERVER[strtoupper($driver) . '_TESTDB'])) {
+ if (! isset(self::$connections[$driver])) {
+ self::$connections[$driver] = [self::connectToDatabase($driver)];
+ static::tearDownSchema(self::$connections[$driver][0], $driver);
+ static::setUpSchema(self::$connections[$driver][0], $driver);
+ }
+ }
+ }
+ }
+}
diff --git a/vendor/ipl/sql/src/Test/TestConnection.php b/vendor/ipl/sql/src/Test/TestConnection.php
index 981696b..913070f 100644
--- a/vendor/ipl/sql/src/Test/TestConnection.php
+++ b/vendor/ipl/sql/src/Test/TestConnection.php
@@ -13,4 +13,53 @@ class TestConnection extends Connection
{
$this->adapter = new TestAdapter();
}
+
+ public function connect()
+ {
+ return $this;
+ }
+
+ public function beginTransaction()
+ {
+ throw new \LogicException('Transactions are not supported by the test connection');
+ }
+
+ public function commitTransaction()
+ {
+ throw new \LogicException('Transactions are not supported by the test connection');
+ }
+
+ public function rollbackTransaction()
+ {
+ throw new \LogicException('Transactions are not supported by the test connection');
+ }
+
+ public function prepexec($stmt, $values = null)
+ {
+ if (PHP_MAJOR_VERSION >= 8) {
+ return new class extends \PDOStatement {
+ public function getIterator(): \Iterator
+ {
+ return new \ArrayIterator([]);
+ }
+
+ public function setFetchMode($mode, ...$args): bool
+ {
+ return true;
+ }
+ };
+ } else {
+ return new class extends \PDOStatement {
+ public function getIterator(): \Iterator
+ {
+ return new \ArrayIterator([]);
+ }
+
+ public function setFetchMode($mode, $params = null): bool
+ {
+ return true;
+ }
+ };
+ }
+ }
}
diff --git a/vendor/ipl/validator/composer.json b/vendor/ipl/validator/composer.json
index 51ba68d..260b7d9 100644
--- a/vendor/ipl/validator/composer.json
+++ b/vendor/ipl/validator/composer.json
@@ -10,7 +10,7 @@
"ext-openssl": "*",
"ipl/stdlib": ">=0.12.0",
"ipl/i18n": ">=0.2.0",
- "psr/http-message": "~1.0"
+ "psr/http-message": "^1.1"
},
"autoload": {
"psr-4": {
@@ -23,6 +23,8 @@
}
},
"require-dev": {
- "guzzlehttp/psr7": "^1"
+ "guzzlehttp/psr7": "^1",
+ "ipl/stdlib": "dev-main",
+ "ipl/i18n": "dev-main"
}
}
diff --git a/vendor/ipl/validator/src/BetweenValidator.php b/vendor/ipl/validator/src/BetweenValidator.php
index 3d7faaf..c8dc026 100644
--- a/vendor/ipl/validator/src/BetweenValidator.php
+++ b/vendor/ipl/validator/src/BetweenValidator.php
@@ -12,10 +12,10 @@ class BetweenValidator extends BaseValidator
{
use Translation;
- /** @var mixed Min value */
+ /** @var int|float Min value */
protected $min;
- /** @var mixed Max value */
+ /** @var int|float Max value */
protected $max;
/**
@@ -33,14 +33,14 @@ class BetweenValidator extends BaseValidator
*
* Required options:
*
- * - min: (scalar) Minimum border
- * - max: (scalar) Maximum border
+ * - min: (int|float) Minimum border
+ * - max: (int|float) Maximum border
*
* Optional options:
*
* - inclusive: (bool) Whether inclusive border values, default true
*
- * @param array $options
+ * @param array{min: int|float, max: int|float, inclusive?: bool} $options
*
* @throws Exception When required option is missing
*/
@@ -58,7 +58,7 @@ class BetweenValidator extends BaseValidator
/**
* Return the min option
*
- * @return mixed
+ * @return int|float
*/
public function getMin()
{
@@ -68,7 +68,7 @@ class BetweenValidator extends BaseValidator
/**
* Set the min option
*
- * @param mixed $min
+ * @param int|float $min
*
* @return $this
*/
@@ -82,7 +82,7 @@ class BetweenValidator extends BaseValidator
/**
* Return the max option
*
- * @return mixed
+ * @return int|float
*/
public function getMax()
{
@@ -92,7 +92,7 @@ class BetweenValidator extends BaseValidator
/**
* Set the max option
*
- * @param mixed $max
+ * @param int|float $max
*
* @return $this
*/
@@ -120,14 +120,19 @@ class BetweenValidator extends BaseValidator
*
* @return $this
*/
- public function setInclusive($inclusive = true): self
+ public function setInclusive(bool $inclusive = true): self
{
- $this->inclusive = (bool) $inclusive;
+ $this->inclusive = $inclusive;
return $this;
}
- public function isValid($value)
+ /**
+ * @param int|float $value
+ *
+ * @return bool
+ */
+ public function isValid($value): bool
{
// Multiple isValid() calls must not stack validation messages
$this->clearMessages();
diff --git a/vendor/ipl/validator/src/CallbackValidator.php b/vendor/ipl/validator/src/CallbackValidator.php
index 611a45e..29b8e7f 100644
--- a/vendor/ipl/validator/src/CallbackValidator.php
+++ b/vendor/ipl/validator/src/CallbackValidator.php
@@ -35,7 +35,7 @@ class CallbackValidator extends BaseValidator
$this->callback = $callback;
}
- public function isValid($value)
+ public function isValid($value): bool
{
// Multiple isValid() calls must not stack validation messages
$this->clearMessages();
diff --git a/vendor/ipl/validator/src/CidrValidator.php b/vendor/ipl/validator/src/CidrValidator.php
index 32c1162..248c589 100644
--- a/vendor/ipl/validator/src/CidrValidator.php
+++ b/vendor/ipl/validator/src/CidrValidator.php
@@ -12,6 +12,10 @@ class CidrValidator extends BaseValidator
{
use Translation;
+ /**
+ * @param string $value
+ * @return bool
+ */
public function isValid($value): bool
{
$this->clearMessages();
diff --git a/vendor/ipl/validator/src/DateTimeValidator.php b/vendor/ipl/validator/src/DateTimeValidator.php
index 1e35d61..602724b 100644
--- a/vendor/ipl/validator/src/DateTimeValidator.php
+++ b/vendor/ipl/validator/src/DateTimeValidator.php
@@ -23,9 +23,9 @@ class DateTimeValidator extends BaseValidator
*
* @param bool $local
*/
- public function __construct($local = true)
+ public function __construct(bool $local = true)
{
- $this->local = (bool) $local;
+ $this->local = $local;
}
/**
@@ -35,7 +35,7 @@ class DateTimeValidator extends BaseValidator
*
* @return bool
*/
- public function isValid($value)
+ public function isValid($value): bool
{
// Multiple isValid() calls must not stack validation messages
$this->clearMessages();
diff --git a/vendor/ipl/validator/src/DeferredInArrayValidator.php b/vendor/ipl/validator/src/DeferredInArrayValidator.php
index 55b9b83..fa0ba5d 100644
--- a/vendor/ipl/validator/src/DeferredInArrayValidator.php
+++ b/vendor/ipl/validator/src/DeferredInArrayValidator.php
@@ -15,7 +15,7 @@ class DeferredInArrayValidator extends InArrayValidator
*
* **Required parameter:**
*
- * - `callback`: (`callable`) The callback to create haystack
+ * - `callback`: (`callable`) The callback to create the haystack
*
* **Optional parameter:**
*
@@ -23,8 +23,8 @@ class DeferredInArrayValidator extends InArrayValidator
*
* * `strict`: (`bool`) Whether the types of the needle in the haystack should also match, default `false`
*
- * @param callable $callback Validation callback
- * @param array $options
+ * @param callable $callback The callback to create the haystack
+ * @param array{haystack?: mixed[], strict?: bool} $options
*/
public function __construct(callable $callback, array $options = [])
{
diff --git a/vendor/ipl/validator/src/EmailAddressValidator.php b/vendor/ipl/validator/src/EmailAddressValidator.php
index 52c3697..e9dc2a7 100644
--- a/vendor/ipl/validator/src/EmailAddressValidator.php
+++ b/vendor/ipl/validator/src/EmailAddressValidator.php
@@ -40,7 +40,7 @@ class EmailAddressValidator extends BaseValidator
* 'mx' => If an MX check should be enabled, boolean
* 'deep' => If a deep MX check should be enabled, boolean
*
- * @param array $options
+ * @param array{max?: bool, deep?: bool} $options
*
* @throws Exception
*/
@@ -266,7 +266,8 @@ class EmailAddressValidator extends BaseValidator
//decode IDN domain name
$decodedHostname = idn_to_ascii($hostname, 0, INTL_IDNA_VARIANT_UTS46);
- $result = getmxrr($decodedHostname, $mxHosts);
+ $result = $decodedHostname && getmxrr($decodedHostname, $mxHosts);
+
if (! $result) {
$this->addMessage(sprintf(
$this->translate("'%s' does not appear to have a valid MX record for the email address '%s'"),
diff --git a/vendor/ipl/validator/src/FileValidator.php b/vendor/ipl/validator/src/FileValidator.php
index 8c5b90e..bc435cc 100644
--- a/vendor/ipl/validator/src/FileValidator.php
+++ b/vendor/ipl/validator/src/FileValidator.php
@@ -34,6 +34,8 @@ class FileValidator extends BaseValidator
* - maxSize: (int) Maximum allowed file size, by default no limit
* - maxFileNameLength: (int) Maximum allowed file name length, by default no limit
* - mimeType: (array) Allowed mime types, by default no restriction
+ *
+ * @param array{minSize?: int, maxSize?: int, maxFileNameLength?: int, mimeType?: string[]} $options
*/
public function __construct(array $options = [])
{
@@ -160,7 +162,11 @@ class FileValidator extends BaseValidator
return $this;
}
- public function isValid($value)
+ /**
+ * @param UploadedFileInterface|UploadedFileInterface[] $value
+ * @return bool
+ */
+ public function isValid($value): bool
{
// Multiple isValid() calls must not stack validation messages
$this->clearMessages();
@@ -185,7 +191,7 @@ class FileValidator extends BaseValidator
if ($this->getMaxSize() && $file->getSize() > $this->getMaxSize()) {
$this->addMessage(sprintf(
$this->translate('File %s is bigger than the allowed maximum size of %d'),
- $file->getClientFileName(),
+ $file->getClientFilename(),
$this->getMaxSize()
));
@@ -195,7 +201,7 @@ class FileValidator extends BaseValidator
if ($this->getMinSize() && $file->getSize() < $this->getMinSize()) {
$this->addMessage(sprintf(
$this->translate('File %s is smaller than the minimum required size of %d'),
- $file->getClientFileName(),
+ $file->getClientFilename(),
$this->getMinSize()
));
@@ -205,7 +211,7 @@ class FileValidator extends BaseValidator
if ($this->getMaxFileNameLength()) {
$strValidator = new StringLengthValidator(['max' => $this->getMaxFileNameLength()]);
- if (! $strValidator->isValid($file->getClientFilename())) {
+ if (! $strValidator->isValid($file->getClientFilename() ?? '')) {
$this->addMessage(sprintf(
$this->translate('File name is longer than the allowed length of %d characters.'),
$this->maxFileNameLength
@@ -217,26 +223,29 @@ class FileValidator extends BaseValidator
if (! empty($this->getAllowedMimeTypes())) {
$hasAllowedMimeType = false;
- foreach ($this->getAllowedMimeTypes() as $type) {
- $fileMimetype = $file->getClientMediaType();
- if (($pos = strpos($type, '/*')) !== false) { // image/*
- $typePrefix = substr($type, 0, $pos);
- if (Str::startsWith($fileMimetype, $typePrefix)) {
+ $fileMimetype = $file->getClientMediaType();
+
+ if ($fileMimetype) {
+ foreach ($this->getAllowedMimeTypes() as $type) {
+ if (($pos = strpos($type, '/*')) !== false) { // image/*
+ $typePrefix = substr($type, 0, $pos);
+ if (Str::startsWith($fileMimetype, $typePrefix)) {
+ $hasAllowedMimeType = true;
+ break;
+ }
+ } elseif ($fileMimetype === $type) { // image/png
$hasAllowedMimeType = true;
break;
}
- } elseif ($fileMimetype === $type) { // image/png
- $hasAllowedMimeType = true;
- break;
}
}
if (! $hasAllowedMimeType) {
$this->addMessage(sprintf(
$this->translate('File %s is of type %s. Only %s allowed.'),
- $file->getClientFileName(),
+ $file->getClientFilename(),
$file->getClientMediaType(),
- implode(', ', $this->allowedMimeTypes)
+ implode(', ', $this->allowedMimeTypes ?? [])
));
$isValid = false;
diff --git a/vendor/ipl/validator/src/GreaterThanValidator.php b/vendor/ipl/validator/src/GreaterThanValidator.php
index e5de3d0..177fa42 100644
--- a/vendor/ipl/validator/src/GreaterThanValidator.php
+++ b/vendor/ipl/validator/src/GreaterThanValidator.php
@@ -11,14 +11,16 @@ class GreaterThanValidator extends BaseValidator
{
use Translation;
- /** @var mixed Comparison value for greater than */
+ /** @var int|float Comparison value for greater than */
protected $min;
/**
* Create a new GreaterThanValidator
*
* Optional options:
- * - min: (scalar) Comparison value for greater than, default 0
+ * - min: (int|float) Comparison value for greater than, default 0
+ *
+ * @param array{min?: int|float} $options
*/
public function __construct(array $options = [])
{
@@ -28,7 +30,7 @@ class GreaterThanValidator extends BaseValidator
/**
* Get the min option
*
- * @return mixed
+ * @return int|float
*/
public function getMin()
{
@@ -38,7 +40,7 @@ class GreaterThanValidator extends BaseValidator
/**
* Set the min option
*
- * @param mixed $min
+ * @param int|float $min
*
* @return $this
*/
@@ -49,7 +51,12 @@ class GreaterThanValidator extends BaseValidator
return $this;
}
- public function isValid($value)
+ /**
+ * @param int|float $value
+ *
+ * @return bool
+ */
+ public function isValid($value): bool
{
// Multiple isValid() calls must not stack validation messages
$this->clearMessages();
diff --git a/vendor/ipl/validator/src/HostnameValidator.php b/vendor/ipl/validator/src/HostnameValidator.php
index 3bb9b66..8c658d0 100644
--- a/vendor/ipl/validator/src/HostnameValidator.php
+++ b/vendor/ipl/validator/src/HostnameValidator.php
@@ -18,7 +18,7 @@ class HostnameValidator extends BaseValidator
*
* @return boolean
*/
- public function isValid($value)
+ public function isValid($value): bool
{
$this->clearMessages();
@@ -26,7 +26,7 @@ class HostnameValidator extends BaseValidator
if (filter_var($asciiHostname, FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME) === false) {
$this->addMessage(sprintf(
$this->translate("%s is not a valid host name."),
- $value ?? ''
+ $value
));
return false;
diff --git a/vendor/ipl/validator/src/InArrayValidator.php b/vendor/ipl/validator/src/InArrayValidator.php
index f8c18ef..f3e67e7 100644
--- a/vendor/ipl/validator/src/InArrayValidator.php
+++ b/vendor/ipl/validator/src/InArrayValidator.php
@@ -11,7 +11,7 @@ class InArrayValidator extends BaseValidator
{
use Translation;
- /** @var array The array */
+ /** @var ?mixed[] The array */
protected $haystack;
/** @var bool Whether the types of the needle in the haystack should also match */
@@ -25,7 +25,7 @@ class InArrayValidator extends BaseValidator
* * `haystack`: (`array`) The array
* * `strict`: (`bool`) Whether the types of the needle in the haystack should also match, default `false`
*
- * @param array $options
+ * @param array{haystack?: mixed[], strict?: bool} $options
*/
public function __construct(array $options = [])
{
@@ -39,7 +39,7 @@ class InArrayValidator extends BaseValidator
/**
* Get the haystack
*
- * @return array
+ * @return mixed[]
*/
public function getHaystack(): array
{
@@ -49,7 +49,7 @@ class InArrayValidator extends BaseValidator
/**
* Set the haystack
*
- * @param array $haystack
+ * @param mixed[] $haystack
*
* @return $this
*/
@@ -84,7 +84,7 @@ class InArrayValidator extends BaseValidator
return $this;
}
- public function isValid($value)
+ public function isValid($value): bool
{
// Multiple isValid() calls must not stack validation messages
$this->clearMessages();
@@ -110,9 +110,9 @@ class InArrayValidator extends BaseValidator
/**
* Get the values from the specified array that are not present in the haystack
*
- * @param array $values
+ * @param mixed[] $values
*
- * @return array Values not found in the haystack
+ * @return mixed[] Values not found in the haystack
*/
protected function findInvalid(array $values = []): array
{
diff --git a/vendor/ipl/validator/src/LessThanValidator.php b/vendor/ipl/validator/src/LessThanValidator.php
index 68e3daf..db80e1a 100644
--- a/vendor/ipl/validator/src/LessThanValidator.php
+++ b/vendor/ipl/validator/src/LessThanValidator.php
@@ -11,14 +11,16 @@ class LessThanValidator extends BaseValidator
{
use Translation;
- /** @var mixed Comparison value for less than */
+ /** @var int|float Comparison value for less than */
protected $max;
/**
* Create a new LessThanValidator
*
* Optional options:
- * - max: (int) Comparison value for less than, default 0
+ * - max: (int|float) Comparison value for less than, default 0
+ *
+ * @param array{max?: int|float} $options
*/
public function __construct(array $options = [])
{
@@ -28,7 +30,7 @@ class LessThanValidator extends BaseValidator
/**
* Get the max option
*
- * @return mixed
+ * @return int|float
*/
public function getMax()
{
@@ -38,7 +40,7 @@ class LessThanValidator extends BaseValidator
/**
* Set the max option
*
- * @param mixed $max
+ * @param int|float $max
*
* @return $this
*/
@@ -49,7 +51,12 @@ class LessThanValidator extends BaseValidator
return $this;
}
- public function isValid($value)
+ /**
+ * @param int|float $value
+ *
+ * @return bool
+ */
+ public function isValid($value): bool
{
// Multiple isValid() calls must not stack validation messages
$this->clearMessages();
diff --git a/vendor/ipl/validator/src/PrivateKeyValidator.php b/vendor/ipl/validator/src/PrivateKeyValidator.php
index b629398..a207170 100644
--- a/vendor/ipl/validator/src/PrivateKeyValidator.php
+++ b/vendor/ipl/validator/src/PrivateKeyValidator.php
@@ -11,7 +11,12 @@ class PrivateKeyValidator extends BaseValidator
{
use Translation;
- public function isValid($value)
+ /**
+ * @param string $value
+ *
+ * @return bool
+ */
+ public function isValid($value): bool
{
// Multiple isValid() calls must not stack validation messages
$this->clearMessages();
diff --git a/vendor/ipl/validator/src/StringLengthValidator.php b/vendor/ipl/validator/src/StringLengthValidator.php
index 57df1eb..d4dd44b 100644
--- a/vendor/ipl/validator/src/StringLengthValidator.php
+++ b/vendor/ipl/validator/src/StringLengthValidator.php
@@ -13,10 +13,10 @@ class StringLengthValidator extends BaseValidator
{
use Translation;
- /** @var mixed Minimum required length */
+ /** @var int Minimum required length */
protected $min;
- /** @var mixed Maximum required length */
+ /** @var ?int Maximum required length */
protected $max;
/** @var ?string Encoding to use */
@@ -26,9 +26,11 @@ class StringLengthValidator extends BaseValidator
* Create a new StringLengthValidator
*
* Optional options:
- * - min: (scalar) Minimum required string length, default 0
- * - max: (scalar) Maximum required string length, default null
- * - encoding: (string) Encoding type, default null
+ * - min: (int) Minimum required string length, default 0
+ * - max: (int) Maximum required string length, default none
+ * - encoding: (string) Encoding type, default none
+ *
+ * @param array{min?: int, max?: int, encoding?: string} $options
*/
public function __construct(array $options = [])
{
@@ -41,9 +43,9 @@ class StringLengthValidator extends BaseValidator
/**
* Get the minimum required string length
*
- * @return mixed
+ * @return int
*/
- public function getMin()
+ public function getMin(): int
{
return $this->min;
}
@@ -51,13 +53,13 @@ class StringLengthValidator extends BaseValidator
/**
* Set the minimum required string length
*
- * @param mixed $min
+ * @param int $min
*
* @return $this
*
* @throws LogicException When the $min is greater than the $max value
*/
- public function setMin($min): self
+ public function setMin(int $min): self
{
if ($this->getMax() !== null && $min > $this->getMax()) {
throw new LogicException(
@@ -77,9 +79,9 @@ class StringLengthValidator extends BaseValidator
/**
* Get the maximum required string length
*
- * @return mixed
+ * @return ?int
*/
- public function getMax()
+ public function getMax(): ?int
{
return $this->max;
}
@@ -87,13 +89,13 @@ class StringLengthValidator extends BaseValidator
/**
* Set the minimum required string length
*
- * @param mixed $max
+ * @param ?int $max
*
* @return $this
*
* @throws LogicException When the $min is greater than the $max value
*/
- public function setMax($max): self
+ public function setMax(?int $max): self
{
if ($max !== null && $this->getMin() > $max) {
throw new LogicException(
@@ -143,7 +145,12 @@ class StringLengthValidator extends BaseValidator
return $this;
}
- public function isValid($value)
+ /**
+ * @param string $value
+ *
+ * @return bool
+ */
+ public function isValid($value): bool
{
// Multiple isValid() calls must not stack validation messages
$this->clearMessages();
diff --git a/vendor/ipl/validator/src/ValidatorChain.php b/vendor/ipl/validator/src/ValidatorChain.php
index 2860a12..8f0b9f3 100644
--- a/vendor/ipl/validator/src/ValidatorChain.php
+++ b/vendor/ipl/validator/src/ValidatorChain.php
@@ -15,6 +15,7 @@ use UnexpectedValueException;
use function ipl\Stdlib\get_php_type;
+/** @implements IteratorAggregate */
class ValidatorChain implements Countable, IteratorAggregate, Validator
{
use Messages;
@@ -23,10 +24,10 @@ class ValidatorChain implements Countable, IteratorAggregate, Validator
/** Default priority at which validators are added */
const DEFAULT_PRIORITY = 1;
- /** @var PriorityQueue Validator chain */
+ /** @var PriorityQueue Validator chain */
protected $validators;
- /** @var SplObjectStorage Validators that break the chain on failure */
+ /** @var SplObjectStorage Validators that break the chain on failure */
protected $validatorsThatBreakTheChain;
/**
@@ -43,7 +44,7 @@ class ValidatorChain implements Countable, IteratorAggregate, Validator
/**
* Get the validators that break the chain
*
- * @return SplObjectStorage
+ * @return SplObjectStorage
*/
public function getValidatorsThatBreakTheChain()
{
@@ -76,7 +77,7 @@ class ValidatorChain implements Countable, IteratorAggregate, Validator
/**
* Add the validators from the given validator specification to the chain
*
- * @param iterable $validators
+ * @param static|Traversable $validators
*
* @return $this
*
@@ -149,7 +150,7 @@ class ValidatorChain implements Countable, IteratorAggregate, Validator
*
* @return $this
*/
- public function addValidatorLoader($namespace, $postfix = null)
+ public function addValidatorLoader($namespace, $postfix = '')
{
$this->addPluginLoader('validator', $namespace, $postfix);
@@ -221,6 +222,10 @@ class ValidatorChain implements Countable, IteratorAggregate, Validator
{
$validatorsThatBreakTheChain = $validatorChain->getValidatorsThatBreakTheChain();
+ /**
+ * @var int $priority
+ * @var Validator $validator
+ */
foreach ($validatorChain->validators->yieldAll() as $priority => $validator) {
$this->add($validator, $validatorsThatBreakTheChain->contains($validator), $priority);
}
@@ -236,11 +241,14 @@ class ValidatorChain implements Countable, IteratorAggregate, Validator
/**
* Export the chain as array
*
- * @return array
+ * @return Validator[]
*/
public function toArray()
{
- return array_values(iterator_to_array($this));
+ /** @var Validator[] $validators */
+ $validators = iterator_to_array($this);
+
+ return array_values($validators);
}
public function count(): int
@@ -251,7 +259,7 @@ class ValidatorChain implements Countable, IteratorAggregate, Validator
/**
* Get an iterator for traversing the validators
*
- * @return Validator[]|PriorityQueue
+ * @return PriorityQueue
*/
public function getIterator(): Traversable
{
@@ -259,7 +267,7 @@ class ValidatorChain implements Countable, IteratorAggregate, Validator
return clone $this->validators;
}
- public function isValid($value)
+ public function isValid($value): bool
{
$this->clearMessages();
diff --git a/vendor/ipl/validator/src/X509CertValidator.php b/vendor/ipl/validator/src/X509CertValidator.php
index 7dfc4f7..0fc9677 100644
--- a/vendor/ipl/validator/src/X509CertValidator.php
+++ b/vendor/ipl/validator/src/X509CertValidator.php
@@ -11,7 +11,11 @@ class X509CertValidator extends BaseValidator
{
use Translation;
- public function isValid($value)
+ /**
+ * @param String $value
+ * @return bool
+ */
+ public function isValid($value): bool
{
// Multiple isValid() calls must not stack validation messages
$this->clearMessages();
diff --git a/vendor/ipl/web/composer.json b/vendor/ipl/web/composer.json
index 642039e..1534baa 100644
--- a/vendor/ipl/web/composer.json
+++ b/vendor/ipl/web/composer.json
@@ -17,10 +17,10 @@
}
},
"require": {
- "php": ">=7.2",
+ "php": ">=8.2",
"ext-json": "*",
"psr/http-message": "^1.1",
- "ipl/html": ">=0.8.0",
+ "ipl/html": ">=0.9.0",
"ipl/i18n": ">=0.2.0",
"ipl/orm": ">=0.5.2",
"ipl/scheduler": ">=0.1.0",
diff --git a/vendor/ipl/web/src/Common/BaseItemList.php b/vendor/ipl/web/src/Common/BaseItemList.php
index 8320d1c..dc7091d 100644
--- a/vendor/ipl/web/src/Common/BaseItemList.php
+++ b/vendor/ipl/web/src/Common/BaseItemList.php
@@ -7,9 +7,12 @@ use ipl\Html\BaseHtmlElement;
use ipl\Orm\ResultSet;
use ipl\Stdlib\BaseFilter;
use ipl\Web\Widget\EmptyStateBar;
+use ipl\Web\Widget\ItemList;
/**
* Base class for item lists
+ *
+ * @deprecated Use {@see ItemList} instead
*/
abstract class BaseItemList extends BaseHtmlElement
{
@@ -33,6 +36,9 @@ abstract class BaseItemList extends BaseHtmlElement
protected $tag = 'ul';
+ /** @var ?string Message to show if the list is empty */
+ protected $emptyStateMessage;
+
/**
* Create a new item list
*
@@ -62,12 +68,52 @@ abstract class BaseItemList extends BaseHtmlElement
{
}
+ /**
+ * Create a list item for the given data
+ *
+ * @param object $data
+ *
+ * @return BaseListItem|BaseTableRowItem
+ */
+ protected function createListItem(object $data)
+ {
+ $className = $this->getItemClass();
+
+ return new $className($data, $this);
+ }
+
+ /**
+ * Get message to show if the list is empty
+ *
+ * @return string
+ */
+ public function getEmptyStateMessage(): string
+ {
+ if ($this->emptyStateMessage === null) {
+ return t('No items found.');
+ }
+
+ return $this->emptyStateMessage;
+ }
+
+ /**
+ * Set message to show if the list is empty
+ *
+ * @param string $message
+ *
+ * @return $this
+ */
+ public function setEmptyStateMessage(string $message): self
+ {
+ $this->emptyStateMessage = $message;
+
+ return $this;
+ }
+
protected function assemble(): void
{
- $itemClass = $this->getItemClass();
foreach ($this->data as $data) {
- /** @var BaseListItem|BaseTableRowItem $item */
- $item = new $itemClass($data, $this);
+ $item = $this->createListItem($data);
$this->emit(self::BEFORE_ITEM_ADD, [$item, $data]);
$this->addHtml($item);
$this->emit(self::ON_ITEM_ADD, [$item, $data]);
@@ -75,7 +121,7 @@ abstract class BaseItemList extends BaseHtmlElement
if ($this->isEmpty()) {
$this->setTag('div');
- $this->addHtml(new EmptyStateBar(t('No items found.')));
+ $this->addHtml(new EmptyStateBar($this->getEmptyStateMessage()));
}
}
}
diff --git a/vendor/ipl/web/src/Common/BaseItemTable.php b/vendor/ipl/web/src/Common/BaseItemTable.php
index f6ca212..6fd7541 100644
--- a/vendor/ipl/web/src/Common/BaseItemTable.php
+++ b/vendor/ipl/web/src/Common/BaseItemTable.php
@@ -7,9 +7,12 @@ use ipl\Html\BaseHtmlElement;
use ipl\Orm\ResultSet;
use ipl\Stdlib\BaseFilter;
use ipl\Web\Widget\EmptyStateBar;
+use ipl\Web\Widget\ItemTable;
/**
* Base class for item tables
+ *
+ * @deprecated Use {@see ItemTable} instead
*/
abstract class BaseItemTable extends BaseHtmlElement
{
diff --git a/vendor/ipl/web/src/Common/BaseListItem.php b/vendor/ipl/web/src/Common/BaseListItem.php
index cf143ee..787391e 100644
--- a/vendor/ipl/web/src/Common/BaseListItem.php
+++ b/vendor/ipl/web/src/Common/BaseListItem.php
@@ -5,14 +5,17 @@ namespace ipl\Web\Common;
use ipl\Html\Attributes;
use ipl\Html\BaseHtmlElement;
use ipl\Html\HtmlElement;
+use ipl\Web\Widget\ItemList;
/**
* Base class for list items
+ *
+ * @deprecated Use a {@see ItemList} with a dedicated {@see ItemRenderer} instead.
*/
abstract class BaseListItem extends BaseHtmlElement
{
/** @var array */
- protected $baseAttributes = ['class' => 'list-item'];
+ protected $baseAttributes = ['class' => ['list-item', 'item-layout', 'default-item-layout']];
/** @var object The associated list item */
protected $item;
diff --git a/vendor/ipl/web/src/Common/BaseOrderedItemList.php b/vendor/ipl/web/src/Common/BaseOrderedItemList.php
index c141fc5..cef5450 100644
--- a/vendor/ipl/web/src/Common/BaseOrderedItemList.php
+++ b/vendor/ipl/web/src/Common/BaseOrderedItemList.php
@@ -6,6 +6,7 @@ use ipl\Web\Widget\EmptyStateBar;
/**
* @method BaseOrderedListItem getItemClass()
+ * @deprecated Use your own implementation instead
*/
abstract class BaseOrderedItemList extends BaseItemList
{
diff --git a/vendor/ipl/web/src/Common/BaseOrderedListItem.php b/vendor/ipl/web/src/Common/BaseOrderedListItem.php
index 03b387d..e43c076 100644
--- a/vendor/ipl/web/src/Common/BaseOrderedListItem.php
+++ b/vendor/ipl/web/src/Common/BaseOrderedListItem.php
@@ -4,6 +4,7 @@ namespace ipl\Web\Common;
use LogicException;
+/** @deprecated Use your own implementation instead */
abstract class BaseOrderedListItem extends BaseListItem
{
/** @var ?int This element's position */
diff --git a/vendor/ipl/web/src/Common/BaseTableRowItem.php b/vendor/ipl/web/src/Common/BaseTableRowItem.php
index c24578f..9149a77 100644
--- a/vendor/ipl/web/src/Common/BaseTableRowItem.php
+++ b/vendor/ipl/web/src/Common/BaseTableRowItem.php
@@ -7,11 +7,13 @@ use ipl\Html\BaseHtmlElement;
use ipl\Html\Html;
use ipl\Html\HtmlDocument;
use ipl\Html\HtmlElement;
+use ipl\Web\Widget\ItemTable;
+/** @deprecated Use a {@see ItemTable} with a dedicated {@see ItemRenderer} instead. */
abstract class BaseTableRowItem extends BaseHtmlElement
{
/** @var array */
- protected $baseAttributes = ['class' => 'table-row'];
+ protected $baseAttributes = ['class' => ['table-row', 'item-layout', 'default-item-layout']];
/** @var object The associated list item */
protected $item;
diff --git a/vendor/ipl/web/src/Common/CsrfCounterMeasure.php b/vendor/ipl/web/src/Common/CsrfCounterMeasure.php
index ae2dace..5ad58df 100644
--- a/vendor/ipl/web/src/Common/CsrfCounterMeasure.php
+++ b/vendor/ipl/web/src/Common/CsrfCounterMeasure.php
@@ -8,12 +8,44 @@ use ipl\Html\FormElement\HiddenElement;
trait CsrfCounterMeasure
{
+ /** @var ?string The ID of the CSRF form element */
+ private ?string $csrfCounterMeasureId = null;
+
+ /** @var bool Whether to actually add the CSRF element to the form */
+ private bool $csrfCounterMeasureEnabled = true;
+
+ /**
+ * Set the ID for the CSRF form element
+ *
+ * @param string $id A unique ID that persists through different requests
+ *
+ * @return $this
+ */
+ public function setCsrfCounterMeasureId(string $id): static
+ {
+ $this->csrfCounterMeasureId = $id;
+
+ return $this;
+ }
+
+ /**
+ * Disable the CSRF form element
+ *
+ * @return void
+ */
+ public function disableCsrfCounterMeasure(): void
+ {
+ $this->csrfCounterMeasureEnabled = false;
+ }
+
/**
* Create a form element to countermeasure CSRF attacks
*
* @param string $uniqueId A unique ID that persists through different requests
*
* @return FormElement
+ *
+ * @deprecated Use {@see addCsrfCounterMeasure()} instead
*/
protected function createCsrfCounterMeasure($uniqueId)
{
@@ -53,4 +85,27 @@ trait CsrfCounterMeasure
return $element;
}
+
+ /**
+ * Add the CSRF form element to this form
+ *
+ * Does nothing if disabled via {@see disableCsrfCounterMeasure()}.
+ * Unless passed as argument, requires a unique ID to be set via {@see setCsrfCounterMeasureId()}.
+ *
+ * @param ?string $uniqueId A unique ID that persists through different requests
+ *
+ * @return void
+ */
+ protected function addCsrfCounterMeasure(?string $uniqueId = null): void
+ {
+ if (! $this->csrfCounterMeasureEnabled) {
+ return;
+ }
+
+ if ($uniqueId === null && $this->csrfCounterMeasureId === null) {
+ throw new Error('No CSRF counter measure ID set');
+ }
+
+ $this->addElement($this->createCsrfCounterMeasure($uniqueId ?? $this->csrfCounterMeasureId));
+ }
}
diff --git a/vendor/ipl/web/src/Common/ItemRenderer.php b/vendor/ipl/web/src/Common/ItemRenderer.php
new file mode 100644
index 0000000..015d61f
--- /dev/null
+++ b/vendor/ipl/web/src/Common/ItemRenderer.php
@@ -0,0 +1,92 @@
+ 'icinga-form icinga-controls'];
+ /** @var bool Whether to disable the legacy form decorator */
+ private bool $disableLegacyDecorator = false;
+
+ /**
+ * Apply default element decorators
+ *
+ * This method must be called before adding any elements to the form.
+ *
+ * Calling this method disables the legacy decorator.
+ *
+ * @return $this
+ */
+ public function applyDefaultElementDecorators(): static
+ {
+ $this->disableLegacyDecorator = true;
+
+ $this->addElementDecoratorLoaderPaths([
+ ['ipl\\Web\\Compat\\FormDecorator', 'Decorator']
+ ]);
+ $labelDecorator = new LabelDecorator();
+ $this->setDefaultElementDecorators([
+ $labelDecorator,
+ [
+ 'name' => 'HtmlTag',
+ 'options' => [
+ 'tag' => 'div',
+ 'class' => 'control-label-group',
+ 'condition' => function (FormElement $element): bool {
+ return ! $element instanceof FormSubmitElement
+ && (! $element instanceof HtmlElementInterface || $element->getTag() !== 'fieldset');
+ }
+ ]
+ ],
+ 'Fieldset',
+ 'Checkbox',
+ 'RenderElement',
+ 'Description',
+ [
+ 'name' => 'HtmlTag',
+ 'options' => [
+ 'tag' => 'div',
+ 'class' => 'control-group',
+ 'condition' => fn(FormElement $element): bool => ! $element instanceof FormSubmitElement
+ ]
+ ],
+ [
+ 'name' => 'HtmlTag',
+ 'options' => [
+ 'tag' => 'div',
+ 'class' => 'control-group form-controls',
+ 'condition' => fn(FormElement $element): bool => $element instanceof FormSubmitElement
+ ]
+ ],
+ ]);
+ $this->getDecorators()->addDecorator($labelDecorator);
+
+ return $this;
+ }
+
/**
* Render the content of the element to HTML
*
@@ -41,6 +105,10 @@ class CompatForm extends Form
public function hasDefaultElementDecorator()
{
+ if ($this->disableLegacyDecorator) {
+ return false;
+ }
+
if (parent::hasDefaultElementDecorator()) {
return true;
}
diff --git a/vendor/ipl/web/src/Compat/FormDecorator/CheckboxDecorator.php b/vendor/ipl/web/src/Compat/FormDecorator/CheckboxDecorator.php
new file mode 100644
index 0000000..0dfe64b
--- /dev/null
+++ b/vendor/ipl/web/src/Compat/FormDecorator/CheckboxDecorator.php
@@ -0,0 +1,52 @@
+getAttributes();
+ $elementAttrs->add('class', 'sr-only');
+
+ if (! $elementAttrs->has('id')) {
+ $elementAttrs->set('id', uniqid('checkbox_'));
+ }
+
+ $attributes = new Attributes([
+ 'class' => 'toggle-switch',
+ 'aria-hidden' => 'true',
+ 'for' => $elementAttrs->get('id')->getValue()
+ ]);
+
+ if ($elementAttrs->get('disabled')->getValue()) {
+ $attributes->add('class', 'disabled');
+ }
+
+ $formElement->prependWrapper(
+ (new HtmlDocument())->addHtml(
+ $formElement,
+ new HtmlElement(
+ 'label',
+ $attributes,
+ new HtmlElement('span', Attributes::create(['class' => 'toggle-slider']))
+ )
+ )
+ );
+ }
+}
diff --git a/vendor/ipl/web/src/Compat/FormDecorator/DescriptionDecorator.php b/vendor/ipl/web/src/Compat/FormDecorator/DescriptionDecorator.php
new file mode 100644
index 0000000..fe6b75e
--- /dev/null
+++ b/vendor/ipl/web/src/Compat/FormDecorator/DescriptionDecorator.php
@@ -0,0 +1,34 @@
+getDescription();
+ $icon = new Icon('info-circle', [
+ 'aria-hidden' => 'true',
+ 'class' => 'control-info',
+ 'role' => 'img',
+ 'title' => $description
+ ]);
+
+ return (new HtmlElement('span', content: new Text($description)))
+ ->addWrapper((new HtmlDocument())->addHtml($icon));
+ }
+}
diff --git a/vendor/ipl/web/src/Compat/FormDecorator/LabelDecorator.php b/vendor/ipl/web/src/Compat/FormDecorator/LabelDecorator.php
new file mode 100755
index 0000000..72e8d12
--- /dev/null
+++ b/vendor/ipl/web/src/Compat/FormDecorator/LabelDecorator.php
@@ -0,0 +1,74 @@
+isRequired()) {
+ $formElement->setAttribute('aria-required', 'true');
+ $requiredHint = new HtmlElement(
+ 'span',
+ Attributes::create([
+ 'class' => 'required-hint',
+ 'aria-hidden' => 'true',
+ 'title' => $this->translate('Required')
+ ]),
+ Text::create(" *")
+ );
+ $this->requiredExplanationNeeded = true;
+ $result->addHtml($requiredHint);
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * Appends an explanation of the asterisk for required fields if at least one such field exists
+ */
+ public function decorateForm(DecorationResult $result, Form $form): void
+ {
+ if ($this->requiredExplanationNeeded) {
+ $requiredExplanation = new HtmlElement(
+ 'ul',
+ Attributes::create(['class' => 'form-info',]),
+ new HtmlElement(
+ 'li',
+ null,
+ Text::create(sprintf($this->translate('%s Required field'), '*'))
+ )
+ );
+ $result->append($requiredExplanation);
+ }
+ }
+}
diff --git a/vendor/ipl/web/src/Compat/SearchControls.php b/vendor/ipl/web/src/Compat/SearchControls.php
index f6e74ab..f554473 100644
--- a/vendor/ipl/web/src/Compat/SearchControls.php
+++ b/vendor/ipl/web/src/Compat/SearchControls.php
@@ -57,9 +57,10 @@ trait SearchControls
$requestUrl = Url::fromRequest();
$preserveParams = array_pop($params) ?? [];
$redirectUrl = array_pop($params);
+ $paramsToAdd = $this->decodedParamValues($preserveParams, $requestUrl);
if ($redirectUrl !== null) {
- $redirectUrl->addParams($requestUrl->onlyWith($preserveParams)->getParams()->toArray(false));
+ $redirectUrl->addParams($paramsToAdd);
} else {
$redirectUrl = $requestUrl->onlyWith($preserveParams);
}
@@ -83,14 +84,14 @@ trait SearchControls
if (method_exists($this, 'completeAction')) {
$searchBar->setSuggestionUrl(Url::fromPath(
"$moduleName/$controllerName/complete",
- ['_disableLayout' => true, 'showCompact' => true]
+ $paramsToAdd + ['_disableLayout' => true, 'showCompact' => true]
));
}
if (method_exists($this, 'searchEditorAction')) {
$searchBar->setEditorUrl(Url::fromPath(
"$moduleName/$controllerName/search-editor"
- )->setParams($redirectUrl->getParams()));
+ )->setParams(clone $redirectUrl->getParams()));
}
$filterColumns = $this->fetchFilterColumns($query);
@@ -127,7 +128,15 @@ trait SearchControls
->on(SearchBar::ON_SENT, function (SearchBar $form) {
/** @var Url $redirectUrl */
$redirectUrl = $form->getRedirectUrl();
- $redirectUrl->setFilter($form->getFilter());
+
+ $baseFilter = $redirectUrl->getFilter();
+ if ($baseFilter && ((! $baseFilter instanceof Filter\Chain) || ! $baseFilter->isEmpty())) {
+ $filter = Filter::all($baseFilter, $form->getFilter());
+ } else {
+ $filter = $form->getFilter();
+ }
+
+ $redirectUrl->setFilter($filter);
$form->setRedirectUrl($redirectUrl);
})->on(SearchBar::ON_SUCCESS, function (SearchBar $form) {
$this->getResponse()->redirectAndExit($form->getRedirectUrl());
@@ -156,14 +165,13 @@ trait SearchControls
$redirectUrl = array_pop($params);
$moduleName = $this->getRequest()->getModuleName();
$controllerName = $this->getRequest()->getControllerName();
+ $paramsToAdd = $this->decodedParamValues($preserveParams, $requestUrl);
if ($redirectUrl !== null) {
- $redirectUrl->addParams($requestUrl->onlyWith($preserveParams)->getParams()->toArray(false));
+ $redirectUrl->addParams($paramsToAdd);
} else {
- $redirectUrl = Url::fromPath("$moduleName/$controllerName");
- if (! empty($preserveParams)) {
- $redirectUrl->setParams($requestUrl->onlyWith($preserveParams)->getParams());
- }
+ $redirectUrl = Url::fromPath("$moduleName/$controllerName")
+ ->setParams($paramsToAdd);
}
$editor = new SearchEditor();
@@ -174,7 +182,7 @@ trait SearchControls
if (method_exists($this, 'completeAction')) {
$editor->setSuggestionUrl(Url::fromPath(
"$moduleName/$controllerName/complete",
- ['_disableLayout' => true, 'showCompact' => true]
+ $paramsToAdd + ['_disableLayout' => true, 'showCompact' => true]
));
}
@@ -217,7 +225,15 @@ trait SearchControls
})->on(SearchEditor::ON_SUCCESS, function (SearchEditor $form) {
/** @var Url $redirectUrl */
$redirectUrl = $form->getRedirectUrl();
- $redirectUrl->setFilter($form->getFilter());
+
+ $baseFilter = $redirectUrl->getFilter();
+ if ($baseFilter && ((! $baseFilter instanceof Filter\Chain) || ! $baseFilter->isEmpty())) {
+ $filter = Filter::all($baseFilter, $form->getFilter());
+ } else {
+ $filter = $form->getFilter();
+ }
+
+ $redirectUrl->setFilter($filter);
$this->getResponse()
->setHeader('X-Icinga-Container', '_self')
@@ -257,4 +273,27 @@ trait SearchControls
$condition->metaData()->set('columnLabel', $label);
}
}
+
+ /**
+ * Decode the given param names from the given Url
+ *
+ * @internal This is only a helping method to prevent params being encoded multiple times in
+ * {@see SearchControls::createSearchBar()} and {@see SearchControls::createSearchEditor()}
+ * and therefore should not be used anywhere else.
+ *
+ * @return array decoded key => value pairs
+ */
+ private function decodedParamValues(array $paramNames, Url $url): array
+ {
+ $params = [];
+ foreach ($paramNames as $param) {
+ $val = $url->getParam($param);
+
+ if ($val !== null) {
+ $params[$param] = $val;
+ }
+ }
+
+ return $params;
+ }
}
diff --git a/vendor/ipl/web/src/Control/PaginationControl.php b/vendor/ipl/web/src/Control/PaginationControl.php
index e704829..85019a5 100644
--- a/vendor/ipl/web/src/Control/PaginationControl.php
+++ b/vendor/ipl/web/src/Control/PaginationControl.php
@@ -4,9 +4,13 @@ namespace ipl\Web\Control;
use ipl\Html\BaseHtmlElement;
use ipl\Html\Html;
+use ipl\Html\TemplateString;
+use ipl\Html\ValidHtml;
+use ipl\I18n\Translation;
use ipl\Stdlib\Contract\Paginatable;
use ipl\Web\Compat\CompatForm;
use ipl\Web\Url;
+use ipl\Web\Widget\ButtonLink;
use ipl\Web\Widget\Icon;
/**
@@ -17,6 +21,8 @@ use ipl\Web\Widget\Icon;
*/
class PaginationControl extends BaseHtmlElement
{
+ use Translation;
+
/** @var string Default page parameter */
public const DEFAULT_PAGE_PARAM = 'page';
@@ -29,9 +35,6 @@ class PaginationControl extends BaseHtmlElement
/** @var string Name of the URL parameter which holds the page size. If given, overrides {@link $defaultPageSize} */
protected $pageSizeParam = 'limit';
- /** @var string */
- protected $pageSpacer = '…';
-
/** @var Paginatable The pagination adapter which handles the underlying data source */
protected $paginatable;
@@ -122,6 +125,26 @@ class PaginationControl extends BaseHtmlElement
return $this;
}
+ /**
+ * Get message content to show when the list is empty
+ *
+ * @return ?ValidHtml Content is returned when given page is out of range, null otherwise
+ */
+ public function getEmptyStateMessage(): ?ValidHtml
+ {
+ $currentPage = $this->getCurrentPageNumber();
+ $pageCount = $this->getPageCount();
+ if ($pageCount && $pageCount < $currentPage) {
+ return TemplateString::create(
+ $this->translate('Page %d is out of range. {{#button}}Navigate to first page{{/button}}'),
+ $currentPage,
+ ['button' => new ButtonLink(null, $this->url->without('page'))]
+ );
+ }
+
+ return null;
+ }
+
/**
* Get the name of the URL parameter which stores the page size
*
@@ -378,12 +401,6 @@ class PaginationControl extends BaseHtmlElement
return $nextItem;
}
- /** @TODO(el): Use ipl-translation when it's ready instead */
- private function translate($message)
- {
- return $message;
- }
-
/**
* Create and return the first page item
*
@@ -460,30 +477,42 @@ class PaginationControl extends BaseHtmlElement
{
$currentPageNumber = $this->getCurrentPageNumber();
- $form = new CompatForm($this->url);
+ $form = new CompatForm();
$form->addAttributes(['class' => 'inline']);
$form->setMethod('GET');
$select = Html::tag('select', [
'name' => $this->getPageParam(),
'class' => 'autosubmit',
- 'title' => t('Go to page …')
+ 'title' => $this->translate('Go to page …')
]);
- if ($currentPageNumber === 1 || $currentPageNumber === $this->getPageCount()) {
+ $pageCount = $this->getPageCount();
+
+ if ($currentPageNumber === 1 || $currentPageNumber === $pageCount) {
$select->add(Html::tag('option', ['disabled' => '', 'selected' => ''], '…'));
}
- foreach (range(2, $this->getPageCount() - 1) as $page) {
- $option = Html::tag('option', [
- 'value' => $page
- ], $page);
+ if (2 <= $pageCount - 1) {
+ foreach (range(2, $pageCount - 1) as $page) {
+ $option = Html::tag('option', [
+ 'value' => $page
+ ], $page);
- if ($page == $currentPageNumber) {
- $option->addAttributes(['selected' => '']);
+ if ($page == $currentPageNumber) {
+ $option->addAttributes(['selected' => '']);
+ }
+
+ $select->add($option);
}
+ }
- $select->add($option);
+ if ($currentPageNumber > $pageCount) {
+ $select->add(Html::tag('option', [
+ 'value' => $currentPageNumber,
+ 'selected' => '',
+ 'disabled' => ''
+ ], $currentPageNumber));
}
$form->add($select);
diff --git a/vendor/ipl/web/src/Control/SearchBar/Suggestions.php b/vendor/ipl/web/src/Control/SearchBar/Suggestions.php
index fe4a2db..4dba21a 100644
--- a/vendor/ipl/web/src/Control/SearchBar/Suggestions.php
+++ b/vendor/ipl/web/src/Control/SearchBar/Suggestions.php
@@ -8,7 +8,6 @@ use ipl\Html\Attributes;
use ipl\Html\BaseHtmlElement;
use ipl\Html\FormattedString;
use ipl\Html\FormElement\ButtonElement;
-use ipl\Html\FormElement\InputElement;
use ipl\Html\HtmlElement;
use ipl\Html\Text;
use ipl\Stdlib\Contract\Paginatable;
@@ -126,7 +125,7 @@ abstract class Suggestions extends BaseHtmlElement
$logicalSep = [
'label' => QueryString::getRuleSymbol($filter),
'search' => QueryString::getRuleSymbol($filter),
- 'class' => 'logical_operator',
+ 'class' => 'logical-operator',
'type' => 'logical_operator'
];
@@ -137,14 +136,14 @@ abstract class Suggestions extends BaseHtmlElement
'search' => '(',
'label' => '(',
'type' => 'grouping_operator',
- 'class' => 'grouping_operator_open'
+ 'class' => 'grouping-operator-open'
];
$terms = array_merge($terms, $this->filterToTerms($child));
$terms[] = [
'search' => ')',
'label' => ')',
'type' => 'grouping_operator',
- 'class' => 'grouping_operator_close'
+ 'class' => 'grouping-operator-close'
];
} else {
/** @var Filter\Condition $child */
@@ -191,7 +190,7 @@ abstract class Suggestions extends BaseHtmlElement
$attributes['data-type'] = $this->type;
}
- $button = new ButtonElement(null, $attributes);
+ $button = new ButtonElement('', $attributes);
if (isset($this->default['type']) && $this->default['type'] === 'terms') {
$terms = $this->filterToTerms($this->default['terms']);
$list = new HtmlElement('ul', Attributes::create(['class' => 'comma-separated']));
@@ -242,11 +241,17 @@ abstract class Suggestions extends BaseHtmlElement
$data = new LimitIterator(new IteratorIterator($this->data), 0, self::DEFAULT_LIMIT);
}
+ $noDefault = null;
foreach ($data as $term => $meta) {
if (is_int($term)) {
$term = $meta;
}
+ if ($this->searchTerm) {
+ // Only the first exact match will set this to true, any other to false
+ $noDefault = $noDefault === null && $term === $this->searchTerm;
+ }
+
$attributes = [
'type' => 'button',
'tabindex' => -1,
@@ -270,7 +275,7 @@ abstract class Suggestions extends BaseHtmlElement
$attributes['data-label'] = $meta;
}
- $button = (new ButtonElement(null, $attributes))
+ $button = (new ButtonElement('', $attributes))
->setAttribute('value', $label)
->addHtml(Text::create($label));
if ($this->type === 'column' && $this->shouldShowRelationFor($term)) {
@@ -290,14 +295,6 @@ abstract class Suggestions extends BaseHtmlElement
$this->getAttributes()->add('class', 'has-more');
}
- $showDefault = true;
- if ($this->searchTerm && $this->count() === 1) {
- // The default option is only shown if the user's input does not result in an exact match
- $input = $this->getFirst('li')->getFirst('button');
- $showDefault = $input->getContent() != $this->searchTerm
- && $input->getAttributes()->get('data-search')->getValue() != $this->searchTerm;
- }
-
if ($this->type === 'column' && ! $this->isEmpty() && ! $this->getFirst('li')->getAttributes()->has('class')) {
// The column title is only added if there are any suggestions and the first item is not a title already
$this->prependHtml(new HtmlElement(
@@ -307,7 +304,7 @@ abstract class Suggestions extends BaseHtmlElement
));
}
- if ($showDefault) {
+ if (! $noDefault) {
$this->assembleDefault();
}
diff --git a/vendor/ipl/web/src/Control/SearchBar/Terms.php b/vendor/ipl/web/src/Control/SearchBar/Terms.php
index c81e336..c7a9ce8 100644
--- a/vendor/ipl/web/src/Control/SearchBar/Terms.php
+++ b/vendor/ipl/web/src/Control/SearchBar/Terms.php
@@ -81,7 +81,7 @@ class Terms extends BaseHtmlElement
if ($i > 0) {
$logicalOperator = QueryString::getRuleSymbol($filters);
$this->assembleTerm([
- 'class' => 'logical_operator',
+ 'class' => 'logical-operator',
'type' => 'logical_operator',
'search' => $logicalOperator,
'label' => $logicalOperator
@@ -110,7 +110,7 @@ class Terms extends BaseHtmlElement
if ($chain instanceof Filter\None) {
$this->assembleTerm([
- 'class' => 'logical_operator',
+ 'class' => 'logical-operator',
'type' => 'negation_operator',
'search' => '!',
'label' => '!'
@@ -119,7 +119,7 @@ class Terms extends BaseHtmlElement
if ($wrap) {
$opening = $this->assembleTerm([
- 'class' => 'grouping_operator_open',
+ 'class' => 'grouping-operator-open',
'type' => 'grouping_operator',
'search' => '(',
'label' => '('
@@ -130,7 +130,7 @@ class Terms extends BaseHtmlElement
if ($wrap) {
$closing = $this->assembleTerm([
- 'class' => 'grouping_operator_close',
+ 'class' => 'grouping-operator-close',
'type' => 'grouping_operator',
'search' => ')',
'label' => ')'
diff --git a/vendor/ipl/web/src/Control/SortControl.php b/vendor/ipl/web/src/Control/SortControl.php
index 65c2c3d..b5cabd8 100644
--- a/vendor/ipl/web/src/Control/SortControl.php
+++ b/vendor/ipl/web/src/Control/SortControl.php
@@ -7,11 +7,11 @@ use ipl\Html\Form;
use ipl\Html\FormDecorator\DivDecorator;
use ipl\Html\FormElement\ButtonElement;
use ipl\Html\HtmlElement;
+use ipl\I18n\Translation;
use ipl\Orm\Common\SortUtil;
use ipl\Orm\Query;
use ipl\Stdlib\Str;
use ipl\Web\Common\FormUid;
-use ipl\Web\Url;
use ipl\Web\Widget\Icon;
use Psr\Http\Message\ServerRequestInterface;
@@ -21,6 +21,7 @@ use Psr\Http\Message\ServerRequestInterface;
class SortControl extends Form
{
use FormUid;
+ use Translation;
/** @var string Default sort param */
public const DEFAULT_SORT_PARAM = 'sort';
@@ -30,13 +31,6 @@ class SortControl extends Form
/** @var string Name of the URL parameter which stores the sort column */
protected $sortParam = self::DEFAULT_SORT_PARAM;
- /**
- * @var Url Request URL
- * @deprecated Access {@see self::getRequest()} instead.
- * @todo Remove once cube calls {@see self::handleRequest()}.
- */
- protected $url;
-
/** @var array Possible sort columns as sort string-value pairs */
private $columns;
@@ -49,14 +43,12 @@ class SortControl extends Form
* Create a new sort control
*
* @param array $columns Possible sort columns
- * @param Url $url Request URL
*
* @internal Use {@see self::create()} instead.
*/
- private function __construct(array $columns, Url $url)
+ private function __construct(array $columns)
{
$this->setColumns($columns);
- $this->url = $url;
}
/**
@@ -73,14 +65,12 @@ class SortControl extends Form
$normalized[SortUtil::normalizeSortSpec($spec)] = $label;
}
- $self = new static($normalized, Url::fromRequest());
+ $self = new static($normalized);
$self->on(self::ON_REQUEST, function (ServerRequestInterface $request) use ($self) {
- if (! $self->hasBeenSent()) {
- // If the form is submitted by POST, handleRequest() won't access the URL, so we have to
- if (($sort = $request->getQueryParams()[$self->getSortParam()] ?? null)) {
- $self->populate([$self->getSortParam() => $sort]);
- }
+ // If the form is submitted by POST, handleRequest() won't access the URL, so we have to
+ if (($sort = $request->getQueryParams()[$self->getSortParam()] ?? null)) {
+ $self->populate([$self->getSortParam() => $sort]);
}
});
@@ -168,12 +158,7 @@ class SortControl extends Form
*/
public function getSort(): ?string
{
- if ($this->getRequest() === null) {
- $sort = $this->url->getParam($this->getSortParam(), $this->getDefault());
- } else {
- $sort = $this->getPopulatedValue($this->getSortParam(), $this->getDefault());
- }
-
+ $sort = $this->getPopulatedValue($this->getSortParam(), $this->getDefault());
if (! empty($sort)) {
$columns = $this->getColumns();
@@ -203,12 +188,6 @@ class SortControl extends Form
*/
public function apply(Query $query, $defaultSort = null): self
{
- if ($this->getRequest() === null) {
- // handleRequest() has not been called yet
- // TODO: Remove this once everything using this requires ipl v0.12.0
- $this->handleRequest(ServerRequest::fromGlobals());
- }
-
$default = $defaultSort ?? (array) $query->getModel()->getDefaultSort();
if (! empty($default)) {
$this->setDefault(SortUtil::normalizeSortSpec($default));
@@ -222,7 +201,16 @@ class SortControl extends Form
return $this;
}
- protected function assemble()
+ /**
+ * Prepare the visual representation of the sort control
+ *
+ * This is called just before rendering happens. What is being done here, doesn't influence validity in any way.
+ * So there is no need to have the result already at hand during validation. Instead, delaying it allows
+ * to influence the visual result as long as possible.
+ *
+ * @return void
+ */
+ protected function prepareContent(): void
{
$columns = $this->getColumns();
$sort = $this->getSort();
@@ -266,7 +254,7 @@ class SortControl extends Form
$this->addElement('select', $this->getSortParam(), [
'class' => 'autosubmit',
- 'label' => 'Sort By',
+ 'label' => $this->translate('Sort By'),
'options' => $columns,
'value' => $value
]);
@@ -278,16 +266,26 @@ class SortControl extends Form
$toggleButton = new ButtonElement($this->getSortParam(), [
'class' => 'control-button spinner',
- 'title' => t('Change sort direction'),
+ 'title' => $this->translate('Change sort direction'),
'type' => 'submit',
'value' => implode(',', array_merge(["{$column} {$toggleDirection}"], $sort))
]);
$toggleButton->add(new Icon($toggleIcon));
$this->addHtml($toggleButton);
+ }
+ protected function assemble()
+ {
if ($this->getMethod() === 'POST' && $this->hasAttribute('name')) {
$this->addElement($this->createUidElement());
}
}
+
+ public function renderUnwrapped()
+ {
+ $this->prepareContent();
+
+ return parent::renderUnwrapped();
+ }
}
diff --git a/vendor/ipl/web/src/FormDecorator/IcingaFormDecorator.php b/vendor/ipl/web/src/FormDecorator/IcingaFormDecorator.php
index f038931..397640d 100644
--- a/vendor/ipl/web/src/FormDecorator/IcingaFormDecorator.php
+++ b/vendor/ipl/web/src/FormDecorator/IcingaFormDecorator.php
@@ -4,6 +4,7 @@ namespace ipl\Web\FormDecorator;
use Icinga\Web\Window;
use ipl\Html\Attributes;
+use ipl\Html\Contract\FormElementDecoration;
use ipl\Html\Contract\FormSubmitElement;
use ipl\Html\FormDecorator\DivDecorator;
use ipl\Html\FormElement\CheckboxElement;
@@ -12,8 +13,13 @@ use ipl\Html\HtmlDocument;
use ipl\Html\HtmlElement;
use ipl\Html\HtmlString;
use ipl\Html\Text;
+use ipl\Web\Compat\CompatForm;
use ipl\Web\Widget\Icon;
+/**
+ * @deprecated Use {@see FormElementDecoration} decorators by calling {@see CompatForm::applyDefaultElementDecorators()}
+ * instead.
+ */
class IcingaFormDecorator extends DivDecorator
{
const SUBMIT_ELEMENT_CLASS = 'form-controls';
diff --git a/vendor/ipl/web/src/FormElement/ScheduleElement.php b/vendor/ipl/web/src/FormElement/ScheduleElement.php
index f872f49..8ef8ee7 100644
--- a/vendor/ipl/web/src/FormElement/ScheduleElement.php
+++ b/vendor/ipl/web/src/FormElement/ScheduleElement.php
@@ -16,7 +16,6 @@ use ipl\Validator\CallbackValidator;
use ipl\Web\FormElement\ScheduleElement\AnnuallyFields;
use ipl\Web\FormElement\ScheduleElement\Common\FieldsProtector;
use ipl\Web\FormElement\ScheduleElement\MonthlyFields;
-use ipl\Web\FormElement\ScheduleElement\Recurrence;
use ipl\Web\FormElement\ScheduleElement\WeeklyFields;
use LogicException;
use Psr\Http\Message\RequestInterface;
@@ -65,29 +64,9 @@ class ScheduleElement extends FieldsetElement
protected function init(): void
{
+ $this->addDefaultPluginLoader('element', 'ipl\\Web\\FormElement\\ScheduleElement', '');
+
$this->start = new DateTime();
- $this->weeklyField = new WeeklyFields('weekly-fields', [
- 'default' => $this->start->format('D'),
- 'protector' => function (string $day) {
- return $this->protectId($day);
- },
- ]);
-
- $this->monthlyFields = new MonthlyFields('monthly-fields', [
- 'default' => $this->start->format('j'),
- 'availableFields' => (int) $this->start->format('t'),
- 'protector' => function ($day) {
- return $this->protectId($day);
- }
- ]);
-
- $this->annuallyFields = new AnnuallyFields('annually-fields', [
- 'default' => $this->start->format('M'),
- 'protector' => function ($month) {
- return $this->protectId($month);
- }
- ]);
-
$this->regulars = [
RRule::MINUTELY => $this->translate('Minutely'),
@@ -108,6 +87,64 @@ class ScheduleElement extends FieldsetElement
];
}
+ /**
+ * Create and return the weekly fields element
+ *
+ * @return WeeklyFields
+ */
+ protected function weeklyField(): WeeklyFields
+ {
+ if ($this->weeklyField === null) {
+ $this->weeklyField = $this->createElement('weeklyFields', 'weekly-fields', [
+ 'default' => $this->start->format('D'),
+ 'protector' => function (string $day) {
+ return $this->protectId($day);
+ },
+ ]);
+ }
+
+ return $this->weeklyField;
+ }
+
+ /**
+ * Create and return the monthly fields element
+ *
+ * @return MonthlyFields
+ */
+ protected function monthlyFields(): MonthlyFields
+ {
+ if ($this->monthlyFields === null) {
+ $this->monthlyFields = $this->createElement('monthlyFields', 'monthly-fields', [
+ 'default' => $this->start->format('j'),
+ 'availableFields' => (int) $this->start->format('t'),
+ 'protector' => function ($day) {
+ return $this->protectId($day);
+ }
+ ]);
+ }
+
+ return $this->monthlyFields;
+ }
+
+ /**
+ * Create and return the annually fields element
+ *
+ * @return AnnuallyFields
+ */
+ protected function annuallyFields(): AnnuallyFields
+ {
+ if ($this->annuallyFields === null) {
+ $this->annuallyFields = $this->createElement('annuallyFields', 'annually-fields', [
+ 'default' => $this->start->format('M'),
+ 'protector' => function ($month) {
+ return $this->protectId($month);
+ }
+ ]);
+ }
+
+ return $this->annuallyFields;
+ }
+
/**
* Get whether this element is rendering a cron expression
*
@@ -190,9 +227,9 @@ class ScheduleElement extends FieldsetElement
$this->start = $start;
// Forward the start time update to the sub elements as well!
- $this->weeklyField->setDefault($start->format('D'));
- $this->annuallyFields->setDefault($start->format('M'));
- $this->monthlyFields
+ $this->weeklyField()->setDefault($start->format('D'));
+ $this->annuallyFields()->setDefault($start->format('M'));
+ $this->monthlyFields()
->setDefault((int) $start->format('j'))
->setAvailableFields((int) $start->format('t'));
@@ -237,16 +274,16 @@ class ScheduleElement extends FieldsetElement
break;
case RRule::WEEKLY:
- $byDay = implode(',', $this->weeklyField->getSelectedWeekDays());
+ $byDay = implode(',', $this->weeklyField()->getSelectedWeekDays());
$rule = new RRule("FREQ=WEEKLY;INTERVAL=$interval;BYDAY=$byDay");
break;
/** @noinspection PhpMissingBreakStatementInspection */
case RRule::MONTHLY:
- $runsOn = $this->monthlyFields->getValue('runsOn', MonthlyFields::RUNS_EACH);
+ $runsOn = $this->monthlyFields()->getValue('runsOn', MonthlyFields::RUNS_EACH);
if ($runsOn === MonthlyFields::RUNS_EACH) {
- $byMonth = implode(',', $this->monthlyFields->getSelectedDays());
+ $byMonth = implode(',', $this->monthlyFields()->getSelectedDays());
$rule = new RRule("FREQ=MONTHLY;INTERVAL=$interval;BYMONTHDAY=$byMonth");
@@ -256,8 +293,8 @@ class ScheduleElement extends FieldsetElement
case RRule::YEARLY:
$rule = "FREQ=MONTHLY;INTERVAL=$interval;";
if ($customFrequency === RRule::YEARLY) {
- $runsOn = $this->annuallyFields->getValue('runsOnThe', 'n');
- $month = $this->annuallyFields->getValue('month', (int) $this->start->format('m'));
+ $runsOn = $this->annuallyFields()->getValue('runsOnThe', 'n');
+ $month = $this->annuallyFields()->getValue('month', (int) $this->start->format('m'));
if (is_string($month)) {
$datetime = DateTime::createFromFormat('!M', $month);
if (! $datetime) {
@@ -275,9 +312,9 @@ class ScheduleElement extends FieldsetElement
}
}
- $element = $this->monthlyFields;
+ $element = $this->monthlyFields();
if ($customFrequency === RRule::YEARLY) {
- $element = $this->annuallyFields;
+ $element = $this->annuallyFields();
}
$runDay = $element->getValue('day', $element::$everyDay);
@@ -355,7 +392,7 @@ class ScheduleElement extends FieldsetElement
if (! $rule->getByDay() || empty($rule->getByDay())) {
$this->setFrequency(RRule::WEEKLY);
} else {
- $values['weekly-fields'] = $this->weeklyField->loadWeekDays($rule->getByDay());
+ $values['weekly-fields'] = $this->weeklyField()->loadWeekDays($rule->getByDay());
$this
->setFrequency(static::CUSTOM_EXPR)
->setCustomFrequency(RRule::WEEKLY);
@@ -369,10 +406,10 @@ class ScheduleElement extends FieldsetElement
$this->setFrequency(static::CUSTOM_EXPR);
if ($isMonthly) {
- $values['monthly-fields'] = $this->monthlyFields->loadRRule($rule);
+ $values['monthly-fields'] = $this->monthlyFields()->loadRRule($rule);
$this->setCustomFrequency(RRule::MONTHLY);
} else {
- $values['annually-fields'] = $this->annuallyFields->loadRRule($rule);
+ $values['annually-fields'] = $this->annuallyFields()->loadRRule($rule);
$this->setCustomFrequency(RRule::YEARLY);
}
} elseif ($isMonthly && $rule->getInterval() === 3) {
@@ -463,16 +500,16 @@ class ScheduleElement extends FieldsetElement
break;
case RRule::WEEKLY:
$this->assembleCommonElements();
- $this->addElement($this->weeklyField);
+ $this->addElement($this->weeklyField());
break;
case RRule::MONTHLY:
$this->assembleCommonElements();
- $this->addElement($this->monthlyFields);
+ $this->addElement($this->monthlyFields());
break;
case RRule::YEARLY:
- $this->addElement($this->annuallyFields);
+ $this->addElement($this->annuallyFields());
}
} elseif ($this->hasCronExpression()) {
$this->addElement('text', 'cron_expression', [
@@ -495,7 +532,9 @@ class ScheduleElement extends FieldsetElement
if ($this->getFrequency() !== static::NO_REPEAT && ! $this->hasCronExpression()) {
$this->addElement(
- new Recurrence('schedule-recurrences', [
+ 'recurrence',
+ 'schedule-recurrences',
+ [
'id' => $this->protectId('schedule-recurrences'),
'label' => $this->translate('Next occurrences'),
'validate' => function (): array {
@@ -511,15 +550,15 @@ class ScheduleElement extends FieldsetElement
$frequency = $this->getCustomFrequency();
switch ($frequency) {
case RRule::WEEKLY:
- $reason = current($this->weeklyField->getMessages());
+ $reason = current($this->weeklyField()->getMessages());
break;
case RRule::MONTHLY:
- $reason = current($this->monthlyFields->getMessages());
+ $reason = current($this->monthlyFields()->getMessages());
break;
default: // annually
- $reason = current($this->annuallyFields->getMessages());
+ $reason = current($this->annuallyFields()->getMessages());
break;
}
@@ -549,7 +588,7 @@ class ScheduleElement extends FieldsetElement
return $rule;
}
- ])
+ ]
);
}
}
@@ -620,7 +659,7 @@ class ScheduleElement extends FieldsetElement
&& $matches[1] === 'start'
) {
// To update the available fields/days based on the provided start time
- $partUpdates[] = $this->monthlyFields;
+ $partUpdates[] = $this->monthlyFields();
}
}
diff --git a/vendor/ipl/web/src/FormElement/ScheduleElement/AnnuallyFields.php b/vendor/ipl/web/src/FormElement/ScheduleElement/AnnuallyFields.php
index 857711a..ae0be84 100644
--- a/vendor/ipl/web/src/FormElement/ScheduleElement/AnnuallyFields.php
+++ b/vendor/ipl/web/src/FormElement/ScheduleElement/AnnuallyFields.php
@@ -46,6 +46,8 @@ class AnnuallyFields extends FieldsetElement
{
parent::init();
$this->initUtils();
+
+ $this->addDefaultPluginLoader('element', 'ipl\\Web\\FormElement\\ScheduleElement', '');
}
/**
@@ -70,7 +72,7 @@ class AnnuallyFields extends FieldsetElement
{
$this->getAttributes()->set('id', $this->protectId('annually-fields'));
- $fieldsSelector = new FieldsRadio('month', [
+ $fieldsSelector = $this->createElement('fieldsRadio', 'month', [
'class' => ['autosubmit', 'sr-only'],
'value' => $this->default,
'options' => $this->months,
@@ -79,22 +81,20 @@ class AnnuallyFields extends FieldsetElement
}
]);
$this->registerElement($fieldsSelector);
+ $this->decorate($fieldsSelector);
$runsOnThe = $this->getPopulatedValue('runsOnThe', 'n');
- $this->addElement('checkbox', 'runsOnThe', [
+ $checkbox = $this->createElement('checkbox', 'runsOnThe', [
'class' => 'autosubmit',
'value' => $runsOnThe
]);
+ $this->registerElement($checkbox);
+ $this->decorate($checkbox);
$checkboxControls = HtmlElement::create('div', ['class' => 'toggle-slider-controls']);
- $checkbox = $this->getElement('runsOnThe');
$checkbox->prependWrapper($checkboxControls);
$checkboxControls->addHtml($checkbox, HtmlElement::create('span', null, $this->translate('On the')));
- $annuallyWrapper = HtmlElement::create('div', ['class' => 'annually']);
- $checkboxControls->prependWrapper($annuallyWrapper);
- $annuallyWrapper->addHtml($fieldsSelector);
-
$notes = HtmlElement::create('div', ['class' => 'note']);
$notes->addHtml(
FormattedString::create(
@@ -103,23 +103,26 @@ class AnnuallyFields extends FieldsetElement
new Icon('arrow-right')
)
);
- $annuallyWrapper->addHtml($notes);
+ $annuallyWrapper = HtmlElement::create('div', ['class' => 'annually']);
+ $fieldsSelector->prependWrapper($annuallyWrapper);
+ $annuallyWrapper->addHtml($fieldsSelector, $notes);
+
+ $this->addHtml($fieldsSelector, $checkbox);
$enumerations = $this->createOrdinalElement();
$enumerations->getAttributes()->set('disabled', $runsOnThe === 'n');
$this->registerElement($enumerations);
+ $this->decorate($enumerations);
$selectableDays = $this->createOrdinalSelectableDays();
$selectableDays->getAttributes()->set('disabled', $runsOnThe === 'n');
$this->registerElement($selectableDays);
$ordinalWrapper = HtmlElement::create('div', ['class' => ['ordinal', 'annually']]);
- $this
- ->decorate($enumerations)
- ->addHtml($enumerations);
-
$enumerations->prependWrapper($ordinalWrapper);
$ordinalWrapper->addHtml($enumerations, $selectableDays);
+
+ $this->addHtml($enumerations);
}
protected function registerAttributeCallbacks(Attributes $attributes)
diff --git a/vendor/ipl/web/src/FormElement/ScheduleElement/MonthlyFields.php b/vendor/ipl/web/src/FormElement/ScheduleElement/MonthlyFields.php
index 26329fc..c85c460 100644
--- a/vendor/ipl/web/src/FormElement/ScheduleElement/MonthlyFields.php
+++ b/vendor/ipl/web/src/FormElement/ScheduleElement/MonthlyFields.php
@@ -108,7 +108,8 @@ class MonthlyFields extends FieldsetElement
foreach (range(1, $this->availableFields) as $day) {
$checkbox = $this->createElement('checkbox', "day$day", [
'class' => ['autosubmit', 'sr-only'],
- 'value' => $day === $this->default && $runsOn === static::RUNS_EACH
+ 'value' => $day === $this->default && $runsOn === static::RUNS_EACH,
+ 'decorators' => []
]);
$this->registerElement($checkbox);
diff --git a/vendor/ipl/web/src/FormElement/ScheduleElement/WeeklyFields.php b/vendor/ipl/web/src/FormElement/ScheduleElement/WeeklyFields.php
index 01933ca..47ddd41 100644
--- a/vendor/ipl/web/src/FormElement/ScheduleElement/WeeklyFields.php
+++ b/vendor/ipl/web/src/FormElement/ScheduleElement/WeeklyFields.php
@@ -102,7 +102,8 @@ class WeeklyFields extends FieldsetElement
foreach ($this->weekdays as $day => $value) {
$checkbox = $this->createElement('checkbox', $day, [
'class' => ['autosubmit', 'sr-only'],
- 'value' => $day === $this->default
+ 'value' => $day === $this->default,
+ 'decorators' => []
]);
$this->registerElement($checkbox);
diff --git a/vendor/ipl/web/src/FormElement/SearchSuggestions.php b/vendor/ipl/web/src/FormElement/SearchSuggestions.php
new file mode 100644
index 0000000..0218d43
--- /dev/null
+++ b/vendor/ipl/web/src/FormElement/SearchSuggestions.php
@@ -0,0 +1,279 @@
+provider = $provider;
+ }
+
+ /**
+ * Set a callback to identify groups for terms delivered by the provider
+ *
+ * The callback must return a string which is used as label for the group.
+ * Its interface is: `function (array $data): string`
+ *
+ * @param callable $callback
+ *
+ * @return $this
+ */
+ public function setGroupingCallback(callable $callback): self
+ {
+ $this->groupingCallback = $callback;
+
+ return $this;
+ }
+
+ /**
+ * Get the callback used to identify groups for terms delivered by the provider
+ *
+ * @return ?callable
+ */
+ public function getGroupingCallback(): ?callable
+ {
+ return $this->groupingCallback;
+ }
+
+ /**
+ * Set the search term (can contain `*` wildcards)
+ *
+ * @param string $term
+ *
+ * @return $this
+ */
+ public function setSearchTerm(string $term): self
+ {
+ $this->searchTerm = $term;
+ $this->setSearchPattern(
+ '/' . str_replace(
+ '\\000',
+ '.*',
+ preg_quote(
+ str_replace(
+ '*',
+ "\0",
+ $term
+ ),
+ '/'
+ )
+ ) . '/i'
+ );
+
+ return $this;
+ }
+
+ /**
+ * Get the search term
+ *
+ * @return ?string
+ */
+ public function getSearchTerm(): ?string
+ {
+ return $this->searchTerm;
+ }
+
+ /**
+ * Set the search pattern used by {@see matchSearch}
+ *
+ * @param string $pattern
+ *
+ * @return $this
+ */
+ protected function setSearchPattern(string $pattern): self
+ {
+ $this->searchPattern = $pattern;
+
+ return $this;
+ }
+
+ /**
+ * Set the original search value
+ *
+ * The one without automatically added wildcards.
+ *
+ * @param string $term
+ *
+ * @return $this
+ */
+ public function setOriginalSearchValue(string $term): self
+ {
+ $this->originalValue = $term;
+
+ return $this;
+ }
+
+ /**
+ * Get the original search value
+ *
+ * @return ?string
+ */
+ public function getOriginalSearchValue(): ?string
+ {
+ return $this->originalValue;
+ }
+
+ /**
+ * Set the terms to exclude in the suggestion list
+ *
+ * @param string[] $terms
+ *
+ * @return $this
+ */
+ public function setExcludeTerms(array $terms): self
+ {
+ $this->excludeTerms = $terms;
+
+ return $this;
+ }
+
+ /**
+ * Get the terms to exclude in the suggestion list
+ *
+ * @return string[]
+ */
+ public function getExcludeTerms(): array
+ {
+ return $this->excludeTerms;
+ }
+
+ /**
+ * Match the given search term against the users search
+ *
+ * @param string $term
+ *
+ * @return bool Whether the search matches or not
+ */
+ public function matchSearch(string $term): bool
+ {
+ if (! $this->searchPattern || $this->searchPattern === '.*') {
+ return true;
+ }
+
+ return (bool) preg_match($this->searchPattern, $term);
+ }
+
+ /**
+ * Load suggestions as requested by the client
+ *
+ * @param ServerRequestInterface $request
+ *
+ * @return $this
+ */
+ public function forRequest(ServerRequestInterface $request): self
+ {
+ if ($request->getMethod() !== 'POST') {
+ return $this;
+ }
+
+ /** @var array> $requestData */
+ $requestData = json_decode($request->getBody()->read(8192), true);
+ if (empty($requestData)) {
+ return $this;
+ }
+
+ $this->setSearchTerm($requestData['term']['label']);
+ $this->setOriginalSearchValue($requestData['term']['search']);
+ $this->setExcludeTerms($requestData['exclude'] ?? []);
+
+ return $this;
+ }
+
+ protected function assemble(): void
+ {
+ $groupingCallback = $this->getGroupingCallback();
+ if ($groupingCallback) {
+ $provider = yield_groups($this->provider, $groupingCallback);
+ } else {
+ $provider = [null => $this->provider];
+ }
+
+ /** @var iterable>> $provider */
+ foreach ($provider as $group => $suggestions) {
+ if ($group) {
+ $this->addHtml(
+ new HtmlElement(
+ 'li',
+ Attributes::create(['class' => 'suggestion-title']),
+ Text::create($group)
+ )
+ );
+ }
+
+ foreach ($suggestions as $data) {
+ $attributes = [
+ 'type' => 'button',
+ 'value' => $data['label'] ?? $data['search']
+ ];
+ foreach ($data as $name => $value) {
+ $attributes["data-$name"] = $value;
+ }
+
+ $this->addHtml(
+ new HtmlElement(
+ 'li',
+ null,
+ new HtmlElement(
+ 'input',
+ Attributes::create($attributes)
+ )
+ )
+ );
+ }
+ }
+
+ if ($this->isEmpty()) {
+ $this->addHtml(new HtmlElement(
+ 'li',
+ Attributes::create(['class' => 'nothing-to-suggest']),
+ new HtmlElement('em', null, Text::create($this->translate('Nothing to suggest')))
+ ));
+ }
+ }
+}
diff --git a/vendor/ipl/web/src/FormElement/SuggestionElement.php b/vendor/ipl/web/src/FormElement/SuggestionElement.php
new file mode 100644
index 0000000..83f3d45
--- /dev/null
+++ b/vendor/ipl/web/src/FormElement/SuggestionElement.php
@@ -0,0 +1,87 @@
+ 'off',
+ 'class' => 'suggestion-element',
+ 'data-enrichment-type' => 'completion'
+ ];
+
+ /** @var Url URL to fetch suggestions from */
+ protected Url $suggestionsUrl;
+
+ /**
+ * Create a new SuggestionElement
+ *
+ * @param string $name Name of the form element
+ * @param Url $suggestionsUrl URL to fetch suggestions from
+ * @param ?(array|Attributes) $attributes Attributes of the form element
+ */
+ public function __construct(string $name, Url $suggestionsUrl, array|Attributes $attributes = null)
+ {
+ parent::__construct($name, $attributes);
+
+ $this->setSuggestionsUrl($suggestionsUrl);
+ }
+
+ /**
+ * Get the URL to fetch suggestions from
+ *
+ * @return Url
+ */
+ public function getSuggestionsUrl(): Url
+ {
+ return $this->suggestionsUrl;
+ }
+
+ /**
+ * Set the URL to fetch suggestions from
+ *
+ * @param Url $suggestionsUrl
+ *
+ * @return $this
+ */
+ public function setSuggestionsUrl(Url $suggestionsUrl): static
+ {
+ $this->suggestionsUrl = $suggestionsUrl;
+
+ return $this;
+ }
+
+ /**
+ * @return string If not set, returns a default placeholder
+ */
+ public function getPlaceholder(): string
+ {
+ return $this->placeholder ?? $this->translate('Start typing to see suggestions…');
+ }
+
+ protected function assemble(): void
+ {
+ $suggestionsId = uniqid('search-suggestions-');
+
+ $this->prependWrapper(
+ new HtmlElement(
+ 'div',
+ new Attributes(['class' => 'suggestion-element-group']),
+ new HtmlElement('div', new Attributes(['id' => $suggestionsId, 'class' => 'search-suggestions'])),
+ new HtmlElement('span', new Attributes(['class' => 'suggestion-element-icon']), new Icon('search'))
+ )
+ );
+
+ $this->getAttributes()->add([
+ 'data-term-suggestions' => '#' . $suggestionsId,
+ 'data-suggest-url' => $this->getSuggestionsUrl()
+ ]);
+ }
+}
diff --git a/vendor/ipl/web/src/FormElement/TermInput.php b/vendor/ipl/web/src/FormElement/TermInput.php
index f1485c7..c1c4b87 100644
--- a/vendor/ipl/web/src/FormElement/TermInput.php
+++ b/vendor/ipl/web/src/FormElement/TermInput.php
@@ -2,6 +2,7 @@
namespace ipl\Web\FormElement;
+use ipl\Html\Attribute;
use ipl\Html\Attributes;
use ipl\Html\Form;
use ipl\Html\FormElement\FieldsetElement;
@@ -268,19 +269,25 @@ class TermInput extends FieldsetElement
if ($this->valueHasBeenPasted()) {
$updates[] = $this->termContainer();
$updates[] = [
- HtmlString::create(json_encode(['#' . $this->getName() . '-search-input', []])),
+ HtmlString::create(json_encode(
+ ['#' . Attribute::sanitizeId($this->getValueOfNameAttribute()) . '-search-input', []]
+ )),
'Behavior:InputEnrichment'
];
} elseif (! empty($this->changes)) {
$updates[] = [
- HtmlString::create(json_encode(['#' . $this->getName() . '-search-input', $this->changes])),
+ HtmlString::create(json_encode(
+ ['#' . Attribute::sanitizeId($this->getValueOfNameAttribute()) . '-search-input', $this->changes]
+ )),
'Behavior:InputEnrichment'
];
}
if (empty($updates) && $this->hasBeenAutoSubmitted()) {
$updates[] = $updates[] = [
- HtmlString::create(json_encode(['#' . $this->getName() . '-search-input', 'bogus'])),
+ HtmlString::create(json_encode(
+ ['#' . Attribute::sanitizeId($this->getValueOfNameAttribute()) . '-search-input', 'bogus']
+ )),
'Behavior:InputEnrichment'
];
}
@@ -314,8 +321,8 @@ class TermInput extends FieldsetElement
public function onRegistered(Form $form)
{
- $termContainerId = $this->getName() . '-terms';
- $mainInputId = $this->getName() . '-search-input';
+ $termContainerId = Attribute::sanitizeId($this->getValueOfNameAttribute()) . '-terms';
+ $mainInputId = Attribute::sanitizeId($this->getValueOfNameAttribute()) . '-search-input';
$autoSubmittedBy = $form->getRequest()->getHeader('X-Icinga-Autosubmittedby');
$this->hasBeenAutoSubmitted = in_array($mainInputId, $autoSubmittedBy, true)
@@ -384,7 +391,7 @@ class TermInput extends FieldsetElement
{
if ($this->termContainer === null) {
$this->termContainer = (new TermContainer($this))
- ->setAttribute('id', $this->getName() . '-terms');
+ ->setAttribute('id', Attribute::sanitizeId($this->getValueOfNameAttribute()) . '-terms');
}
return $this->termContainer;
@@ -392,7 +399,7 @@ class TermInput extends FieldsetElement
protected function assemble()
{
- $myName = $this->getName();
+ $myName = Attribute::sanitizeId($this->getValueOfNameAttribute());
$termInputId = $myName . '-term-input';
$dataInputId = $myName . '-data-input';
diff --git a/vendor/ipl/web/src/FormElement/TermInput/TermContainer.php b/vendor/ipl/web/src/FormElement/TermInput/TermContainer.php
index 0e0bb0e..8eabf0e 100644
--- a/vendor/ipl/web/src/FormElement/TermInput/TermContainer.php
+++ b/vendor/ipl/web/src/FormElement/TermInput/TermContainer.php
@@ -5,11 +5,15 @@ namespace ipl\Web\FormElement\TermInput;
use ipl\Html\Attributes;
use ipl\Html\BaseHtmlElement;
use ipl\Html\HtmlElement;
+use ipl\Html\Text;
+use ipl\I18n\Translation;
use ipl\Web\FormElement\TermInput;
use ipl\Web\Widget\Icon;
class TermContainer extends BaseHtmlElement
{
+ use Translation;
+
protected $tag = 'div';
protected $defaultAttributes = ['class' => 'terms'];
@@ -33,6 +37,12 @@ class TermContainer extends BaseHtmlElement
protected function assemble()
{
+ if ($this->input->getReadOnly()) {
+ $removeLabel = $this->translate('Remove');
+ // bind remove translation to DOM, this allows the JS part to make use of it
+ $this->setAttribute('data-remove-action-label', $removeLabel);
+ }
+
foreach ($this->input->getTerms() as $i => $term) {
$value = $term->getLabel() ?: $term->getSearchValue();
@@ -57,7 +67,16 @@ class TermContainer extends BaseHtmlElement
);
if ($this->input->getReadOnly()) {
$label->addHtml(
- new Icon('trash'),
+ new HtmlElement(
+ 'div',
+ Attributes::create(['class' => 'remove-action', 'title' => $removeLabel]),
+ new Icon('trash'),
+ new HtmlElement(
+ 'span',
+ Attributes::create(['class' => 'remove-action-label']),
+ new Text($removeLabel)
+ )
+ ),
new HtmlElement('span', Attributes::create(['class' => 'invalid-reason']))
);
}
diff --git a/vendor/ipl/web/src/FormElement/TermInput/TermSuggestions.php b/vendor/ipl/web/src/FormElement/TermInput/TermSuggestions.php
index 26b00ea..9a94b1c 100644
--- a/vendor/ipl/web/src/FormElement/TermInput/TermSuggestions.php
+++ b/vendor/ipl/web/src/FormElement/TermInput/TermSuggestions.php
@@ -2,280 +2,11 @@
namespace ipl\Web\FormElement\TermInput;
-use ipl\Html\Attributes;
-use ipl\Html\BaseHtmlElement;
-use ipl\Html\HtmlElement;
-use ipl\Html\Text;
-use ipl\I18n\Translation;
-use Psr\Http\Message\ServerRequestInterface;
-use Traversable;
+use ipl\Web\FormElement\SearchSuggestions;
-use function ipl\Stdlib\yield_groups;
-
-class TermSuggestions extends BaseHtmlElement
+/**
+ * @deprecated Use {@see SearchSuggestions} instead
+ */
+class TermSuggestions extends SearchSuggestions
{
- use Translation;
-
- protected $tag = 'ul';
-
- /** @var Traversable */
- protected $provider;
-
- /** @var ?callable */
- protected $groupingCallback;
-
- /** @var ?string */
- protected $searchTerm;
-
- /** @var ?string */
- protected $searchPattern;
-
- /** @var ?string */
- protected $originalValue;
-
- /** @var string[] */
- protected $excludeTerms = [];
-
- /**
- * Create new TermSuggestions
- *
- * The provider must deliver terms in form of arrays with the following keys:
- * * (required) search: The search value
- * * label: A human-readable label
- * * class: A CSS class
- * * title: A message shown upon hover on the term
- *
- * Any excess key is also transferred to the client, but currently unused.
- *
- * @param Traversable $provider
- */
- public function __construct(Traversable $provider)
- {
- $this->provider = $provider;
- }
-
- /**
- * Set a callback to identify groups for terms delivered by the provider
- *
- * The callback must return a string which is used as label for the group.
- * Its interface is: `function (array $data): string`
- *
- * @param callable $callback
- *
- * @return $this
- */
- public function setGroupingCallback(callable $callback): self
- {
- $this->groupingCallback = $callback;
-
- return $this;
- }
-
- /**
- * Get the callback used to identify groups for terms delivered by the provider
- *
- * @return ?callable
- */
- public function getGroupingCallback(): ?callable
- {
- return $this->groupingCallback;
- }
-
- /**
- * Set the search term (can contain `*` wildcards)
- *
- * @param string $term
- *
- * @return $this
- */
- public function setSearchTerm(string $term): self
- {
- $this->searchTerm = $term;
- $this->setSearchPattern(
- '/' . str_replace(
- '\\000',
- '.*',
- preg_quote(
- str_replace(
- '*',
- "\0",
- $term
- ),
- '/'
- )
- ) . '/i'
- );
-
- return $this;
- }
-
- /**
- * Get the search term
- *
- * @return ?string
- */
- public function getSearchTerm(): ?string
- {
- return $this->searchTerm;
- }
-
- /**
- * Set the search pattern used by {@see matchSearch}
- *
- * @param string $pattern
- *
- * @return $this
- */
- protected function setSearchPattern(string $pattern): self
- {
- $this->searchPattern = $pattern;
-
- return $this;
- }
-
- /**
- * Set the original search value
- *
- * The one without automatically added wildcards.
- *
- * @param string $term
- *
- * @return $this
- */
- public function setOriginalSearchValue(string $term): self
- {
- $this->originalValue = $term;
-
- return $this;
- }
-
- /**
- * Get the original search value
- *
- * @return ?string
- */
- public function getOriginalSearchValue(): ?string
- {
- return $this->originalValue;
- }
-
- /**
- * Set the terms to exclude in the suggestion list
- *
- * @param string[] $terms
- *
- * @return $this
- */
- public function setExcludeTerms(array $terms): self
- {
- $this->excludeTerms = $terms;
-
- return $this;
- }
-
- /**
- * Get the terms to exclude in the suggestion list
- *
- * @return string[]
- */
- public function getExcludeTerms(): array
- {
- return $this->excludeTerms;
- }
-
- /**
- * Match the given search term against the users search
- *
- * @param string $term
- *
- * @return bool Whether the search matches or not
- */
- public function matchSearch(string $term): bool
- {
- if (! $this->searchPattern || $this->searchPattern === '.*') {
- return true;
- }
-
- return (bool) preg_match($this->searchPattern, $term);
- }
-
- /**
- * Load suggestions as requested by the client
- *
- * @param ServerRequestInterface $request
- *
- * @return $this
- */
- public function forRequest(ServerRequestInterface $request): self
- {
- if ($request->getMethod() !== 'POST') {
- return $this;
- }
-
- /** @var array> $requestData */
- $requestData = json_decode($request->getBody()->read(8192), true);
- if (empty($requestData)) {
- return $this;
- }
-
- $this->setSearchTerm($requestData['term']['label']);
- $this->setOriginalSearchValue($requestData['term']['search']);
- $this->setExcludeTerms($requestData['exclude'] ?? []);
-
- return $this;
- }
-
- protected function assemble()
- {
- $groupingCallback = $this->getGroupingCallback();
- if ($groupingCallback) {
- $provider = yield_groups($this->provider, $groupingCallback);
- } else {
- $provider = [null => $this->provider];
- }
-
- /** @var iterable>> $provider */
- foreach ($provider as $group => $suggestions) {
- if ($group) {
- $this->addHtml(
- new HtmlElement(
- 'li',
- Attributes::create([
- 'class' => 'suggestion-title'
- ]),
- Text::create($group)
- )
- );
- }
-
- foreach ($suggestions as $data) {
- $attributes = [
- 'type' => 'button',
- 'value' => $data['label'] ?? $data['search']
- ];
- foreach ($data as $name => $value) {
- $attributes["data-$name"] = $value;
- }
-
- $this->addHtml(
- new HtmlElement(
- 'li',
- null,
- new HtmlElement(
- 'input',
- Attributes::create($attributes)
- )
- )
- );
- }
- }
-
- if ($this->isEmpty()) {
- $this->addHtml(new HtmlElement(
- 'li',
- Attributes::create(['class' => 'nothing-to-suggest']),
- new HtmlElement('em', null, Text::create($this->translate('Nothing to suggest')))
- ));
- }
- }
}
diff --git a/vendor/ipl/web/src/Layout/Controls.php b/vendor/ipl/web/src/Layout/Controls.php
index 8763775..9b52613 100644
--- a/vendor/ipl/web/src/Layout/Controls.php
+++ b/vendor/ipl/web/src/Layout/Controls.php
@@ -43,7 +43,7 @@ class Controls extends BaseHtmlElement
return $this;
}
- public function isEmpty()
+ public function isEmpty(): bool
{
if (! parent::isEmpty()) {
return false;
diff --git a/vendor/ipl/web/src/Layout/DetailedItemLayout.php b/vendor/ipl/web/src/Layout/DetailedItemLayout.php
new file mode 100644
index 0000000..a0c19c2
--- /dev/null
+++ b/vendor/ipl/web/src/Layout/DetailedItemLayout.php
@@ -0,0 +1,27 @@
+get('class')
+ ->removeValue('default-item-layout')
+ ->addValue('detailed-item-layout');
+ }
+
+ protected function assembleMain(HtmlDocument $container): void
+ {
+ $this->registerHeader($container);
+ $this->registerCaption($container);
+ $this->registerFooter($container);
+ }
+}
diff --git a/vendor/ipl/web/src/Layout/DetailedItemTableLayout.php b/vendor/ipl/web/src/Layout/DetailedItemTableLayout.php
new file mode 100644
index 0000000..bcedebc
--- /dev/null
+++ b/vendor/ipl/web/src/Layout/DetailedItemTableLayout.php
@@ -0,0 +1,19 @@
+get('class')
+ ->removeValue('default-item-layout')
+ ->addValue('detailed-item-layout');
+ }
+}
diff --git a/vendor/ipl/web/src/Layout/HeaderItemLayout.php b/vendor/ipl/web/src/Layout/HeaderItemLayout.php
new file mode 100644
index 0000000..7245174
--- /dev/null
+++ b/vendor/ipl/web/src/Layout/HeaderItemLayout.php
@@ -0,0 +1,17 @@
+get('class')->addValue('header-item-layout');
+ }
+}
diff --git a/vendor/ipl/web/src/Layout/ItemLayout.php b/vendor/ipl/web/src/Layout/ItemLayout.php
new file mode 100644
index 0000000..49f760f
--- /dev/null
+++ b/vendor/ipl/web/src/Layout/ItemLayout.php
@@ -0,0 +1,478 @@
+ */
+ protected $before = [];
+
+ /** @var array */
+ protected $after = [];
+
+ /**
+ * Create a new layout for items
+ *
+ * @param Item $item The item to render
+ * @param ItemRenderer $renderer The renderer used to assemble the layout's content
+ */
+ public function __construct($item, ItemRenderer $renderer)
+ {
+ $this->item = $item;
+ $this->renderer = $renderer;
+ }
+
+ /**
+ * Get the name of this layout
+ *
+ * @return string
+ */
+ public function getName(): string
+ {
+ return static::NAME;
+ }
+
+ /**
+ * Create attributes for this layout
+ *
+ * @param Attributes $attributes
+ *
+ * @return void
+ */
+ protected function createAttributes(Attributes $attributes): void
+ {
+ $attributes->get('class')->addValue(['item-layout', 'default-item-layout']);
+ }
+
+ /**
+ * Get attributes to apply to the container the layout is added to
+ *
+ * @return Attributes
+ */
+ public function getAttributes(): Attributes
+ {
+ $attributes = new Attributes();
+ $this->createAttributes($attributes);
+ $this->renderer->assembleAttributes($this->item, $attributes, $this->getName());
+
+ return $attributes;
+ }
+
+ /**
+ * Create a container for the visual representation of the item
+ *
+ * @return HtmlDocument
+ */
+ protected function createVisual(): HtmlDocument
+ {
+ return new HtmlElement('div', Attributes::create(['class' => static::VISUAL]));
+ }
+
+ /**
+ * Assemble the visual representation of the item in the given container
+ *
+ * @return void
+ */
+ protected function assembleVisual(HtmlDocument $container)
+ {
+ $this->renderer->assembleVisual($this->item, $container, $this->getName());
+ }
+
+ /**
+ * Create, assemble and register the visual representation of the item
+ *
+ * @param HtmlDocument $container
+ *
+ * @return void
+ */
+ protected function registerVisual(HtmlDocument $container): void
+ {
+ $visual = $this->createVisual();
+
+ $this->createBefore(static::VISUAL, $container);
+
+ $this->assembleVisual($visual);
+ if ($visual->isEmpty()) {
+ return;
+ }
+
+ $container->addHtml($visual);
+
+ $this->createAfter(static::VISUAL, $container);
+ }
+
+ /**
+ * Create a container for the main content of the item
+ *
+ * @return HtmlDocument
+ */
+ protected function createMain(): HtmlDocument
+ {
+ return new HtmlElement('div', Attributes::create(['class' => static::MAIN]));
+ }
+
+ /**
+ * Assemble the main content of the item in the given container
+ *
+ * @param HtmlDocument $container
+ *
+ * @return void
+ */
+ protected function assembleMain(HtmlDocument $container): void
+ {
+ $this->registerHeader($container);
+ $this->registerCaption($container);
+ }
+
+ /**
+ * Create, assemble and register the main content of the item
+ *
+ * @param HtmlDocument $container
+ *
+ * @return void
+ */
+ protected function registerMain(HtmlDocument $container): void
+ {
+ $main = $this->createMain();
+
+ $this->createBefore(static::MAIN, $container);
+
+ $this->assembleMain($main);
+
+ $container->addHtml($main);
+
+ $this->createAfter(static::MAIN, $container);
+ }
+
+ /**
+ * Create a container for the header of the item
+ *
+ * @return HtmlDocument
+ */
+ protected function createHeader(): HtmlDocument
+ {
+ return new HtmlElement('header');
+ }
+
+ /**
+ * Assemble the header of the item in the given container
+ *
+ * @param HtmlDocument $container
+ *
+ * @return void
+ */
+ protected function assembleHeader(HtmlDocument $container): void
+ {
+ $this->registerTitle($container);
+ $this->registerExtendedInfo($container);
+ }
+
+ /**
+ * Create, assemble and register the header of the item
+ *
+ * @param HtmlDocument $container
+ *
+ * @return void
+ */
+ protected function registerHeader(HtmlDocument $container): void
+ {
+ $header = $this->createHeader();
+
+ $this->createBefore(static::HEADER, $container);
+
+ $this->assembleHeader($header);
+
+ $container->addHtml($header);
+
+ $this->createAfter(static::HEADER, $container);
+ }
+
+ /**
+ * Create a container for the footer of the item
+ *
+ * @return HtmlDocument
+ */
+ protected function createFooter(): HtmlDocument
+ {
+ return new HtmlElement('footer');
+ }
+
+ /**
+ * Assemble the footer of the item in the given container
+ *
+ * @param HtmlDocument $container
+ *
+ * @return void
+ */
+ protected function assembleFooter(HtmlDocument $container): void
+ {
+ $this->renderer->assembleFooter($this->item, $container, $this->getName());
+ }
+
+ /**
+ * Create, assemble and register the footer of the item
+ *
+ * @param HtmlDocument $container
+ *
+ * @return void
+ */
+ protected function registerFooter(HtmlDocument $container): void
+ {
+ $footer = $this->createFooter();
+
+ $this->createBefore(static::FOOTER, $container);
+
+ $this->assembleFooter($footer);
+ if ($footer->isEmpty()) {
+ return;
+ }
+
+ $container->addHtml($footer);
+
+ $this->createAfter(static::FOOTER, $container);
+ }
+
+ /**
+ * Create a container for the caption of the item
+ *
+ * @return HtmlDocument
+ */
+ protected function createCaption(): HtmlDocument
+ {
+ return new HtmlElement('section', Attributes::create(['class' => static::CAPTION]));
+ }
+
+ /**
+ * Assemble the caption of the item in the given container
+ *
+ * @param HtmlDocument $container
+ *
+ * @return void
+ */
+ protected function assembleCaption(HtmlDocument $container): void
+ {
+ $this->renderer->assembleCaption($this->item, $container, $this->getName());
+ }
+
+ /**
+ * Create, assemble and register the caption of the item
+ *
+ * @param HtmlDocument $container
+ *
+ * @return void
+ */
+ protected function registerCaption(HtmlDocument $container): void
+ {
+ $caption = $this->createCaption();
+
+ $this->createBefore(static::CAPTION, $container);
+
+ $this->assembleCaption($caption);
+
+ $container->addHtml($caption);
+
+ $this->createAfter(static::CAPTION, $container);
+ }
+
+ /**
+ * Create a container for the title of the item
+ *
+ * @return HtmlDocument
+ */
+ protected function createTitle(): HtmlDocument
+ {
+ return new HtmlElement('div', Attributes::create(['class' => static::TITLE]));
+ }
+
+ /**
+ * Assemble the title of the item in the given container
+ *
+ * @param HtmlDocument $container
+ *
+ * @return void
+ */
+ protected function assembleTitle(HtmlDocument $container): void
+ {
+ $this->renderer->assembleTitle($this->item, $container, $this->getName());
+ }
+
+ /**
+ * Create, assemble and register the title of the item
+ *
+ * @param HtmlDocument $container
+ *
+ * @return void
+ */
+ protected function registerTitle(HtmlDocument $container): void
+ {
+ $title = $this->createTitle();
+
+ $this->createBefore(static::TITLE, $container);
+
+ $this->assembleTitle($title);
+
+ $container->addHtml($title);
+
+ $this->createAfter(static::TITLE, $container);
+ }
+
+ /**
+ * Create a container for the extended information of the item
+ *
+ * @return HtmlDocument
+ */
+ protected function createExtendedInfo(): HtmlDocument
+ {
+ return new HtmlElement('div', Attributes::create(['class' => static::EXTENDED_INFO]));
+ }
+
+ /**
+ * Assemble the extended information of the item in the given container
+ *
+ * @param HtmlDocument $container
+ *
+ * @return void
+ */
+ protected function assembleExtendedInfo(HtmlDocument $container): void
+ {
+ $this->renderer->assembleExtendedInfo($this->item, $container, $this->getName());
+ }
+
+ /**
+ * Create, assemble and register the extended information of the item
+ *
+ * @param HtmlDocument $container
+ *
+ * @return void
+ */
+ protected function registerExtendedInfo(HtmlDocument $container): void
+ {
+ $info = $this->createExtendedInfo();
+
+ $this->createBefore(static::EXTENDED_INFO, $container);
+
+ $this->assembleExtendedInfo($info);
+ if ($info->isEmpty()) {
+ return;
+ }
+
+ $container->addHtml($info);
+
+ $this->createAfter(static::EXTENDED_INFO, $container);
+ }
+
+ /**
+ * Render a custom section before the given one
+ *
+ * @param SECTION $section Identifier of the target section
+ * @param string $customSection Identifier for the custom section
+ *
+ * @return void
+ */
+ public function before(string $section, string $customSection): void
+ {
+ $this->before[$section] = $customSection;
+ }
+
+ /**
+ * Add a custom section before the given one
+ *
+ * @param SECTION $section Identifier of the target section
+ * @param HtmlDocument $container The container to add the custom section to
+ *
+ * @return void
+ */
+ protected function createBefore(string $section, HtmlDocument $container): void
+ {
+ if (isset($this->before[$section])) {
+ $customSection = new HtmlElement('div', Attributes::create(['class' => $this->before[$section]]));
+ if ($this->renderer->assemble($this->item, $this->before[$section], $customSection, $this->getName())) {
+ $container->addHtml($customSection);
+ }
+ }
+ }
+
+ /**
+ * Render a custom section after the given one
+ *
+ * @param SECTION $section Identifier of the target section
+ * @param string $customSection Identifier for the custom section
+ *
+ * @return void
+ */
+ public function after(string $section, string $customSection): void
+ {
+ $this->after[$section] = $customSection;
+ }
+
+ /**
+ * Add a custom section after the given one
+ *
+ * @param SECTION $section Identifier of the target section
+ * @param HtmlDocument $container The container to add the custom section to
+ *
+ * @return void
+ */
+ protected function createAfter(string $section, HtmlDocument $container): void
+ {
+ if (isset($this->after[$section])) {
+ $customSection = new HtmlElement('div', Attributes::create(['class' => $this->after[$section]]));
+ if ($this->renderer->assemble($this->item, $this->after[$section], $customSection, $this->getName())) {
+ $container->addHtml($customSection);
+ }
+ }
+ }
+
+ /**
+ * Assemble the layout
+ *
+ * @return void
+ */
+ protected function assemble(): void
+ {
+ $this->registerVisual($this);
+ $this->registerMain($this);
+ }
+}
diff --git a/vendor/ipl/web/src/Layout/ItemTableLayout.php b/vendor/ipl/web/src/Layout/ItemTableLayout.php
new file mode 100644
index 0000000..ede658c
--- /dev/null
+++ b/vendor/ipl/web/src/Layout/ItemTableLayout.php
@@ -0,0 +1,125 @@
+
+ */
+class ItemTableLayout extends ItemLayout
+{
+ /** @var ItemTableRenderer */
+ protected $renderer;
+
+ /** @var int Number of caption columns */
+ protected $columnCount = 0;
+
+ /**
+ * Create a new item table layout
+ *
+ * @param Item $item
+ * @param ItemTableRenderer $renderer
+ */
+ public function __construct($item, ItemTableRenderer $renderer)
+ {
+ parent::__construct($item, $renderer);
+ }
+
+ /**
+ * Get the number of caption columns
+ *
+ * @return int
+ */
+ public function getColumnCount(): int
+ {
+ return $this->columnCount;
+ }
+
+ /**
+ * Create column
+ *
+ * @param string $class CSS class to apply
+ *
+ * @return HtmlElement
+ */
+ protected function createColumn(string $class): HtmlElement
+ {
+ return new HtmlElement('div', Attributes::create(['class' => ['col', $class]]));
+ }
+
+ protected function createVisual(): HtmlDocument
+ {
+ return $this->createColumn(ItemLayout::VISUAL);
+ }
+
+ protected function createMain(): HtmlDocument
+ {
+ return $this->createColumn(ItemLayout::MAIN);
+ }
+
+ protected function assembleHeader(HtmlDocument $container): void
+ {
+ $this->registerTitle($container);
+ }
+
+ /**
+ * Create a container for the item's columns
+ *
+ * @return HtmlDocument
+ */
+ protected function createColumns(): HtmlDocument
+ {
+ return new HtmlDocument();
+ }
+
+ /**
+ * Assemble columns for the item
+ *
+ * @param HtmlDocument $container
+ *
+ * @return void
+ */
+ protected function assembleColumns(HtmlDocument $container): void
+ {
+ $this->renderer->assembleColumns($this->item, $container, $this->getName());
+ }
+
+ /**
+ * Create, assemble and register columns for the item
+ *
+ * @param HtmlDocument $container
+ *
+ * @return void
+ */
+ protected function registerColumns(HtmlDocument $container): void
+ {
+ $columns = $this->createColumns();
+
+ $this->createBefore('columns', $container);
+
+ $this->assembleColumns($columns);
+
+ $this->columnCount = $columns->count();
+
+ $container->addFrom($columns, function (ValidHtml $content) {
+ return $this->createColumn('')->addHtml($content);
+ });
+
+ $this->createAfter('columns', $container);
+ }
+
+ protected function assemble(): void
+ {
+ $this->registerVisual($this);
+ $this->registerMain($this);
+ $this->registerColumns($this);
+ }
+}
diff --git a/vendor/ipl/web/src/Layout/MinimalItemLayout.php b/vendor/ipl/web/src/Layout/MinimalItemLayout.php
new file mode 100644
index 0000000..c70521e
--- /dev/null
+++ b/vendor/ipl/web/src/Layout/MinimalItemLayout.php
@@ -0,0 +1,30 @@
+get('class')->addValue('minimal-item-layout');
+ }
+
+ protected function assembleMain(HtmlDocument $container): void
+ {
+ $this->registerHeader($container);
+ }
+
+ protected function assembleHeader(HtmlDocument $container): void
+ {
+ $this->registerTitle($container);
+ $this->registerCaption($container);
+ $this->registerExtendedInfo($container);
+ }
+}
diff --git a/vendor/ipl/web/src/Layout/MinimalItemTableLayout.php b/vendor/ipl/web/src/Layout/MinimalItemTableLayout.php
new file mode 100644
index 0000000..6330220
--- /dev/null
+++ b/vendor/ipl/web/src/Layout/MinimalItemTableLayout.php
@@ -0,0 +1,29 @@
+get('class')->addValue('minimal-item-layout');
+ }
+
+ protected function assembleHeader(HtmlDocument $container): void
+ {
+ $this->registerTitle($container);
+ $this->registerCaption($container);
+ }
+
+ protected function assembleMain(HtmlDocument $container): void
+ {
+ $this->registerHeader($container);
+ }
+}
diff --git a/vendor/ipl/web/src/Widget/Ball.php b/vendor/ipl/web/src/Widget/Ball.php
new file mode 100644
index 0000000..61b7284
--- /dev/null
+++ b/vendor/ipl/web/src/Widget/Ball.php
@@ -0,0 +1,102 @@
+ ['ball']];
+
+ /** @var SIZE */
+ protected $size = self::SIZE_LARGE;
+
+ /**
+ * Create a new ball element
+ *
+ * @param SIZE $size
+ */
+ public function __construct(string $size = self::SIZE_LARGE)
+ {
+ $size = trim($size);
+ if (empty($size)) {
+ $size = self::SIZE_MEDIUM;
+ }
+
+ $this->size = $size;
+ }
+
+ /**
+ * Register the attribute callbacks
+ *
+ * @param Attributes $attributes
+ */
+ protected function registerAttributeCallbacks(Attributes $attributes): void
+ {
+ $attributes->registerAttributeCallback('class', function () {
+ return new Attribute('class', $this->assembleCssClasses());
+ });
+ }
+
+ /**
+ * Assemble the CSS classes for the ball
+ *
+ * @return array
+ */
+ protected function assembleCssClasses(): array
+ {
+ return ['ball-size-' . $this->size];
+ }
+
+ /**
+ * Add content to the ball
+ *
+ * Automatically wraps text content in a span element.
+ *
+ * @param ValidHtml ...$content
+ *
+ * @return $this
+ */
+ public function addHtml(ValidHtml ...$content): static
+ {
+ if (count($content) === 1 && $content[0] instanceof Text) {
+ $content[0] = new HtmlElement('span', null, $content[0]);
+ }
+
+ return parent::addHtml(...$content);
+ }
+}
diff --git a/vendor/ipl/web/src/Widget/ButtonLink.php b/vendor/ipl/web/src/Widget/ButtonLink.php
index 2da5dfd..b9cd1fa 100644
--- a/vendor/ipl/web/src/Widget/ButtonLink.php
+++ b/vendor/ipl/web/src/Widget/ButtonLink.php
@@ -2,13 +2,54 @@
namespace ipl\Web\Widget;
+use ipl\Html\Attribute;
+
/**
* Button like link generally pointing to CRUD actions
*/
class ButtonLink extends ActionLink
{
protected $defaultAttributes = [
- 'class' => 'button-link',
- 'data-base-target' => '_main'
+ 'role' => 'button',
+ 'class' => 'button-link',
+ 'data-base-target' => '_main'
];
+
+ /** @var ?string The explanation why the button is disabled */
+ protected ?string $disabledExplanation = null;
+
+ /**
+ * Disable the button with explanation
+ *
+ * @param string $explanation Why the button is disabled
+ *
+ * @return $this
+ */
+ public function disable(string $explanation): self
+ {
+ $this->disabledExplanation = $explanation;
+
+ return $this;
+ }
+
+ public function createHrefAttribute(): ?Attribute
+ {
+ if ($this->disabledExplanation) {
+ return null;
+ }
+
+ return parent::createHrefAttribute();
+ }
+
+ public function assemble(): void
+ {
+ parent::assemble();
+
+ if ($this->disabledExplanation) {
+ $this->addAttributes([
+ 'aria-disabled' => 'true',
+ 'title' => $this->disabledExplanation,
+ ]);
+ }
+ }
}
diff --git a/vendor/ipl/web/src/Widget/ContinueWith.php b/vendor/ipl/web/src/Widget/ContinueWith.php
index 1479e9a..6c3fd69 100644
--- a/vendor/ipl/web/src/Widget/ContinueWith.php
+++ b/vendor/ipl/web/src/Widget/ContinueWith.php
@@ -54,6 +54,11 @@ class ContinueWith extends BaseHtmlElement
$filter = $filter(); /** @var Filter\Rule $filter */
}
+ $baseFilter = $this->url->getFilter();
+ if ($baseFilter && ((! $baseFilter instanceof Filter\Chain) || ! $baseFilter->isEmpty())) {
+ $filter = Filter::all($baseFilter, $filter);
+ }
+
if ($filter instanceof Filter\Chain && $filter->isEmpty()) {
$this->addHtml(new HtmlElement(
'span',
diff --git a/vendor/ipl/web/src/Widget/ItemList.php b/vendor/ipl/web/src/Widget/ItemList.php
new file mode 100644
index 0000000..f8da067
--- /dev/null
+++ b/vendor/ipl/web/src/Widget/ItemList.php
@@ -0,0 +1,191 @@
+ */
+ protected $data;
+
+ /** @var ItemRenderer|callable */
+ protected $itemRenderer;
+
+ /** @var string */
+ private $itemLayoutClass = ItemLayout::class;
+
+ /** @var ?ValidHtml Message to show if the list is empty */
+ protected $emptyStateMessage;
+
+ /** @var array */
+ protected $baseAttributes = [
+ 'class' => 'item-list',
+ 'data-base-target' => '_next',
+ 'data-pdfexport-page-breaks-at' => '.list-item'
+ ];
+
+ protected $tag = 'ul';
+
+ /**
+ * Create a new item list
+ *
+ * @param ResultSet|iterable $data
+ * @param ItemRenderer|callable $itemRenderer If a callable is passed,
+ * it must accept an item as first argument
+ */
+ public function __construct($data, $itemRenderer)
+ {
+ if (! is_iterable($data)) {
+ throw new InvalidArgumentException('Data must be an array or an instance of Traversable');
+ }
+
+ $this->data = $data;
+ $this->itemRenderer = $itemRenderer;
+
+ $this->addAttributes($this->baseAttributes);
+
+ $this->init();
+ }
+
+ /**
+ * Initialize the item list
+ *
+ * If you want to adjust the item list after construction, override this method.
+ */
+ protected function init(): void
+ {
+ }
+
+ /**
+ * Set the layout class for the items
+ *
+ * @param string $class Must be an instance of the previously set item layout class
+ *
+ * @return $this
+ *
+ * @throws InvalidArgumentException If the class is not a subclass of {@see ItemLayout}
+ */
+ public function setItemLayoutClass(string $class): self
+ {
+ if ($class !== $this->itemLayoutClass && ! is_subclass_of($class, $this->itemLayoutClass)) {
+ throw new InvalidArgumentException("Class $class must be a subclass of " . $this->itemLayoutClass);
+ }
+
+ $this->itemLayoutClass = $class;
+
+ return $this;
+ }
+
+ /**
+ * Get the layout for the given item
+ *
+ * @param Item $item
+ *
+ * @return ItemLayout
+ */
+ public function getItemLayout($item): ItemLayout
+ {
+ return new $this->itemLayoutClass($item, $this->getItemRenderer($item));
+ }
+
+ /**
+ * Get message to show if the list is empty
+ *
+ * @return ValidHtml
+ */
+ public function getEmptyStateMessage(): ValidHtml
+ {
+ if ($this->emptyStateMessage === null) {
+ return new Text($this->translate('No items found.'));
+ }
+
+ return $this->emptyStateMessage;
+ }
+
+ /**
+ * Set message to show if the list is empty
+ *
+ * @param mixed $message If empty, the default message is used
+ *
+ * @return $this
+ */
+ public function setEmptyStateMessage(mixed $message): self
+ {
+ if (empty($message)) {
+ $this->emptyStateMessage = null;
+ } else {
+ $this->emptyStateMessage = Html::wantHtml($message);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get renderer for the given item
+ *
+ * @param Item $item
+ *
+ * @return ItemRenderer
+ */
+ protected function getItemRenderer($item): ItemRenderer
+ {
+ if (is_callable($this->itemRenderer)) {
+ return call_user_func($this->itemRenderer, $item);
+ } elseif (is_string($this->itemRenderer)) {
+ $this->itemRenderer = new $this->itemRenderer();
+ }
+
+ return $this->itemRenderer;
+ }
+
+ /**
+ * Create a list item for the given data
+ *
+ * @param Result $data
+ *
+ * @return ListItem
+ */
+ protected function createListItem(object $data)
+ {
+ return new ListItem($data, $this);
+ }
+
+ protected function assemble(): void
+ {
+ /** @var Result $data */
+ foreach ($this->data as $data) {
+ $item = $this->createListItem($data);
+ $this->emit(self::BEFORE_ITEM_ADD, [$item, $data]);
+ $this->addHtml($item);
+ $this->emit(self::ON_ITEM_ADD, [$item, $data]);
+ }
+
+ if ($this->isEmpty()) {
+ $this->setTag('div');
+ $this->addHtml(new EmptyState($this->getEmptyStateMessage()));
+ }
+ }
+}
diff --git a/vendor/ipl/web/src/Widget/ItemTable.php b/vendor/ipl/web/src/Widget/ItemTable.php
new file mode 100644
index 0000000..d791fbc
--- /dev/null
+++ b/vendor/ipl/web/src/Widget/ItemTable.php
@@ -0,0 +1,76 @@
+
+ */
+class ItemTable extends ItemList
+{
+ /** @var array */
+ protected $baseAttributes = [
+ 'class' => 'item-table',
+ 'data-base-target' => '_next'
+ ];
+
+ /** @var bool Whether the list already listens for an item's assembly to determine the number of caption columns */
+ protected $listeningForColumnCount = false;
+
+ /** @var StyleWithNonce */
+ protected $style;
+
+ protected function init(): void
+ {
+ parent::init();
+
+ $this->setItemLayoutClass(ItemTableLayout::class);
+ }
+
+ /**
+ * Create a list item for the given data
+ *
+ * @param object $data
+ *
+ * @return ItemTableRow
+ */
+ protected function createListItem(object $data): ValidHtml
+ {
+ return new ItemTableRow($data, $this);
+ }
+
+ public function getItemLayout($item): ItemLayout
+ {
+ $layout = parent::getItemLayout($item);
+ if (! $this->listeningForColumnCount) {
+ $this->listeningForColumnCount = true;
+ $layout->on(HtmlDocument::ON_ASSEMBLED, function (ItemTableLayout $layout) {
+ $columns = $layout->getColumnCount();
+ if ($columns === 0) {
+ throw new LogicException('An item table requires at least a single column.');
+ }
+
+ $this->style->addFor($this, ['--columns' => $columns]);
+ });
+ }
+
+ return $layout;
+ }
+
+ protected function assemble(): void
+ {
+ parent::assemble();
+
+ $this->style = new StyleWithNonce();
+ $this->addHtml($this->style);
+ }
+}
diff --git a/vendor/ipl/web/src/Widget/ItemTable/ItemTableRenderer.php b/vendor/ipl/web/src/Widget/ItemTable/ItemTableRenderer.php
new file mode 100644
index 0000000..d1faf69
--- /dev/null
+++ b/vendor/ipl/web/src/Widget/ItemTable/ItemTableRenderer.php
@@ -0,0 +1,26 @@
+
+ */
+interface ItemTableRenderer extends ItemRenderer
+{
+ /**
+ * Assemble columns for an item
+ *
+ * @param Item $item The item to render
+ * @param HtmlDocument $columns The container to add the result to
+ * @param string $layout The name of the layout
+ *
+ * @return void
+ */
+ public function assembleColumns($item, HtmlDocument $columns, string $layout): void;
+}
diff --git a/vendor/ipl/web/src/Widget/ItemTableRow.php b/vendor/ipl/web/src/Widget/ItemTableRow.php
new file mode 100644
index 0000000..9b7804b
--- /dev/null
+++ b/vendor/ipl/web/src/Widget/ItemTableRow.php
@@ -0,0 +1,46 @@
+ The list where the item is part of */
+ protected $list;
+
+ protected $tag = 'li';
+
+ protected $defaultAttributes = ['class' => 'table-row'];
+
+ /**
+ * Create a new table row item
+ *
+ * @param Item $item
+ * @param ItemTable $table
+ */
+ public function __construct($item, ItemTable $table)
+ {
+ $this->item = $item;
+ $this->list = $table;
+ }
+
+ protected function assemble()
+ {
+ $layout = $this->list->getItemLayout($this->item);
+
+ $this->addAttributes($layout->getAttributes());
+ $this->addHtml($layout);
+ }
+}
diff --git a/vendor/ipl/web/src/Widget/ListItem.php b/vendor/ipl/web/src/Widget/ListItem.php
new file mode 100644
index 0000000..7187379
--- /dev/null
+++ b/vendor/ipl/web/src/Widget/ListItem.php
@@ -0,0 +1,46 @@
+ The list where the item is part of */
+ protected $list;
+
+ protected $tag = 'li';
+
+ protected $defaultAttributes = ['class' => 'list-item'];
+
+ /**
+ * Create a new list item
+ *
+ * @param Item $item
+ * @param ItemList $list
+ */
+ public function __construct($item, ItemList $list)
+ {
+ $this->item = $item;
+ $this->list = $list;
+ }
+
+ protected function assemble()
+ {
+ $layout = $this->list->getItemLayout($this->item);
+
+ $this->addAttributes($layout->getAttributes());
+ $this->addHtml($layout);
+ }
+}
diff --git a/vendor/ipl/web/src/Widget/StateBall.php b/vendor/ipl/web/src/Widget/StateBall.php
index 5a1216d..cc47e13 100644
--- a/vendor/ipl/web/src/Widget/StateBall.php
+++ b/vendor/ipl/web/src/Widget/StateBall.php
@@ -2,42 +2,62 @@
namespace ipl\Web\Widget;
-use ipl\Html\BaseHtmlElement;
-
/**
* State ball element that supports different sizes and colors
+ *
+ * @phpstan-import-type SIZE from Ball
+ * @phpstan-type STATE 'none'|'pending'|'up'|'down'|'ok'|'critical'|'warning'|'unknown'|'unreachable'
*/
-class StateBall extends BaseHtmlElement
+class StateBall extends Ball
{
- const SIZE_TINY = 'xs';
- const SIZE_SMALL = 's';
- const SIZE_MEDIUM = 'm';
- const SIZE_MEDIUM_LARGE = 'ml';
- const SIZE_BIG = 'l';
- const SIZE_LARGE = 'xl';
+ protected $defaultAttributes = ['class' => 'state-ball'];
- protected $tag = 'span';
+ /** @var STATE */
+ protected $state = 'none';
+
+ /** @var bool */
+ protected $handled = false;
/**
* Create a new state ball element
*
- * @param string $state
- * @param string $size
+ * @param STATE $state
+ * @param SIZE $size
*/
- public function __construct($state = 'none', $size = self::SIZE_SMALL)
+ public function __construct(string $state = 'none', string $size = self::SIZE_SMALL)
{
$state = trim($state);
-
if (empty($state)) {
$state = 'none';
}
- $size = trim($size);
+ $this->state = $state;
- if (empty($size)) {
- $size = self::SIZE_MEDIUM;
+ parent::__construct($size);
+ }
+
+ /**
+ * Show the handled state instead
+ *
+ * @param bool $handled
+ *
+ * @return $this
+ */
+ public function setHandled(bool $handled): self
+ {
+ $this->handled = $handled;
+
+ return $this;
+ }
+
+ protected function assembleCssClasses(): array
+ {
+ $classes = parent::assembleCssClasses();
+ $classes[] = 'state-' . $this->state;
+ if ($this->handled) {
+ $classes[] = 'handled';
}
- $this->defaultAttributes = ['class' => "state-ball state-$state ball-size-$size"];
+ return $classes;
}
}
diff --git a/vendor/ramsey/collection/LICENSE b/vendor/ramsey/collection/LICENSE
index ae15f59..a7fcf12 100644
--- a/vendor/ramsey/collection/LICENSE
+++ b/vendor/ramsey/collection/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2015-2021 Ben Ramsey
+Copyright (c) 2015-2022 Ben Ramsey
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/vendor/ramsey/collection/composer.json b/vendor/ramsey/collection/composer.json
index 0c5d095..42fc22b 100644
--- a/vendor/ramsey/collection/composer.json
+++ b/vendor/ramsey/collection/composer.json
@@ -1,7 +1,8 @@
{
"name": "ramsey/collection",
+ "description": "A PHP library for representing and manipulating collections.",
+ "license": "MIT",
"type": "library",
- "description": "A PHP 7.2+ library for representing and manipulating collections.",
"keywords": [
"array",
"collection",
@@ -10,7 +11,6 @@
"queue",
"set"
],
- "license": "MIT",
"authors": [
{
"name": "Ben Ramsey",
@@ -19,29 +19,28 @@
}
],
"require": {
- "php": "^7.2 || ^8"
+ "php": "^8.1"
},
"require-dev": {
- "captainhook/captainhook": "^5.3",
- "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
- "ergebnis/composer-normalize": "^2.6",
- "fakerphp/faker": "^1.5",
- "hamcrest/hamcrest-php": "^2",
- "jangregor/phpstan-prophecy": "^0.8",
- "mockery/mockery": "^1.3",
- "phpstan/extension-installer": "^1",
- "phpstan/phpstan": "^0.12.32",
- "phpstan/phpstan-mockery": "^0.12.5",
- "phpstan/phpstan-phpunit": "^0.12.11",
- "phpunit/phpunit": "^8.5 || ^9",
- "psy/psysh": "^0.10.4",
- "slevomat/coding-standard": "^6.3",
- "squizlabs/php_codesniffer": "^3.5",
- "vimeo/psalm": "^4.4"
- },
- "config": {
- "sort-packages": true
+ "captainhook/plugin-composer": "^5.3",
+ "ergebnis/composer-normalize": "^2.45",
+ "fakerphp/faker": "^1.24",
+ "hamcrest/hamcrest-php": "^2.0",
+ "jangregor/phpstan-prophecy": "^2.1",
+ "mockery/mockery": "^1.6",
+ "php-parallel-lint/php-console-highlighter": "^1.0",
+ "php-parallel-lint/php-parallel-lint": "^1.4",
+ "phpspec/prophecy-phpunit": "^2.3",
+ "phpstan/extension-installer": "^1.4",
+ "phpstan/phpstan": "^2.1",
+ "phpstan/phpstan-mockery": "^2.0",
+ "phpstan/phpstan-phpunit": "^2.0",
+ "phpunit/phpunit": "^10.5",
+ "ramsey/coding-standard": "^2.3",
+ "ramsey/conventional-commits": "^1.6",
+ "roave/security-advisories": "dev-latest"
},
+ "prefer-stable": true,
"autoload": {
"psr-4": {
"Ramsey\\Collection\\": "src/"
@@ -49,57 +48,61 @@
},
"autoload-dev": {
"psr-4": {
- "Ramsey\\Console\\": "resources/console/",
"Ramsey\\Collection\\Test\\": "tests/"
+ }
+ },
+ "config": {
+ "allow-plugins": {
+ "captainhook/plugin-composer": true,
+ "dealerdirect/phpcodesniffer-composer-installer": true,
+ "ergebnis/composer-normalize": true,
+ "phpstan/extension-installer": true
},
- "files": [
- "vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest.php"
- ]
+ "sort-packages": true
+ },
+ "extra": {
+ "captainhook": {
+ "force-install": true
+ },
+ "ramsey/conventional-commits": {
+ "configFile": "conventional-commits.json"
+ }
},
"scripts": {
- "post-autoload-dump": "captainhook install --ansi -f -s",
- "br:analyze": [
- "@br:analyze:phpstan",
- "@br:analyze:psalm"
+ "dev:analyze": [
+ "@dev:analyze:phpstan"
],
- "br:analyze:phpstan": "phpstan --memory-limit=1G analyse",
- "br:analyze:psalm": "psalm --diff --config=psalm.xml",
- "br:build:clean": "git clean -fX build/.",
- "br:build:clear-cache": "git clean -fX build/cache/.",
- "br:lint": "phpcs --cache=build/cache/phpcs.cache",
- "br:lint:fix": "./bin/lint-fix.sh",
- "br:repl": [
- "echo ; echo 'Type ./bin/repl to start the REPL.'"
+ "dev:analyze:phpstan": "phpstan analyse --ansi --memory-limit=1G",
+ "dev:build:clean": "git clean -fX build/",
+ "dev:lint": [
+ "@dev:lint:syntax",
+ "@dev:lint:style"
],
- "br:test": "phpunit",
- "br:test:all": [
- "@br:lint",
- "@br:analyze",
- "@br:test"
+ "dev:lint:fix": "phpcbf",
+ "dev:lint:style": "phpcs --colors",
+ "dev:lint:syntax": "parallel-lint --colors src/ tests/",
+ "dev:test": [
+ "@dev:lint",
+ "@dev:analyze",
+ "@dev:test:unit"
],
- "br:test:coverage:ci": "phpunit --coverage-clover build/logs/clover.xml",
- "br:test:coverage:html": "phpunit --coverage-html build/coverage",
- "pre-commit": [
- "@br:lint:fix",
- "@br:lint",
- "@br:analyze"
- ],
- "test": "@br:test:all"
+ "dev:test:coverage:ci": "phpunit --colors=always --coverage-text --coverage-clover build/coverage/clover.xml --coverage-cobertura build/coverage/cobertura.xml --coverage-crap4j build/coverage/crap4j.xml --coverage-xml build/coverage/coverage-xml --log-junit build/junit.xml",
+ "dev:test:coverage:html": "phpunit --colors=always --coverage-html build/coverage/coverage-html/",
+ "dev:test:unit": "phpunit --colors=always",
+ "test": "@dev:test"
},
"scripts-descriptions": {
- "br:analyze": "Performs static analysis on the code base.",
- "br:analyze:phpstan": "Runs the PHPStan static analyzer.",
- "br:analyze:psalm": "Runs the Psalm static analyzer.",
- "br:build:clean": "Removes everything not under version control from the build directory.",
- "br:build:clear-cache": "Removes everything not under version control from build/cache/.",
- "br:lint": "Checks all source code for coding standards issues.",
- "br:lint:fix": "Checks source code for coding standards issues and fixes them, if possible.",
- "br:repl": "Note: Use ./bin/repl to run the REPL.",
- "br:test": "Runs the full unit test suite.",
- "br:test:all": "Runs linting, static analysis, and unit tests.",
- "br:test:coverage:ci": "Runs the unit test suite and generates a Clover coverage report.",
- "br:test:coverage:html": "Runs the unit tests suite and generates an HTML coverage report.",
- "pre-commit": "These commands are run as part of a Git pre-commit hook installed using captainhook/captainhook. Each command should be prepared to accept a list of space-separated staged files.",
- "test": "Shortcut to run the full test suite."
+ "dev:analyze": "Runs all static analysis checks.",
+ "dev:analyze:phpstan": "Runs the PHPStan static analyzer.",
+ "dev:build:clean": "Cleans the build/ directory.",
+ "dev:lint": "Runs all linting checks.",
+ "dev:lint:fix": "Auto-fixes coding standards issues, if possible.",
+ "dev:lint:style": "Checks for coding standards issues.",
+ "dev:lint:syntax": "Checks for syntax errors.",
+ "dev:test": "Runs linting, static analysis, and unit tests.",
+ "dev:test:coverage:ci": "Runs unit tests and generates CI coverage reports.",
+ "dev:test:coverage:html": "Runs unit tests and generates HTML coverage report.",
+ "dev:test:unit": "Runs unit tests.",
+ "test": "Runs linting, static analysis, and unit tests."
}
}
diff --git a/vendor/ramsey/collection/src/AbstractArray.php b/vendor/ramsey/collection/src/AbstractArray.php
index a8a164c..6d6b6d6 100644
--- a/vendor/ramsey/collection/src/AbstractArray.php
+++ b/vendor/ramsey/collection/src/AbstractArray.php
@@ -17,15 +17,14 @@ namespace Ramsey\Collection;
use ArrayIterator;
use Traversable;
-use function serialize;
-use function unserialize;
+use function count;
/**
* This class provides a basic implementation of `ArrayInterface`, to minimize
* the effort required to implement this interface.
*
* @template T
- * @template-implements ArrayInterface
+ * @implements ArrayInterface
*/
abstract class AbstractArray implements ArrayInterface
{
@@ -34,7 +33,7 @@ abstract class AbstractArray implements ArrayInterface
*
* @var array
*/
- protected $data = [];
+ protected array $data = [];
/**
* Constructs a new array object.
@@ -43,7 +42,7 @@ abstract class AbstractArray implements ArrayInterface
*/
public function __construct(array $data = [])
{
- // Invoke offsetSet() for each value added; in this way, sub-classes
+ // Invoke offsetSet() for each value added; in this way, subclasses
// may provide additional logic about values added to the array object.
foreach ($data as $key => $value) {
$this[$key] = $value;
@@ -55,7 +54,7 @@ abstract class AbstractArray implements ArrayInterface
*
* @link http://php.net/manual/en/iteratoraggregate.getiterator.php IteratorAggregate::getIterator()
*
- * @return Traversable
+ * @return Traversable
*/
public function getIterator(): Traversable
{
@@ -69,7 +68,7 @@ abstract class AbstractArray implements ArrayInterface
*
* @param array-key $offset The offset to check.
*/
- public function offsetExists($offset): bool
+ public function offsetExists(mixed $offset): bool
{
return isset($this->data[$offset]);
}
@@ -81,13 +80,12 @@ abstract class AbstractArray implements ArrayInterface
*
* @param array-key $offset The offset for which a value should be returned.
*
- * @return T|null the value stored at the offset, or null if the offset
+ * @return T the value stored at the offset, or null if the offset
* does not exist.
*/
- #[\ReturnTypeWillChange]
- public function offsetGet($offset)
+ public function offsetGet(mixed $offset): mixed
{
- return $this->data[$offset] ?? null;
+ return $this->data[$offset];
}
/**
@@ -95,12 +93,11 @@ abstract class AbstractArray implements ArrayInterface
*
* @link http://php.net/manual/en/arrayaccess.offsetset.php ArrayAccess::offsetSet()
*
- * @param array-key|null $offset The offset to set. If `null`, the value may be
- * set at a numerically-indexed offset.
+ * @param array-key | null $offset The offset to set. If `null`, the value
+ * may be set at a numerically-indexed offset.
* @param T $value The value to set at the given offset.
*/
- // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
- public function offsetSet($offset, $value): void
+ public function offsetSet(mixed $offset, mixed $value): void
{
if ($offset === null) {
$this->data[] = $value;
@@ -116,50 +113,34 @@ abstract class AbstractArray implements ArrayInterface
*
* @param array-key $offset The offset to remove from the array.
*/
- public function offsetUnset($offset): void
+ public function offsetUnset(mixed $offset): void
{
unset($this->data[$offset]);
}
/**
- * Returns a serialized string representation of this array object.
+ * Returns data suitable for PHP serialization.
*
- * @link http://php.net/manual/en/serializable.serialize.php Serializable::serialize()
+ * @link https://www.php.net/manual/en/language.oop5.magic.php#language.oop5.magic.serialize
+ * @link https://www.php.net/serialize
*
- * @return string a PHP serialized string.
+ * @return array
*/
- public function serialize(): string
+ public function __serialize(): array
{
- return serialize($this->data);
- }
-
- public function __serialize()
- {
- return $this->serialize();
+ return $this->data;
}
/**
- * Converts a serialized string representation into an instance object.
+ * Adds unserialized data to the object.
*
- * @link http://php.net/manual/en/serializable.unserialize.php Serializable::unserialize()
- *
- * @param string $serialized A PHP serialized string to unserialize.
- *
- * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
+ * @param array $data
*/
- public function unserialize($serialized): void
+ public function __unserialize(array $data): void
{
- /** @var array $data */
- $data = unserialize($serialized, ['allowed_classes' => false]);
-
$this->data = $data;
}
- public function __unserialize(array $data)
- {
- $this->unserialize($data);
- }
-
/**
* Returns the number of items in this array.
*
@@ -185,6 +166,6 @@ abstract class AbstractArray implements ArrayInterface
public function isEmpty(): bool
{
- return count($this->data) === 0;
+ return $this->data === [];
}
}
diff --git a/vendor/ramsey/collection/src/AbstractCollection.php b/vendor/ramsey/collection/src/AbstractCollection.php
index f803f42..2f006b9 100644
--- a/vendor/ramsey/collection/src/AbstractCollection.php
+++ b/vendor/ramsey/collection/src/AbstractCollection.php
@@ -17,24 +17,27 @@ namespace Ramsey\Collection;
use Closure;
use Ramsey\Collection\Exception\CollectionMismatchException;
use Ramsey\Collection\Exception\InvalidArgumentException;
-use Ramsey\Collection\Exception\InvalidSortOrderException;
-use Ramsey\Collection\Exception\OutOfBoundsException;
+use Ramsey\Collection\Exception\InvalidPropertyOrMethod;
+use Ramsey\Collection\Exception\NoSuchElementException;
+use Ramsey\Collection\Exception\UnsupportedOperationException;
use Ramsey\Collection\Tool\TypeTrait;
use Ramsey\Collection\Tool\ValueExtractorTrait;
use Ramsey\Collection\Tool\ValueToStringTrait;
use function array_filter;
+use function array_key_first;
+use function array_key_last;
use function array_map;
use function array_merge;
+use function array_reduce;
use function array_search;
use function array_udiff;
use function array_uintersect;
-use function current;
-use function end;
use function in_array;
-use function reset;
+use function is_int;
+use function is_object;
+use function spl_object_id;
use function sprintf;
-use function unserialize;
use function usort;
/**
@@ -42,8 +45,8 @@ use function usort;
* minimize the effort required to implement this interface
*
* @template T
- * @template-extends AbstractArray
- * @template-implements CollectionInterface
+ * @extends AbstractArray
+ * @implements CollectionInterface
*/
abstract class AbstractCollection extends AbstractArray implements CollectionInterface
{
@@ -52,32 +55,29 @@ abstract class AbstractCollection extends AbstractArray implements CollectionInt
use ValueExtractorTrait;
/**
- * @inheritDoc
+ * @throws InvalidArgumentException if $element is of the wrong type.
*/
- public function add($element): bool
+ public function add(mixed $element): bool
{
$this[] = $element;
return true;
}
- /**
- * @inheritDoc
- */
- public function contains($element, bool $strict = true): bool
+ public function contains(mixed $element, bool $strict = true): bool
{
return in_array($element, $this->data, $strict);
}
/**
- * @inheritDoc
+ * @throws InvalidArgumentException if $element is of the wrong type.
*/
- public function offsetSet($offset, $value): void
+ public function offsetSet(mixed $offset, mixed $value): void
{
if ($this->checkType($this->getType(), $value) === false) {
throw new InvalidArgumentException(
'Value must be of type ' . $this->getType() . '; value is '
- . $this->toolValueToString($value)
+ . $this->toolValueToString($value),
);
}
@@ -88,13 +88,10 @@ abstract class AbstractCollection extends AbstractArray implements CollectionInt
}
}
- /**
- * @inheritDoc
- */
- public function remove($element): bool
+ public function remove(mixed $element): bool
{
if (($position = array_search($element, $this->data, true)) !== false) {
- unset($this->data[$position]);
+ unset($this[$position]);
return true;
}
@@ -103,6 +100,11 @@ abstract class AbstractCollection extends AbstractArray implements CollectionInt
}
/**
+ * @throws InvalidPropertyOrMethod if the $propertyOrMethod does not exist
+ * on the elements in this collection.
+ * @throws UnsupportedOperationException if unable to call column() on this
+ * collection.
+ *
* @inheritDoc
*/
public function column(string $propertyOrMethod): array
@@ -110,77 +112,74 @@ abstract class AbstractCollection extends AbstractArray implements CollectionInt
$temp = [];
foreach ($this->data as $item) {
- /** @var mixed $value */
- $value = $this->extractValue($item, $propertyOrMethod);
-
- /** @psalm-suppress MixedAssignment */
- $temp[] = $value;
+ $temp[] = $this->extractValue($item, $propertyOrMethod);
}
return $temp;
}
/**
- * @inheritDoc
+ * @return T
+ *
+ * @throws NoSuchElementException if this collection is empty.
*/
- public function first()
+ public function first(): mixed
{
- if ($this->isEmpty()) {
- throw new OutOfBoundsException('Can\'t determine first item. Collection is empty');
+ $firstIndex = array_key_first($this->data);
+
+ if ($firstIndex === null) {
+ throw new NoSuchElementException('Can\'t determine first item. Collection is empty');
}
- reset($this->data);
-
- /** @var T $first */
- $first = current($this->data);
-
- return $first;
+ return $this->data[$firstIndex];
}
/**
- * @inheritDoc
+ * @return T
+ *
+ * @throws NoSuchElementException if this collection is empty.
*/
- public function last()
+ public function last(): mixed
{
- if ($this->isEmpty()) {
- throw new OutOfBoundsException('Can\'t determine last item. Collection is empty');
+ $lastIndex = array_key_last($this->data);
+
+ if ($lastIndex === null) {
+ throw new NoSuchElementException('Can\'t determine last item. Collection is empty');
}
- /** @var T $item */
- $item = end($this->data);
- reset($this->data);
-
- return $item;
+ return $this->data[$lastIndex];
}
- public function sort(string $propertyOrMethod, string $order = self::SORT_ASC): CollectionInterface
+ /**
+ * @return CollectionInterface
+ *
+ * @throws InvalidPropertyOrMethod if the $propertyOrMethod does not exist
+ * on the elements in this collection.
+ * @throws UnsupportedOperationException if unable to call sort() on this
+ * collection.
+ */
+ public function sort(?string $propertyOrMethod = null, Sort $order = Sort::Ascending): CollectionInterface
{
- if (!in_array($order, [self::SORT_ASC, self::SORT_DESC], true)) {
- throw new InvalidSortOrderException('Invalid sort order given: ' . $order);
- }
-
$collection = clone $this;
usort(
$collection->data,
- /**
- * @param T $a
- * @param T $b
- */
- function ($a, $b) use ($propertyOrMethod, $order): int {
- /** @var mixed $aValue */
+ function (mixed $a, mixed $b) use ($propertyOrMethod, $order): int {
$aValue = $this->extractValue($a, $propertyOrMethod);
-
- /** @var mixed $bValue */
$bValue = $this->extractValue($b, $propertyOrMethod);
- return ($aValue <=> $bValue) * ($order === self::SORT_DESC ? -1 : 1);
- }
+ return ($aValue <=> $bValue) * ($order === Sort::Descending ? -1 : 1);
+ },
);
return $collection;
}
+ /**
+ * @param callable(T): bool $callback A callable to use for filtering elements.
+ *
+ * @return CollectionInterface
+ */
public function filter(callable $callback): CollectionInterface
{
$collection = clone $this;
@@ -190,23 +189,56 @@ abstract class AbstractCollection extends AbstractArray implements CollectionInt
}
/**
- * {@inheritdoc}
+ * @return CollectionInterface
+ *
+ * @throws InvalidPropertyOrMethod if the $propertyOrMethod does not exist
+ * on the elements in this collection.
+ * @throws UnsupportedOperationException if unable to call where() on this
+ * collection.
*/
- public function where(string $propertyOrMethod, $value): CollectionInterface
+ public function where(?string $propertyOrMethod, mixed $value): CollectionInterface
{
- return $this->filter(function ($item) use ($propertyOrMethod, $value) {
- /** @var mixed $accessorValue */
- $accessorValue = $this->extractValue($item, $propertyOrMethod);
-
- return $accessorValue === $value;
- });
+ return $this->filter(
+ fn (mixed $item): bool => $this->extractValue($item, $propertyOrMethod) === $value,
+ );
}
+ /**
+ * @param callable(T): TCallbackReturn $callback A callable to apply to each
+ * item of the collection.
+ *
+ * @return CollectionInterface
+ *
+ * @template TCallbackReturn
+ */
public function map(callable $callback): CollectionInterface
{
return new Collection('mixed', array_map($callback, $this->data));
}
+ /**
+ * @param callable(TCarry, T): TCarry $callback A callable to apply to each
+ * item of the collection to reduce it to a single value.
+ * @param TCarry $initial This is the initial value provided to the callback.
+ *
+ * @return TCarry
+ *
+ * @template TCarry
+ */
+ public function reduce(callable $callback, mixed $initial): mixed
+ {
+ return array_reduce($this->data, $callback, $initial);
+ }
+
+ /**
+ * @param CollectionInterface $other The collection to check for divergent
+ * items.
+ *
+ * @return CollectionInterface
+ *
+ * @throws CollectionMismatchException if the compared collections are of
+ * differing types.
+ */
public function diff(CollectionInterface $other): CollectionInterface
{
$this->compareCollectionTypes($other);
@@ -214,71 +246,79 @@ abstract class AbstractCollection extends AbstractArray implements CollectionInt
$diffAtoB = array_udiff($this->data, $other->toArray(), $this->getComparator());
$diffBtoA = array_udiff($other->toArray(), $this->data, $this->getComparator());
- /** @var array $diff */
- $diff = array_merge($diffAtoB, $diffBtoA);
-
$collection = clone $this;
- $collection->data = $diff;
+ $collection->data = array_merge($diffAtoB, $diffBtoA);
return $collection;
}
+ /**
+ * @param CollectionInterface $other The collection to check for
+ * intersecting items.
+ *
+ * @return CollectionInterface
+ *
+ * @throws CollectionMismatchException if the compared collections are of
+ * differing types.
+ */
public function intersect(CollectionInterface $other): CollectionInterface
{
$this->compareCollectionTypes($other);
- /** @var array $intersect */
- $intersect = array_uintersect($this->data, $other->toArray(), $this->getComparator());
-
$collection = clone $this;
- $collection->data = $intersect;
+ $collection->data = array_uintersect($this->data, $other->toArray(), $this->getComparator());
return $collection;
}
+ /**
+ * @param CollectionInterface ...$collections The collections to merge.
+ *
+ * @return CollectionInterface
+ *
+ * @throws CollectionMismatchException if unable to merge any of the given
+ * collections or items within the given collections due to type
+ * mismatch errors.
+ */
public function merge(CollectionInterface ...$collections): CollectionInterface
{
- $temp = [$this->data];
+ $mergedCollection = clone $this;
foreach ($collections as $index => $collection) {
if (!$collection instanceof static) {
throw new CollectionMismatchException(
- sprintf('Collection with index %d must be of type %s', $index, static::class)
+ sprintf('Collection with index %d must be of type %s', $index, static::class),
);
}
// When using generics (Collection.php, Set.php, etc),
// we also need to make sure that the internal types match each other
- if ($collection->getType() !== $this->getType()) {
+ if ($this->getUniformType($collection) !== $this->getUniformType($this)) {
throw new CollectionMismatchException(
- sprintf('Collection items in collection with index %d must be of type %s', $index, $this->getType())
+ sprintf(
+ 'Collection items in collection with index %d must be of type %s',
+ $index,
+ $this->getType(),
+ ),
);
}
- $temp[] = $collection->toArray();
+ foreach ($collection as $key => $value) {
+ if (is_int($key)) {
+ $mergedCollection[] = $value;
+ } else {
+ $mergedCollection[$key] = $value;
+ }
+ }
}
- $merge = array_merge(...$temp);
-
- $collection = clone $this;
- $collection->data = $merge;
-
- return $collection;
- }
-
- /**
- * @inheritDoc
- */
- public function unserialize($serialized): void
- {
- /** @var array $data */
- $data = unserialize($serialized, ['allowed_classes' => [$this->getType()]]);
-
- $this->data = $data;
+ return $mergedCollection;
}
/**
* @param CollectionInterface $other
+ *
+ * @throws CollectionMismatchException
*/
private function compareCollectionTypes(CollectionInterface $other): void
{
@@ -288,29 +328,38 @@ abstract class AbstractCollection extends AbstractArray implements CollectionInt
// When using generics (Collection.php, Set.php, etc),
// we also need to make sure that the internal types match each other
- if ($other->getType() !== $this->getType()) {
+ if ($this->getUniformType($other) !== $this->getUniformType($this)) {
throw new CollectionMismatchException('Collection items must be of type ' . $this->getType());
}
}
private function getComparator(): Closure
{
- return /**
- * @param T $a
- * @param T $b
- */
- function ($a, $b): int {
- // If the two values are object, we convert them to unique scalars.
- // If the collection contains mixed values (unlikely) where some are objects
- // and some are not, we leave them as they are.
- // The comparator should still work and the result of $a < $b should
- // be consistent but unpredictable since not documented.
- if (is_object($a) && is_object($b)) {
- $a = spl_object_id($a);
- $b = spl_object_id($b);
- }
+ return function (mixed $a, mixed $b): int {
+ // If the two values are object, we convert them to unique scalars.
+ // If the collection contains mixed values (unlikely) where some are objects
+ // and some are not, we leave them as they are.
+ // The comparator should still work and the result of $a < $b should
+ // be consistent but unpredictable since not documented.
+ if (is_object($a) && is_object($b)) {
+ $a = spl_object_id($a);
+ $b = spl_object_id($b);
+ }
- return $a === $b ? 0 : ($a < $b ? 1 : -1);
- };
+ return $a === $b ? 0 : ($a < $b ? 1 : -1);
+ };
+ }
+
+ /**
+ * @param CollectionInterface $collection
+ */
+ private function getUniformType(CollectionInterface $collection): string
+ {
+ return match ($collection->getType()) {
+ 'integer' => 'int',
+ 'boolean' => 'bool',
+ 'double' => 'float',
+ default => $collection->getType(),
+ };
}
}
diff --git a/vendor/ramsey/collection/src/AbstractSet.php b/vendor/ramsey/collection/src/AbstractSet.php
index 3bd2296..63f8331 100644
--- a/vendor/ramsey/collection/src/AbstractSet.php
+++ b/vendor/ramsey/collection/src/AbstractSet.php
@@ -20,26 +20,27 @@ namespace Ramsey\Collection;
* this specific type of collection.
*
* @template T
- * @template-extends AbstractCollection
+ * @extends AbstractCollection
*/
abstract class AbstractSet extends AbstractCollection
{
- /**
- * @inheritDoc
- */
- public function add($element): bool
+ public function add(mixed $element): bool
{
if ($this->contains($element)) {
return false;
}
- return parent::add($element);
+ // Call offsetSet() on the parent instead of add(), since calling
+ // parent::add() will invoke $this->offsetSet(), which will call
+ // $this->contains() a second time. This can cause performance issues
+ // with extremely large collections. For more information, see
+ // https://github.com/ramsey/collection/issues/68.
+ parent::offsetSet(null, $element);
+
+ return true;
}
- /**
- * @inheritDoc
- */
- public function offsetSet($offset, $value): void
+ public function offsetSet(mixed $offset, mixed $value): void
{
if ($this->contains($value)) {
return;
diff --git a/vendor/ramsey/collection/src/ArrayInterface.php b/vendor/ramsey/collection/src/ArrayInterface.php
index 19fbff3..bc7f6f4 100644
--- a/vendor/ramsey/collection/src/ArrayInterface.php
+++ b/vendor/ramsey/collection/src/ArrayInterface.php
@@ -17,18 +17,18 @@ namespace Ramsey\Collection;
use ArrayAccess;
use Countable;
use IteratorAggregate;
-use Serializable;
/**
* `ArrayInterface` provides traversable array functionality to data types.
*
* @template T
+ * @extends ArrayAccess
+ * @extends IteratorAggregate
*/
interface ArrayInterface extends
ArrayAccess,
Countable,
- IteratorAggregate,
- Serializable
+ IteratorAggregate
{
/**
* Removes all items from this array.
diff --git a/vendor/ramsey/collection/src/Collection.php b/vendor/ramsey/collection/src/Collection.php
index 2f8dedd..3b0f768 100644
--- a/vendor/ramsey/collection/src/Collection.php
+++ b/vendor/ramsey/collection/src/Collection.php
@@ -24,7 +24,7 @@ namespace Ramsey\Collection;
*
* Example usage:
*
- * ``` php
+ * ```
* $collection = new \Ramsey\Collection\Collection('My\\Foo');
* $collection->add(new \My\Foo());
* $collection->add(new \My\Foo());
@@ -37,7 +37,7 @@ namespace Ramsey\Collection;
* It is preferable to subclass `AbstractCollection` to create your own typed
* collections. For example:
*
- * ``` php
+ * ```
* namespace My\Foo;
*
* class FooCollection extends \Ramsey\Collection\AbstractCollection
@@ -51,7 +51,7 @@ namespace Ramsey\Collection;
*
* And then use it similarly to the earlier example:
*
- * ``` php
+ * ```
* $fooCollection = new \My\Foo\FooCollection();
* $fooCollection->add(new \My\Foo());
* $fooCollection->add(new \My\Foo());
@@ -64,38 +64,27 @@ namespace Ramsey\Collection;
* The benefit with this approach is that you may do type-checking on the
* collection object:
*
- * ``` php
+ * ```
* if ($collection instanceof \My\Foo\FooCollection) {
* // the collection is a collection of My\Foo objects
* }
* ```
*
* @template T
- * @template-extends AbstractCollection
+ * @extends AbstractCollection
*/
class Collection extends AbstractCollection
{
- /**
- * The type of elements stored in this collection.
- *
- * A collection's type is immutable once it is set. For this reason, this
- * property is set private.
- *
- * @var string
- */
- private $collectionType;
-
/**
* Constructs a collection object of the specified type, optionally with the
* specified data.
*
- * @param string $collectionType The type (FQCN) associated with this
+ * @param string $collectionType The type or class name associated with this
* collection.
* @param array $data The initial items to store in the collection.
*/
- public function __construct(string $collectionType, array $data = [])
+ public function __construct(private readonly string $collectionType, array $data = [])
{
- $this->collectionType = $collectionType;
parent::__construct($data);
}
diff --git a/vendor/ramsey/collection/src/CollectionInterface.php b/vendor/ramsey/collection/src/CollectionInterface.php
index dfef6ca..3ffbb16 100644
--- a/vendor/ramsey/collection/src/CollectionInterface.php
+++ b/vendor/ramsey/collection/src/CollectionInterface.php
@@ -14,27 +14,23 @@ declare(strict_types=1);
namespace Ramsey\Collection;
+use Ramsey\Collection\Exception\CollectionMismatchException;
+use Ramsey\Collection\Exception\InvalidArgumentException;
+use Ramsey\Collection\Exception\InvalidPropertyOrMethod;
+use Ramsey\Collection\Exception\NoSuchElementException;
+use Ramsey\Collection\Exception\UnsupportedOperationException;
+
/**
- * A collection represents a group of objects, known as its elements.
+ * A collection represents a group of values, known as its elements.
*
* Some collections allow duplicate elements and others do not. Some are ordered
* and others unordered.
*
* @template T
- * @template-extends ArrayInterface
+ * @extends ArrayInterface
*/
interface CollectionInterface extends ArrayInterface
{
- /**
- * Ascending sort type.
- */
- public const SORT_ASC = 'asc';
-
- /**
- * Descending sort type.
- */
- public const SORT_DESC = 'desc';
-
/**
* Ensures that this collection contains the specified element (optional
* operation).
@@ -58,9 +54,11 @@ interface CollectionInterface extends ArrayInterface
* @param T $element The element to add to the collection.
*
* @return bool `true` if this collection changed as a result of the call.
+ *
+ * @throws InvalidArgumentException if the collection refuses to add the
+ * $element for any reason other than that it already contains the element.
*/
- // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
- public function add($element): bool;
+ public function add(mixed $element): bool;
/**
* Returns `true` if this collection contains the specified element.
@@ -68,8 +66,7 @@ interface CollectionInterface extends ArrayInterface
* @param T $element The element to check whether the collection contains.
* @param bool $strict Whether to perform a strict type check on the value.
*/
- // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
- public function contains($element, bool $strict = true): bool;
+ public function contains(mixed $element, bool $strict = true): bool;
/**
* Returns the type associated with this collection.
@@ -84,15 +81,20 @@ interface CollectionInterface extends ArrayInterface
*
* @return bool `true` if an element was removed as a result of this call.
*/
- // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
- public function remove($element): bool;
+ public function remove(mixed $element): bool;
/**
- * Returns the values from the given property or method.
+ * Returns the values from the given property, method, or array key.
*
- * @param string $propertyOrMethod The property or method name to filter by.
+ * @param string $propertyOrMethod The name of the property, method, or
+ * array key to evaluate and return.
*
* @return list
+ *
+ * @throws InvalidPropertyOrMethod if the $propertyOrMethod does not exist
+ * on the elements in this collection.
+ * @throws UnsupportedOperationException if unable to call column() on this
+ * collection.
*/
public function column(string $propertyOrMethod): array;
@@ -100,29 +102,41 @@ interface CollectionInterface extends ArrayInterface
* Returns the first item of the collection.
*
* @return T
+ *
+ * @throws NoSuchElementException if this collection is empty.
*/
- public function first();
+ public function first(): mixed;
/**
* Returns the last item of the collection.
*
* @return T
+ *
+ * @throws NoSuchElementException if this collection is empty.
*/
- public function last();
+ public function last(): mixed;
/**
- * Sort the collection by a property or method with the given sort order.
+ * Sort the collection by a property, method, or array key with the given
+ * sort order.
+ *
+ * If $propertyOrMethod is `null`, this will sort by comparing each element.
*
* This will always leave the original collection untouched and will return
* a new one.
*
- * @param string $propertyOrMethod The property or method to sort by.
- * @param string $order The sort order for the resulting collection (one of
- * this interface's `SORT_*` constants).
+ * @param string | null $propertyOrMethod The property, method, or array key
+ * to sort by.
+ * @param Sort $order The sort order for the resulting collection.
*
* @return CollectionInterface
+ *
+ * @throws InvalidPropertyOrMethod if the $propertyOrMethod does not exist
+ * on the elements in this collection.
+ * @throws UnsupportedOperationException if unable to call sort() on this
+ * collection.
*/
- public function sort(string $propertyOrMethod, string $order = self::SORT_ASC): self;
+ public function sort(?string $propertyOrMethod = null, Sort $order = Sort::Ascending): self;
/**
* Filter out items of the collection which don't match the criteria of
@@ -134,24 +148,31 @@ interface CollectionInterface extends ArrayInterface
* See the {@link http://php.net/manual/en/function.array-filter.php PHP array_filter() documentation}
* for examples of how the `$callback` parameter works.
*
- * @param callable(T):bool $callback A callable to use for filtering elements.
+ * @param callable(T): bool $callback A callable to use for filtering elements.
*
* @return CollectionInterface
*/
public function filter(callable $callback): self;
/**
- * Create a new collection where items match the criteria of given callback.
+ * Create a new collection where the result of the given property, method,
+ * or array key of each item in the collection equals the given value.
*
* This will always leave the original collection untouched and will return
* a new one.
*
- * @param string $propertyOrMethod The property or method to evaluate.
+ * @param string | null $propertyOrMethod The property, method, or array key
+ * to evaluate. If `null`, the element itself is compared to $value.
* @param mixed $value The value to match.
*
* @return CollectionInterface
+ *
+ * @throws InvalidPropertyOrMethod if the $propertyOrMethod does not exist
+ * on the elements in this collection.
+ * @throws UnsupportedOperationException if unable to call where() on this
+ * collection.
*/
- public function where(string $propertyOrMethod, $value): self;
+ public function where(?string $propertyOrMethod, mixed $value): self;
/**
* Apply a given callback method on each item of the collection.
@@ -163,7 +184,7 @@ interface CollectionInterface extends ArrayInterface
* See the {@link http://php.net/manual/en/function.array-map.php PHP array_map() documentation}
* for examples of how the `$callback` parameter works.
*
- * @param callable(T):TCallbackReturn $callback A callable to apply to each
+ * @param callable(T): TCallbackReturn $callback A callable to apply to each
* item of the collection.
*
* @return CollectionInterface
@@ -172,6 +193,23 @@ interface CollectionInterface extends ArrayInterface
*/
public function map(callable $callback): self;
+ /**
+ * Apply a given callback method on each item of the collection
+ * to reduce it to a single value.
+ *
+ * See the {@link http://php.net/manual/en/function.array-reduce.php PHP array_reduce() documentation}
+ * for examples of how the `$callback` and `$initial` parameters work.
+ *
+ * @param callable(TCarry, T): TCarry $callback A callable to apply to each
+ * item of the collection to reduce it to a single value.
+ * @param TCarry $initial This is the initial value provided to the callback.
+ *
+ * @return TCarry
+ *
+ * @template TCarry
+ */
+ public function reduce(callable $callback, mixed $initial): mixed;
+
/**
* Create a new collection with divergent items between current and given
* collection.
@@ -180,6 +218,9 @@ interface CollectionInterface extends ArrayInterface
* items.
*
* @return CollectionInterface
+ *
+ * @throws CollectionMismatchException if the compared collections are of
+ * differing types.
*/
public function diff(CollectionInterface $other): self;
@@ -191,6 +232,9 @@ interface CollectionInterface extends ArrayInterface
* intersecting items.
*
* @return CollectionInterface
+ *
+ * @throws CollectionMismatchException if the compared collections are of
+ * differing types.
*/
public function intersect(CollectionInterface $other): self;
@@ -200,6 +244,10 @@ interface CollectionInterface extends ArrayInterface
* @param CollectionInterface ...$collections The collections to merge.
*
* @return CollectionInterface
+ *
+ * @throws CollectionMismatchException if unable to merge any of the given
+ * collections or items within the given collections due to type
+ * mismatch errors.
*/
public function merge(CollectionInterface ...$collections): self;
}
diff --git a/vendor/ramsey/collection/src/DoubleEndedQueue.php b/vendor/ramsey/collection/src/DoubleEndedQueue.php
index 6ebdca5..62947a2 100644
--- a/vendor/ramsey/collection/src/DoubleEndedQueue.php
+++ b/vendor/ramsey/collection/src/DoubleEndedQueue.php
@@ -17,171 +17,150 @@ namespace Ramsey\Collection;
use Ramsey\Collection\Exception\InvalidArgumentException;
use Ramsey\Collection\Exception\NoSuchElementException;
+use function array_key_last;
+use function array_pop;
+use function array_unshift;
+
/**
* This class provides a basic implementation of `DoubleEndedQueueInterface`, to
* minimize the effort required to implement this interface.
*
* @template T
- * @template-extends Queue
- * @template-implements DoubleEndedQueueInterface
+ * @extends Queue
+ * @implements DoubleEndedQueueInterface
*/
class DoubleEndedQueue extends Queue implements DoubleEndedQueueInterface
{
/**
- * Index of the last element in the queue.
+ * Constructs a double-ended queue (dequeue) object of the specified type,
+ * optionally with the specified data.
*
- * @var int
+ * @param string $queueType The type or class name associated with this dequeue.
+ * @param array $data The initial items to store in the dequeue.
*/
- private $tail = -1;
-
- /**
- * @inheritDoc
- */
- public function offsetSet($offset, $value): void
+ public function __construct(private readonly string $queueType, array $data = [])
{
- if ($this->checkType($this->getType(), $value) === false) {
- throw new InvalidArgumentException(
- 'Value must be of type ' . $this->getType() . '; value is '
- . $this->toolValueToString($value)
- );
- }
-
- $this->tail++;
-
- $this->data[$this->tail] = $value;
+ parent::__construct($this->queueType, $data);
}
/**
- * @inheritDoc
+ * @throws InvalidArgumentException if $element is of the wrong type
*/
- public function addFirst($element): bool
+ public function addFirst(mixed $element): bool
{
if ($this->checkType($this->getType(), $element) === false) {
throw new InvalidArgumentException(
'Value must be of type ' . $this->getType() . '; value is '
- . $this->toolValueToString($element)
+ . $this->toolValueToString($element),
);
}
- $this->index--;
-
- $this->data[$this->index] = $element;
+ array_unshift($this->data, $element);
return true;
}
/**
- * @inheritDoc
+ * @throws InvalidArgumentException if $element is of the wrong type
*/
- public function addLast($element): bool
+ public function addLast(mixed $element): bool
{
return $this->add($element);
}
- /**
- * @inheritDoc
- */
- public function offerFirst($element): bool
+ public function offerFirst(mixed $element): bool
{
try {
return $this->addFirst($element);
- } catch (InvalidArgumentException $e) {
+ } catch (InvalidArgumentException) {
return false;
}
}
- /**
- * @inheritDoc
- */
- public function offerLast($element): bool
+ public function offerLast(mixed $element): bool
{
return $this->offer($element);
}
/**
- * @inheritDoc
+ * @return T the first element in this queue.
+ *
+ * @throws NoSuchElementException if the queue is empty
*/
- public function removeFirst()
+ public function removeFirst(): mixed
{
return $this->remove();
}
/**
- * @inheritDoc
+ * @return T the last element in this queue.
+ *
+ * @throws NoSuchElementException if this queue is empty.
*/
- public function removeLast()
+ public function removeLast(): mixed
{
- $tail = $this->pollLast();
-
- if ($tail === null) {
- throw new NoSuchElementException('Can\'t return element from Queue. Queue is empty.');
- }
-
- return $tail;
+ return $this->pollLast() ?? throw new NoSuchElementException(
+ 'Can\'t return element from Queue. Queue is empty.',
+ );
}
/**
- * @inheritDoc
+ * @return T | null the head of this queue, or `null` if this queue is empty.
*/
- public function pollFirst()
+ public function pollFirst(): mixed
{
return $this->poll();
}
/**
- * @inheritDoc
+ * @return T | null the tail of this queue, or `null` if this queue is empty.
*/
- public function pollLast()
+ public function pollLast(): mixed
{
- if ($this->count() === 0) {
- return null;
- }
-
- $tail = $this[$this->tail];
-
- unset($this[$this->tail]);
- $this->tail--;
-
- return $tail;
+ return array_pop($this->data);
}
/**
- * @inheritDoc
+ * @return T the head of this queue.
+ *
+ * @throws NoSuchElementException if this queue is empty.
*/
- public function firstElement()
+ public function firstElement(): mixed
{
return $this->element();
}
/**
- * @inheritDoc
+ * @return T the tail of this queue.
+ *
+ * @throws NoSuchElementException if this queue is empty.
*/
- public function lastElement()
+ public function lastElement(): mixed
{
- if ($this->count() === 0) {
- throw new NoSuchElementException('Can\'t return element from Queue. Queue is empty.');
- }
-
- return $this->data[$this->tail];
+ return $this->peekLast() ?? throw new NoSuchElementException(
+ 'Can\'t return element from Queue. Queue is empty.',
+ );
}
/**
- * @inheritDoc
+ * @return T | null the head of this queue, or `null` if this queue is empty.
*/
- public function peekFirst()
+ public function peekFirst(): mixed
{
return $this->peek();
}
/**
- * @inheritDoc
+ * @return T | null the tail of this queue, or `null` if this queue is empty.
*/
- public function peekLast()
+ public function peekLast(): mixed
{
- if ($this->count() === 0) {
+ $lastIndex = array_key_last($this->data);
+
+ if ($lastIndex === null) {
return null;
}
- return $this->data[$this->tail];
+ return $this->data[$lastIndex];
}
}
diff --git a/vendor/ramsey/collection/src/DoubleEndedQueueInterface.php b/vendor/ramsey/collection/src/DoubleEndedQueueInterface.php
index 67aae5e..15cc0e9 100644
--- a/vendor/ramsey/collection/src/DoubleEndedQueueInterface.php
+++ b/vendor/ramsey/collection/src/DoubleEndedQueueInterface.php
@@ -15,6 +15,7 @@ declare(strict_types=1);
namespace Ramsey\Collection;
use Ramsey\Collection\Exception\NoSuchElementException;
+use RuntimeException;
/**
* A linear collection that supports element insertion and removal at both ends.
@@ -160,7 +161,7 @@ use Ramsey\Collection\Exception\NoSuchElementException;
* empty.
*
* @template T
- * @template-extends QueueInterface
+ * @extends QueueInterface
*/
interface DoubleEndedQueueInterface extends QueueInterface
{
@@ -175,13 +176,12 @@ interface DoubleEndedQueueInterface extends QueueInterface
*
* @return bool `true` if this queue changed as a result of the call.
*
- * @throws \RuntimeException if a queue refuses to add a particular element
+ * @throws RuntimeException if a queue refuses to add a particular element
* for any reason other than that it already contains the element.
* Implementations should use a more-specific exception that extends
* `\RuntimeException`.
*/
- // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
- public function addFirst($element): bool;
+ public function addFirst(mixed $element): bool;
/**
* Inserts the specified element at the end of this queue if it is possible
@@ -196,13 +196,12 @@ interface DoubleEndedQueueInterface extends QueueInterface
*
* @return bool `true` if this queue changed as a result of the call.
*
- * @throws \RuntimeException if a queue refuses to add a particular element
+ * @throws RuntimeException if a queue refuses to add a particular element
* for any reason other than that it already contains the element.
* Implementations should use a more-specific exception that extends
* `\RuntimeException`.
*/
- // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
- public function addLast($element): bool;
+ public function addLast(mixed $element): bool;
/**
* Inserts the specified element at the front of this queue if it is
@@ -216,8 +215,7 @@ interface DoubleEndedQueueInterface extends QueueInterface
*
* @return bool `true` if the element was added to this queue, else `false`.
*/
- // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
- public function offerFirst($element): bool;
+ public function offerFirst(mixed $element): bool;
/**
* Inserts the specified element at the end of this queue if it is possible
@@ -231,8 +229,7 @@ interface DoubleEndedQueueInterface extends QueueInterface
*
* @return bool `true` if the element was added to this queue, else `false`.
*/
- // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
- public function offerLast($element): bool;
+ public function offerLast(mixed $element): bool;
/**
* Retrieves and removes the head of this queue.
@@ -244,7 +241,7 @@ interface DoubleEndedQueueInterface extends QueueInterface
*
* @throws NoSuchElementException if this queue is empty.
*/
- public function removeFirst();
+ public function removeFirst(): mixed;
/**
* Retrieves and removes the tail of this queue.
@@ -256,23 +253,23 @@ interface DoubleEndedQueueInterface extends QueueInterface
*
* @throws NoSuchElementException if this queue is empty.
*/
- public function removeLast();
+ public function removeLast(): mixed;
/**
* Retrieves and removes the head of this queue, or returns `null` if this
* queue is empty.
*
- * @return T|null the head of this queue, or `null` if this queue is empty.
+ * @return T | null the head of this queue, or `null` if this queue is empty.
*/
- public function pollFirst();
+ public function pollFirst(): mixed;
/**
* Retrieves and removes the tail of this queue, or returns `null` if this
* queue is empty.
*
- * @return T|null the tail of this queue, or `null` if this queue is empty.
+ * @return T | null the tail of this queue, or `null` if this queue is empty.
*/
- public function pollLast();
+ public function pollLast(): mixed;
/**
* Retrieves, but does not remove, the head of this queue.
@@ -284,7 +281,7 @@ interface DoubleEndedQueueInterface extends QueueInterface
*
* @throws NoSuchElementException if this queue is empty.
*/
- public function firstElement();
+ public function firstElement(): mixed;
/**
* Retrieves, but does not remove, the tail of this queue.
@@ -296,21 +293,21 @@ interface DoubleEndedQueueInterface extends QueueInterface
*
* @throws NoSuchElementException if this queue is empty.
*/
- public function lastElement();
+ public function lastElement(): mixed;
/**
* Retrieves, but does not remove, the head of this queue, or returns `null`
* if this queue is empty.
*
- * @return T|null the head of this queue, or `null` if this queue is empty.
+ * @return T | null the head of this queue, or `null` if this queue is empty.
*/
- public function peekFirst();
+ public function peekFirst(): mixed;
/**
* Retrieves, but does not remove, the tail of this queue, or returns `null`
* if this queue is empty.
*
- * @return T|null the tail of this queue, or `null` if this queue is empty.
+ * @return T | null the tail of this queue, or `null` if this queue is empty.
*/
- public function peekLast();
+ public function peekLast(): mixed;
}
diff --git a/vendor/ramsey/collection/src/Exception/InvalidSortOrderException.php b/vendor/ramsey/collection/src/Exception/CollectionException.php
similarity index 73%
rename from vendor/ramsey/collection/src/Exception/InvalidSortOrderException.php
rename to vendor/ramsey/collection/src/Exception/CollectionException.php
index 9337ccc..4aa92be 100644
--- a/vendor/ramsey/collection/src/Exception/InvalidSortOrderException.php
+++ b/vendor/ramsey/collection/src/Exception/CollectionException.php
@@ -14,9 +14,8 @@ declare(strict_types=1);
namespace Ramsey\Collection\Exception;
-/**
- * Thrown when attempting to use a sort order that is not recognized.
- */
-class InvalidSortOrderException extends \RuntimeException
+use Throwable;
+
+interface CollectionException extends Throwable
{
}
diff --git a/vendor/ramsey/collection/src/Exception/CollectionMismatchException.php b/vendor/ramsey/collection/src/Exception/CollectionMismatchException.php
index d4b335f..42f5be2 100644
--- a/vendor/ramsey/collection/src/Exception/CollectionMismatchException.php
+++ b/vendor/ramsey/collection/src/Exception/CollectionMismatchException.php
@@ -14,9 +14,11 @@ declare(strict_types=1);
namespace Ramsey\Collection\Exception;
+use RuntimeException;
+
/**
* Thrown when attempting to operate on collections of differing types.
*/
-class CollectionMismatchException extends \RuntimeException
+class CollectionMismatchException extends RuntimeException implements CollectionException
{
}
diff --git a/vendor/ramsey/collection/src/Exception/InvalidArgumentException.php b/vendor/ramsey/collection/src/Exception/InvalidArgumentException.php
index dcc3eac..7b41b4a 100644
--- a/vendor/ramsey/collection/src/Exception/InvalidArgumentException.php
+++ b/vendor/ramsey/collection/src/Exception/InvalidArgumentException.php
@@ -14,9 +14,11 @@ declare(strict_types=1);
namespace Ramsey\Collection\Exception;
+use InvalidArgumentException as PhpInvalidArgumentException;
+
/**
* Thrown to indicate an argument is not of the expected type.
*/
-class InvalidArgumentException extends \InvalidArgumentException
+class InvalidArgumentException extends PhpInvalidArgumentException implements CollectionException
{
}
diff --git a/vendor/ramsey/collection/src/Exception/ValueExtractionException.php b/vendor/ramsey/collection/src/Exception/InvalidPropertyOrMethod.php
similarity index 58%
rename from vendor/ramsey/collection/src/Exception/ValueExtractionException.php
rename to vendor/ramsey/collection/src/Exception/InvalidPropertyOrMethod.php
index f6c6cb4..a53be14 100644
--- a/vendor/ramsey/collection/src/Exception/ValueExtractionException.php
+++ b/vendor/ramsey/collection/src/Exception/InvalidPropertyOrMethod.php
@@ -14,9 +14,13 @@ declare(strict_types=1);
namespace Ramsey\Collection\Exception;
+use RuntimeException;
+
/**
- * Thrown when attempting to extract a value for a method or property that does not exist.
+ * Thrown when attempting to evaluate a property, method, or array key
+ * that doesn't exist on an element or cannot otherwise be evaluated in the
+ * current context.
*/
-class ValueExtractionException extends \RuntimeException
+class InvalidPropertyOrMethod extends RuntimeException implements CollectionException
{
}
diff --git a/vendor/ramsey/collection/src/Exception/NoSuchElementException.php b/vendor/ramsey/collection/src/Exception/NoSuchElementException.php
index 9debe8f..cd98f0c 100644
--- a/vendor/ramsey/collection/src/Exception/NoSuchElementException.php
+++ b/vendor/ramsey/collection/src/Exception/NoSuchElementException.php
@@ -14,9 +14,11 @@ declare(strict_types=1);
namespace Ramsey\Collection\Exception;
+use RuntimeException;
+
/**
* Thrown when attempting to access an element that does not exist.
*/
-class NoSuchElementException extends \RuntimeException
+class NoSuchElementException extends RuntimeException implements CollectionException
{
}
diff --git a/vendor/ramsey/collection/src/Exception/OutOfBoundsException.php b/vendor/ramsey/collection/src/Exception/OutOfBoundsException.php
index 4e9d16f..c75294e 100644
--- a/vendor/ramsey/collection/src/Exception/OutOfBoundsException.php
+++ b/vendor/ramsey/collection/src/Exception/OutOfBoundsException.php
@@ -14,9 +14,11 @@ declare(strict_types=1);
namespace Ramsey\Collection\Exception;
+use OutOfBoundsException as PhpOutOfBoundsException;
+
/**
* Thrown when attempting to access an element out of the range of the collection.
*/
-class OutOfBoundsException extends \OutOfBoundsException
+class OutOfBoundsException extends PhpOutOfBoundsException implements CollectionException
{
}
diff --git a/vendor/ramsey/collection/src/Exception/UnsupportedOperationException.php b/vendor/ramsey/collection/src/Exception/UnsupportedOperationException.php
index 8f45e58..d074f45 100644
--- a/vendor/ramsey/collection/src/Exception/UnsupportedOperationException.php
+++ b/vendor/ramsey/collection/src/Exception/UnsupportedOperationException.php
@@ -14,9 +14,11 @@ declare(strict_types=1);
namespace Ramsey\Collection\Exception;
+use RuntimeException;
+
/**
* Thrown to indicate that the requested operation is not supported.
*/
-class UnsupportedOperationException extends \RuntimeException
+class UnsupportedOperationException extends RuntimeException implements CollectionException
{
}
diff --git a/vendor/ramsey/collection/src/GenericArray.php b/vendor/ramsey/collection/src/GenericArray.php
index 9b95df3..2b079aa 100644
--- a/vendor/ramsey/collection/src/GenericArray.php
+++ b/vendor/ramsey/collection/src/GenericArray.php
@@ -17,7 +17,7 @@ namespace Ramsey\Collection;
/**
* `GenericArray` represents a standard array object.
*
- * @template-extends AbstractArray
+ * @extends AbstractArray
*/
class GenericArray extends AbstractArray
{
diff --git a/vendor/ramsey/collection/src/Map/AbstractMap.php b/vendor/ramsey/collection/src/Map/AbstractMap.php
index 70f7116..92f23e6 100644
--- a/vendor/ramsey/collection/src/Map/AbstractMap.php
+++ b/vendor/ramsey/collection/src/Map/AbstractMap.php
@@ -16,48 +16,64 @@ namespace Ramsey\Collection\Map;
use Ramsey\Collection\AbstractArray;
use Ramsey\Collection\Exception\InvalidArgumentException;
+use Traversable;
use function array_key_exists;
use function array_keys;
use function in_array;
+use function var_export;
/**
* This class provides a basic implementation of `MapInterface`, to minimize the
* effort required to implement this interface.
*
+ * @template K of array-key
* @template T
- * @template-extends AbstractArray
- * @template-implements MapInterface
+ * @extends AbstractArray
+ * @implements MapInterface
*/
abstract class AbstractMap extends AbstractArray implements MapInterface
{
/**
+ * @param array $data The initial items to add to this map.
+ */
+ public function __construct(array $data = [])
+ {
+ parent::__construct($data);
+ }
+
+ /**
+ * @return Traversable
+ */
+ public function getIterator(): Traversable
+ {
+ return parent::getIterator();
+ }
+
+ /**
+ * @param K $offset The offset to set
+ * @param T $value The value to set at the given offset.
+ *
* @inheritDoc
*/
- public function offsetSet($offset, $value): void
+ public function offsetSet(mixed $offset, mixed $value): void
{
if ($offset === null) {
throw new InvalidArgumentException(
'Map elements are key/value pairs; a key must be provided for '
- . 'value ' . var_export($value, true)
+ . 'value ' . var_export($value, true),
);
}
$this->data[$offset] = $value;
}
- /**
- * @inheritDoc
- */
- public function containsKey($key): bool
+ public function containsKey(int | string $key): bool
{
return array_key_exists($key, $this->data);
}
- /**
- * @inheritDoc
- */
- public function containsValue($value): bool
+ public function containsValue(mixed $value): bool
{
return in_array($value, $this->data, true);
}
@@ -67,25 +83,29 @@ abstract class AbstractMap extends AbstractArray implements MapInterface
*/
public function keys(): array
{
+ /** @var list */
return array_keys($this->data);
}
/**
- * @inheritDoc
+ * @param K $key The key to return from the map.
+ * @param T | null $defaultValue The default value to use if `$key` is not found.
+ *
+ * @return T | null the value or `null` if the key could not be found.
*/
- public function get($key, $defaultValue = null)
+ public function get(int | string $key, mixed $defaultValue = null): mixed
{
- if (!$this->containsKey($key)) {
- return $defaultValue;
- }
-
- return $this[$key];
+ return $this[$key] ?? $defaultValue;
}
/**
- * @inheritDoc
+ * @param K $key The key to put or replace in the map.
+ * @param T $value The value to store at `$key`.
+ *
+ * @return T | null the previous value associated with key, or `null` if
+ * there was no mapping for `$key`.
*/
- public function put($key, $value)
+ public function put(int | string $key, mixed $value): mixed
{
$previousValue = $this->get($key);
$this[$key] = $value;
@@ -94,9 +114,13 @@ abstract class AbstractMap extends AbstractArray implements MapInterface
}
/**
- * @inheritDoc
+ * @param K $key The key to put in the map.
+ * @param T $value The value to store at `$key`.
+ *
+ * @return T | null the previous value associated with key, or `null` if
+ * there was no mapping for `$key`.
*/
- public function putIfAbsent($key, $value)
+ public function putIfAbsent(int | string $key, mixed $value): mixed
{
$currentValue = $this->get($key);
@@ -108,9 +132,12 @@ abstract class AbstractMap extends AbstractArray implements MapInterface
}
/**
- * @inheritDoc
+ * @param K $key The key to remove from the map.
+ *
+ * @return T | null the previous value associated with key, or `null` if
+ * there was no mapping for `$key`.
*/
- public function remove($key)
+ public function remove(int | string $key): mixed
{
$previousValue = $this->get($key);
unset($this[$key]);
@@ -118,10 +145,7 @@ abstract class AbstractMap extends AbstractArray implements MapInterface
return $previousValue;
}
- /**
- * @inheritDoc
- */
- public function removeIf($key, $value): bool
+ public function removeIf(int | string $key, mixed $value): bool
{
if ($this->get($key) === $value) {
unset($this[$key]);
@@ -133,9 +157,13 @@ abstract class AbstractMap extends AbstractArray implements MapInterface
}
/**
- * @inheritDoc
+ * @param K $key The key to replace.
+ * @param T $value The value to set at `$key`.
+ *
+ * @return T | null the previous value associated with key, or `null` if
+ * there was no mapping for `$key`.
*/
- public function replace($key, $value)
+ public function replace(int | string $key, mixed $value): mixed
{
$currentValue = $this->get($key);
@@ -146,10 +174,7 @@ abstract class AbstractMap extends AbstractArray implements MapInterface
return $currentValue;
}
- /**
- * @inheritDoc
- */
- public function replaceIf($key, $oldValue, $newValue): bool
+ public function replaceIf(int | string $key, mixed $oldValue, mixed $newValue): bool
{
if ($this->get($key) === $oldValue) {
$this[$key] = $newValue;
@@ -159,4 +184,22 @@ abstract class AbstractMap extends AbstractArray implements MapInterface
return false;
}
+
+ /**
+ * @return array
+ */
+ public function __serialize(): array
+ {
+ /** @var array */
+ return parent::__serialize();
+ }
+
+ /**
+ * @return array
+ */
+ public function toArray(): array
+ {
+ /** @var array */
+ return parent::toArray();
+ }
}
diff --git a/vendor/ramsey/collection/src/Map/AbstractTypedMap.php b/vendor/ramsey/collection/src/Map/AbstractTypedMap.php
index baa6793..8b6cc04 100644
--- a/vendor/ramsey/collection/src/Map/AbstractTypedMap.php
+++ b/vendor/ramsey/collection/src/Map/AbstractTypedMap.php
@@ -22,10 +22,10 @@ use Ramsey\Collection\Tool\ValueToStringTrait;
* This class provides a basic implementation of `TypedMapInterface`, to
* minimize the effort required to implement this interface.
*
- * @template K
+ * @template K of array-key
* @template T
- * @template-extends AbstractMap
- * @template-implements TypedMapInterface
+ * @extends AbstractMap
+ * @implements TypedMapInterface
*/
abstract class AbstractTypedMap extends AbstractMap implements TypedMapInterface
{
@@ -33,37 +33,27 @@ abstract class AbstractTypedMap extends AbstractMap implements TypedMapInterface
use ValueToStringTrait;
/**
- * @param K|null $offset
+ * @param K $offset
* @param T $value
*
* @inheritDoc
- *
- * @psalm-suppress MoreSpecificImplementedParamType
*/
- public function offsetSet($offset, $value): void
+ public function offsetSet(mixed $offset, mixed $value): void
{
- if ($offset === null) {
- throw new InvalidArgumentException(
- 'Map elements are key/value pairs; a key must be provided for '
- . 'value ' . var_export($value, true)
- );
- }
-
if ($this->checkType($this->getKeyType(), $offset) === false) {
throw new InvalidArgumentException(
'Key must be of type ' . $this->getKeyType() . '; key is '
- . $this->toolValueToString($offset)
+ . $this->toolValueToString($offset),
);
}
if ($this->checkType($this->getValueType(), $value) === false) {
throw new InvalidArgumentException(
'Value must be of type ' . $this->getValueType() . '; value is '
- . $this->toolValueToString($value)
+ . $this->toolValueToString($value),
);
}
- /** @psalm-suppress MixedArgumentTypeCoercion */
parent::offsetSet($offset, $value);
}
}
diff --git a/vendor/ramsey/collection/src/Map/AssociativeArrayMap.php b/vendor/ramsey/collection/src/Map/AssociativeArrayMap.php
index 3274dc9..34e4e85 100644
--- a/vendor/ramsey/collection/src/Map/AssociativeArrayMap.php
+++ b/vendor/ramsey/collection/src/Map/AssociativeArrayMap.php
@@ -17,8 +17,7 @@ namespace Ramsey\Collection\Map;
/**
* `AssociativeArrayMap` represents a standard associative array object.
*
- * @template T
- * @template-extends AbstractMap
+ * @extends AbstractMap
*/
class AssociativeArrayMap extends AbstractMap
{
diff --git a/vendor/ramsey/collection/src/Map/MapInterface.php b/vendor/ramsey/collection/src/Map/MapInterface.php
index 04e52a2..22ba1bd 100644
--- a/vendor/ramsey/collection/src/Map/MapInterface.php
+++ b/vendor/ramsey/collection/src/Map/MapInterface.php
@@ -21,17 +21,18 @@ use Ramsey\Collection\ArrayInterface;
*
* A map cannot contain duplicate keys; each key can map to at most one value.
*
+ * @template K of array-key
* @template T
- * @template-extends ArrayInterface
+ * @extends ArrayInterface
*/
interface MapInterface extends ArrayInterface
{
/**
* Returns `true` if this map contains a mapping for the specified key.
*
- * @param array-key $key The key to check in the map.
+ * @param K $key The key to check in the map.
*/
- public function containsKey($key): bool;
+ public function containsKey(int | string $key): bool;
/**
* Returns `true` if this map maps one or more keys to the specified value.
@@ -40,13 +41,12 @@ interface MapInterface extends ArrayInterface
*
* @param T $value The value to check in the map.
*/
- // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
- public function containsValue($value): bool;
+ public function containsValue(mixed $value): bool;
/**
* Return an array of the keys contained in this map.
*
- * @return list
+ * @return list
*/
public function keys(): array;
@@ -55,13 +55,12 @@ interface MapInterface extends ArrayInterface
* map contains no mapping for the key, or (optionally) `$defaultValue` if
* this map contains no mapping for the key.
*
- * @param array-key $key The key to return from the map.
- * @param T|null $defaultValue The default value to use if `$key` is not found.
+ * @param K $key The key to return from the map.
+ * @param T | null $defaultValue The default value to use if `$key` is not found.
*
- * @return T|null the value or `null` if the key could not be found.
+ * @return T | null the value or `null` if the key could not be found.
*/
- // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
- public function get($key, $defaultValue = null);
+ public function get(int | string $key, mixed $defaultValue = null): mixed;
/**
* Associates the specified value with the specified key in this map.
@@ -69,14 +68,13 @@ interface MapInterface extends ArrayInterface
* If the map previously contained a mapping for the key, the old value is
* replaced by the specified value.
*
- * @param array-key $key The key to put or replace in the map.
+ * @param K $key The key to put or replace in the map.
* @param T $value The value to store at `$key`.
*
- * @return T|null the previous value associated with key, or `null` if
+ * @return T | null the previous value associated with key, or `null` if
* there was no mapping for `$key`.
*/
- // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
- public function put($key, $value);
+ public function put(int | string $key, mixed $value): mixed;
/**
* Associates the specified value with the specified key in this map only if
@@ -85,25 +83,23 @@ interface MapInterface extends ArrayInterface
* If there is already a value associated with `$key`, this returns that
* value without replacing it.
*
- * @param array-key $key The key to put in the map.
+ * @param K $key The key to put in the map.
* @param T $value The value to store at `$key`.
*
- * @return T|null the previous value associated with key, or `null` if
+ * @return T | null the previous value associated with key, or `null` if
* there was no mapping for `$key`.
*/
- // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
- public function putIfAbsent($key, $value);
+ public function putIfAbsent(int | string $key, mixed $value): mixed;
/**
* Removes the mapping for a key from this map if it is present.
*
- * @param array-key $key The key to remove from the map.
+ * @param K $key The key to remove from the map.
*
- * @return T|null the previous value associated with key, or `null` if
+ * @return T | null the previous value associated with key, or `null` if
* there was no mapping for `$key`.
*/
- // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
- public function remove($key);
+ public function remove(int | string $key): mixed;
/**
* Removes the entry for the specified key only if it is currently mapped to
@@ -111,26 +107,24 @@ interface MapInterface extends ArrayInterface
*
* This performs a strict type check on the value.
*
- * @param array-key $key The key to remove from the map.
+ * @param K $key The key to remove from the map.
* @param T $value The value to match.
*
* @return bool true if the value was removed.
*/
- // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
- public function removeIf($key, $value): bool;
+ public function removeIf(int | string $key, mixed $value): bool;
/**
* Replaces the entry for the specified key only if it is currently mapped
* to some value.
*
- * @param array-key $key The key to replace.
+ * @param K $key The key to replace.
* @param T $value The value to set at `$key`.
*
- * @return T|null the previous value associated with key, or `null` if
+ * @return T | null the previous value associated with key, or `null` if
* there was no mapping for `$key`.
*/
- // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
- public function replace($key, $value);
+ public function replace(int | string $key, mixed $value): mixed;
/**
* Replaces the entry for the specified key only if currently mapped to the
@@ -138,12 +132,11 @@ interface MapInterface extends ArrayInterface
*
* This performs a strict type check on the value.
*
- * @param array-key $key The key to remove from the map.
+ * @param K $key The key to remove from the map.
* @param T $oldValue The value to match.
* @param T $newValue The value to use as a replacement.
*
* @return bool true if the value was replaced.
*/
- // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
- public function replaceIf($key, $oldValue, $newValue): bool;
+ public function replaceIf(int | string $key, mixed $oldValue, mixed $newValue): bool;
}
diff --git a/vendor/ramsey/collection/src/Map/NamedParameterMap.php b/vendor/ramsey/collection/src/Map/NamedParameterMap.php
index ecc52f7..f948e47 100644
--- a/vendor/ramsey/collection/src/Map/NamedParameterMap.php
+++ b/vendor/ramsey/collection/src/Map/NamedParameterMap.php
@@ -26,7 +26,7 @@ use function is_int;
* `NamedParameterMap` represents a mapping of values to a set of named keys
* that may optionally be typed
*
- * @template-extends AbstractMap
+ * @extends AbstractMap
*/
class NamedParameterMap extends AbstractMap
{
@@ -38,13 +38,13 @@ class NamedParameterMap extends AbstractMap
*
* @var array
*/
- protected $namedParameters;
+ private readonly array $namedParameters;
/**
* Constructs a new `NamedParameterMap`.
*
* @param array $namedParameters The named parameters defined for this map.
- * @param array $data An initial set of data to set on this map.
+ * @param array $data An initial set of data to set on this map.
*/
public function __construct(array $namedParameters, array $data = [])
{
@@ -62,22 +62,12 @@ class NamedParameterMap extends AbstractMap
return $this->namedParameters;
}
- /**
- * @inheritDoc
- */
- public function offsetSet($offset, $value): void
+ public function offsetSet(mixed $offset, mixed $value): void
{
- if ($offset === null) {
- throw new InvalidArgumentException(
- 'Map elements are key/value pairs; a key must be provided for '
- . 'value ' . var_export($value, true)
- );
- }
-
if (!array_key_exists($offset, $this->namedParameters)) {
throw new InvalidArgumentException(
'Attempting to set value for unconfigured parameter \''
- . $offset . '\''
+ . $this->toolValueToString($offset) . '\'',
);
}
@@ -85,7 +75,7 @@ class NamedParameterMap extends AbstractMap
throw new InvalidArgumentException(
'Value for \'' . $offset . '\' must be of type '
. $this->namedParameters[$offset] . '; value is '
- . $this->toolValueToString($value)
+ . $this->toolValueToString($value),
);
}
diff --git a/vendor/ramsey/collection/src/Map/TypedMap.php b/vendor/ramsey/collection/src/Map/TypedMap.php
index 094551a..4a090c8 100644
--- a/vendor/ramsey/collection/src/Map/TypedMap.php
+++ b/vendor/ramsey/collection/src/Map/TypedMap.php
@@ -14,13 +14,11 @@ declare(strict_types=1);
namespace Ramsey\Collection\Map;
-use Ramsey\Collection\Tool\TypeTrait;
-
/**
* A `TypedMap` represents a map of elements where key and value are typed.
*
* Each element is identified by a key with defined type and a value of defined
- * type. The keys of the map must be unique. The values on the map can be=
+ * type. The keys of the map must be unique. The values on the map can be
* repeated but each with its own different key.
*
* The most common case is to use a string type key, but it's not limited to
@@ -31,7 +29,7 @@ use Ramsey\Collection\Tool\TypeTrait;
*
* Example usage:
*
- * ```php
+ * ```
* $map = new TypedMap('string', Foo::class);
* $map['x'] = new Foo();
* foreach ($map as $key => $value) {
@@ -53,7 +51,7 @@ use Ramsey\Collection\Tool\TypeTrait;
* It is preferable to subclass `AbstractTypedMap` to create your own typed map
* implementation:
*
- * ```php
+ * ```
* class FooTypedMap extends AbstractTypedMap
* {
* public function getKeyType()
@@ -70,7 +68,7 @@ use Ramsey\Collection\Tool\TypeTrait;
*
* … but you also may use the `TypedMap` class:
*
- * ```php
+ * ```
* class FooTypedMap extends TypedMap
* {
* public function __constructor(array $data = [])
@@ -80,34 +78,12 @@ use Ramsey\Collection\Tool\TypeTrait;
* }
* ```
*
- * @template K
+ * @template K of array-key
* @template T
- * @template-extends AbstractTypedMap
+ * @extends AbstractTypedMap
*/
class TypedMap extends AbstractTypedMap
{
- use TypeTrait;
-
- /**
- * The data type of keys stored in this collection.
- *
- * A map key's type is immutable once it is set. For this reason, this
- * property is set private.
- *
- * @var string data type of the map key.
- */
- private $keyType;
-
- /**
- * The data type of values stored in this collection.
- *
- * A map value's type is immutable once it is set. For this reason, this
- * property is set private.
- *
- * @var string data type of the map value.
- */
- private $valueType;
-
/**
* Constructs a map object of the specified key and value types,
* optionally with the specified data.
@@ -116,12 +92,11 @@ class TypedMap extends AbstractTypedMap
* @param string $valueType The data type of the map's values.
* @param array $data The initial data to set for this map.
*/
- public function __construct(string $keyType, string $valueType, array $data = [])
- {
- $this->keyType = $keyType;
- $this->valueType = $valueType;
-
- /** @psalm-suppress MixedArgumentTypeCoercion */
+ public function __construct(
+ private readonly string $keyType,
+ private readonly string $valueType,
+ array $data = [],
+ ) {
parent::__construct($data);
}
diff --git a/vendor/ramsey/collection/src/Map/TypedMapInterface.php b/vendor/ramsey/collection/src/Map/TypedMapInterface.php
index 51b6a81..5a44f06 100644
--- a/vendor/ramsey/collection/src/Map/TypedMapInterface.php
+++ b/vendor/ramsey/collection/src/Map/TypedMapInterface.php
@@ -18,8 +18,9 @@ namespace Ramsey\Collection\Map;
* A `TypedMapInterface` represents a map of elements where key and value are
* typed.
*
+ * @template K of array-key
* @template T
- * @template-extends MapInterface
+ * @extends MapInterface
*/
interface TypedMapInterface extends MapInterface
{
diff --git a/vendor/ramsey/collection/src/Queue.php b/vendor/ramsey/collection/src/Queue.php
index 4af2fdf..0f5b337 100644
--- a/vendor/ramsey/collection/src/Queue.php
+++ b/vendor/ramsey/collection/src/Queue.php
@@ -19,46 +19,30 @@ use Ramsey\Collection\Exception\NoSuchElementException;
use Ramsey\Collection\Tool\TypeTrait;
use Ramsey\Collection\Tool\ValueToStringTrait;
+use function array_key_first;
+
/**
* This class provides a basic implementation of `QueueInterface`, to minimize
* the effort required to implement this interface.
*
* @template T
- * @template-extends AbstractArray
- * @template-implements QueueInterface
+ * @extends AbstractArray
+ * @implements QueueInterface
*/
class Queue extends AbstractArray implements QueueInterface
{
use TypeTrait;
use ValueToStringTrait;
- /**
- * The type of elements stored in this queue.
- *
- * A queue's type is immutable once it is set. For this reason, this
- * property is set private.
- *
- * @var string
- */
- private $queueType;
-
- /**
- * The index of the head of the queue.
- *
- * @var int
- */
- protected $index = 0;
-
/**
* Constructs a queue object of the specified type, optionally with the
* specified data.
*
- * @param string $queueType The type (FQCN) associated with this queue.
- * @param array $data The initial items to store in the collection.
+ * @param string $queueType The type or class name associated with this queue.
+ * @param array $data The initial items to store in the queue.
*/
- public function __construct(string $queueType, array $data = [])
+ public function __construct(private readonly string $queueType, array $data = [])
{
- $this->queueType = $queueType;
parent::__construct($data);
}
@@ -68,13 +52,15 @@ class Queue extends AbstractArray implements QueueInterface
* Since arbitrary offsets may not be manipulated in a queue, this method
* serves only to fulfill the `ArrayAccess` interface requirements. It is
* invoked by other operations when adding values to the queue.
+ *
+ * @throws InvalidArgumentException if $value is of the wrong type.
*/
- public function offsetSet($offset, $value): void
+ public function offsetSet(mixed $offset, mixed $value): void
{
if ($this->checkType($this->getType(), $value) === false) {
throw new InvalidArgumentException(
'Value must be of type ' . $this->getType() . '; value is '
- . $this->toolValueToString($value)
+ . $this->toolValueToString($value),
);
}
@@ -82,9 +68,9 @@ class Queue extends AbstractArray implements QueueInterface
}
/**
- * @inheritDoc
+ * @throws InvalidArgumentException if $value is of the wrong type.
*/
- public function add($element): bool
+ public function add(mixed $element): bool
{
$this[] = $element;
@@ -92,74 +78,67 @@ class Queue extends AbstractArray implements QueueInterface
}
/**
- * @inheritDoc
+ * @return T
+ *
+ * @throws NoSuchElementException if this queue is empty.
*/
- public function element()
+ public function element(): mixed
{
- $element = $this->peek();
-
- if ($element === null) {
- throw new NoSuchElementException(
- 'Can\'t return element from Queue. Queue is empty.'
- );
- }
-
- return $element;
+ return $this->peek() ?? throw new NoSuchElementException(
+ 'Can\'t return element from Queue. Queue is empty.',
+ );
}
- /**
- * @inheritDoc
- */
- public function offer($element): bool
+ public function offer(mixed $element): bool
{
try {
return $this->add($element);
- } catch (InvalidArgumentException $e) {
+ } catch (InvalidArgumentException) {
return false;
}
}
/**
- * @inheritDoc
+ * @return T | null
*/
- public function peek()
+ public function peek(): mixed
{
- if ($this->count() === 0) {
+ $index = array_key_first($this->data);
+
+ if ($index === null) {
return null;
}
- return $this[$this->index];
+ return $this[$index];
}
/**
- * @inheritDoc
+ * @return T | null
*/
- public function poll()
+ public function poll(): mixed
{
- if ($this->count() === 0) {
+ $index = array_key_first($this->data);
+
+ if ($index === null) {
return null;
}
- $head = $this[$this->index];
-
- unset($this[$this->index]);
- $this->index++;
+ $head = $this[$index];
+ unset($this[$index]);
return $head;
}
/**
- * @inheritDoc
+ * @return T
+ *
+ * @throws NoSuchElementException if this queue is empty.
*/
- public function remove()
+ public function remove(): mixed
{
- $head = $this->poll();
-
- if ($head === null) {
- throw new NoSuchElementException('Can\'t return element from Queue. Queue is empty.');
- }
-
- return $head;
+ return $this->poll() ?? throw new NoSuchElementException(
+ 'Can\'t return element from Queue. Queue is empty.',
+ );
}
public function getType(): string
diff --git a/vendor/ramsey/collection/src/QueueInterface.php b/vendor/ramsey/collection/src/QueueInterface.php
index 7ebbb5d..f29ce43 100644
--- a/vendor/ramsey/collection/src/QueueInterface.php
+++ b/vendor/ramsey/collection/src/QueueInterface.php
@@ -15,6 +15,7 @@ declare(strict_types=1);
namespace Ramsey\Collection;
use Ramsey\Collection\Exception\NoSuchElementException;
+use RuntimeException;
/**
* A queue is a collection in which the entities in the collection are kept in
@@ -94,7 +95,7 @@ use Ramsey\Collection\Exception\NoSuchElementException;
* `poll()` method to indicate that the queue contains no elements.
*
* @template T
- * @template-extends ArrayInterface
+ * @extends ArrayInterface
*/
interface QueueInterface extends ArrayInterface
{
@@ -123,13 +124,12 @@ interface QueueInterface extends ArrayInterface
*
* @return bool `true` if this queue changed as a result of the call.
*
- * @throws \RuntimeException if a queue refuses to add a particular element
+ * @throws RuntimeException if a queue refuses to add a particular element
* for any reason other than that it already contains the element.
* Implementations should use a more-specific exception that extends
* `\RuntimeException`.
*/
- // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
- public function add($element): bool;
+ public function add(mixed $element): bool;
/**
* Retrieves, but does not remove, the head of this queue.
@@ -143,7 +143,7 @@ interface QueueInterface extends ArrayInterface
*
* @throws NoSuchElementException if this queue is empty.
*/
- public function element();
+ public function element(): mixed;
/**
* Inserts the specified element into this queue if it is possible to do so
@@ -159,8 +159,7 @@ interface QueueInterface extends ArrayInterface
*
* @return bool `true` if the element was added to this queue, else `false`.
*/
- // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
- public function offer($element): bool;
+ public function offer(mixed $element): bool;
/**
* Retrieves, but does not remove, the head of this queue, or returns `null`
@@ -168,9 +167,9 @@ interface QueueInterface extends ArrayInterface
*
* @see self::element()
*
- * @return T|null the head of this queue, or `null` if this queue is empty.
+ * @return T | null the head of this queue, or `null` if this queue is empty.
*/
- public function peek();
+ public function peek(): mixed;
/**
* Retrieves and removes the head of this queue, or returns `null`
@@ -178,9 +177,9 @@ interface QueueInterface extends ArrayInterface
*
* @see self::remove()
*
- * @return T|null the head of this queue, or `null` if this queue is empty.
+ * @return T | null the head of this queue, or `null` if this queue is empty.
*/
- public function poll();
+ public function poll(): mixed;
/**
* Retrieves and removes the head of this queue.
@@ -194,7 +193,7 @@ interface QueueInterface extends ArrayInterface
*
* @throws NoSuchElementException if this queue is empty.
*/
- public function remove();
+ public function remove(): mixed;
/**
* Returns the type associated with this queue.
diff --git a/vendor/ramsey/collection/src/Set.php b/vendor/ramsey/collection/src/Set.php
index ac1c5cb..d60f248 100644
--- a/vendor/ramsey/collection/src/Set.php
+++ b/vendor/ramsey/collection/src/Set.php
@@ -24,11 +24,11 @@ namespace Ramsey\Collection;
*
* Example usage:
*
- * ``` php
+ * ```
* $foo = new \My\Foo();
* $set = new Set(\My\Foo::class);
*
- * $set->add($foo); // returns TRUE, the element don't exists
+ * $set->add($foo); // returns TRUE, the element doesn't exist
* $set->add($foo); // returns FALSE, the element already exists
*
* $bar = new \My\Foo();
@@ -36,29 +36,19 @@ namespace Ramsey\Collection;
* ```
*
* @template T
- * @template-extends AbstractSet
+ * @extends AbstractSet
*/
class Set extends AbstractSet
{
- /**
- * The type of elements stored in this set
- *
- * A set's type is immutable. For this reason, this property is private.
- *
- * @var string
- */
- private $setType;
-
/**
* Constructs a set object of the specified type, optionally with the
* specified data.
*
- * @param string $setType The type (FQCN) associated with this set.
+ * @param string $setType The type or class name associated with this set.
* @param array $data The initial items to store in the set.
*/
- public function __construct(string $setType, array $data = [])
+ public function __construct(private readonly string $setType, array $data = [])
{
- $this->setType = $setType;
parent::__construct($data);
}
diff --git a/vendor/ramsey/collection/src/Sort.php b/vendor/ramsey/collection/src/Sort.php
new file mode 100644
index 0000000..0c3c192
--- /dev/null
+++ b/vendor/ramsey/collection/src/Sort.php
@@ -0,0 +1,31 @@
+
+ * @license http://opensource.org/licenses/MIT MIT
+ */
+
+declare(strict_types=1);
+
+namespace Ramsey\Collection;
+
+/**
+ * Collection sorting
+ */
+enum Sort: string
+{
+ /**
+ * Sort items in a collection in ascending order.
+ */
+ case Ascending = 'asc';
+
+ /**
+ * Sort items in a collection in descending order.
+ */
+ case Descending = 'desc';
+}
diff --git a/vendor/ramsey/collection/src/Tool/TypeTrait.php b/vendor/ramsey/collection/src/Tool/TypeTrait.php
index 8214e96..ac51b7f 100644
--- a/vendor/ramsey/collection/src/Tool/TypeTrait.php
+++ b/vendor/ramsey/collection/src/Tool/TypeTrait.php
@@ -36,38 +36,22 @@ trait TypeTrait
* @param string $type The type to check the value against.
* @param mixed $value The value to check.
*/
- protected function checkType(string $type, $value): bool
+ protected function checkType(string $type, mixed $value): bool
{
- switch ($type) {
- case 'array':
- return is_array($value);
- case 'bool':
- case 'boolean':
- return is_bool($value);
- case 'callable':
- return is_callable($value);
- case 'float':
- case 'double':
- return is_float($value);
- case 'int':
- case 'integer':
- return is_int($value);
- case 'null':
- return $value === null;
- case 'numeric':
- return is_numeric($value);
- case 'object':
- return is_object($value);
- case 'resource':
- return is_resource($value);
- case 'scalar':
- return is_scalar($value);
- case 'string':
- return is_string($value);
- case 'mixed':
- return true;
- default:
- return $value instanceof $type;
- }
+ return match ($type) {
+ 'array' => is_array($value),
+ 'bool', 'boolean' => is_bool($value),
+ 'callable' => is_callable($value),
+ 'float', 'double' => is_float($value),
+ 'int', 'integer' => is_int($value),
+ 'null' => $value === null,
+ 'numeric' => is_numeric($value),
+ 'object' => is_object($value),
+ 'resource' => is_resource($value),
+ 'scalar' => is_scalar($value),
+ 'string' => is_string($value),
+ 'mixed' => true,
+ default => $value instanceof $type,
+ };
}
}
diff --git a/vendor/ramsey/collection/src/Tool/ValueExtractorTrait.php b/vendor/ramsey/collection/src/Tool/ValueExtractorTrait.php
index f9be1be..bbe27b4 100644
--- a/vendor/ramsey/collection/src/Tool/ValueExtractorTrait.php
+++ b/vendor/ramsey/collection/src/Tool/ValueExtractorTrait.php
@@ -14,9 +14,12 @@ declare(strict_types=1);
namespace Ramsey\Collection\Tool;
-use Ramsey\Collection\Exception\ValueExtractionException;
+use Ramsey\Collection\Exception\InvalidPropertyOrMethod;
+use Ramsey\Collection\Exception\UnsupportedOperationException;
+use ReflectionProperty;
-use function get_class;
+use function is_array;
+use function is_object;
use function method_exists;
use function property_exists;
use function sprintf;
@@ -27,32 +30,71 @@ use function sprintf;
trait ValueExtractorTrait
{
/**
- * Extracts the value of the given property or method from the object.
+ * Returns the type associated with this collection.
+ */
+ abstract public function getType(): string;
+
+ /**
+ * Extracts the value of the given property, method, or array key from the
+ * element.
*
- * @param mixed $object The object to extract the value from.
- * @param string $propertyOrMethod The property or method for which the
+ * If `$propertyOrMethod` is `null`, we return the element as-is.
+ *
+ * @param mixed $element The element to extract the value from.
+ * @param string | null $propertyOrMethod The property or method for which the
* value should be extracted.
*
- * @return mixed the value extracted from the specified property or method.
+ * @return mixed the value extracted from the specified property, method,
+ * or array key, or the element itself.
*
- * @throws ValueExtractionException if the method or property is not defined.
+ * @throws InvalidPropertyOrMethod
+ * @throws UnsupportedOperationException
*/
- protected function extractValue($object, string $propertyOrMethod)
+ protected function extractValue(mixed $element, ?string $propertyOrMethod): mixed
{
- if (!is_object($object)) {
- throw new ValueExtractionException('Unable to extract a value from a non-object');
+ if ($propertyOrMethod === null) {
+ return $element;
}
- if (property_exists($object, $propertyOrMethod)) {
- return $object->$propertyOrMethod;
+ if (!is_object($element) && !is_array($element)) {
+ throw new UnsupportedOperationException(sprintf(
+ 'The collection type "%s" does not support the $propertyOrMethod parameter',
+ $this->getType(),
+ ));
}
- if (method_exists($object, $propertyOrMethod)) {
- return $object->{$propertyOrMethod}();
+ if (is_array($element)) {
+ return $element[$propertyOrMethod] ?? throw new InvalidPropertyOrMethod(sprintf(
+ 'Key or index "%s" not found in collection elements',
+ $propertyOrMethod,
+ ));
}
- throw new ValueExtractionException(
- sprintf('Method or property "%s" not defined in %s', $propertyOrMethod, get_class($object))
- );
+ if (property_exists($element, $propertyOrMethod) && method_exists($element, $propertyOrMethod)) {
+ $reflectionProperty = new ReflectionProperty($element, $propertyOrMethod);
+ if ($reflectionProperty->isPublic()) {
+ return $element->$propertyOrMethod;
+ }
+
+ return $element->{$propertyOrMethod}();
+ }
+
+ if (property_exists($element, $propertyOrMethod)) {
+ return $element->$propertyOrMethod;
+ }
+
+ if (method_exists($element, $propertyOrMethod)) {
+ return $element->{$propertyOrMethod}();
+ }
+
+ if (isset($element->$propertyOrMethod)) {
+ return $element->$propertyOrMethod;
+ }
+
+ throw new InvalidPropertyOrMethod(sprintf(
+ 'Method or property "%s" not defined in %s',
+ $propertyOrMethod,
+ $element::class,
+ ));
}
}
diff --git a/vendor/ramsey/collection/src/Tool/ValueToStringTrait.php b/vendor/ramsey/collection/src/Tool/ValueToStringTrait.php
index 721ade0..40c7803 100644
--- a/vendor/ramsey/collection/src/Tool/ValueToStringTrait.php
+++ b/vendor/ramsey/collection/src/Tool/ValueToStringTrait.php
@@ -16,11 +16,12 @@ namespace Ramsey\Collection\Tool;
use DateTimeInterface;
-use function get_class;
+use function assert;
use function get_resource_type;
use function is_array;
use function is_bool;
use function is_callable;
+use function is_object;
use function is_resource;
use function is_scalar;
@@ -44,7 +45,7 @@ trait ValueToStringTrait
*
* @param mixed $value the value to return as a string.
*/
- protected function toolValueToString($value): string
+ protected function toolValueToString(mixed $value): string
{
// null
if ($value === null) {
@@ -71,16 +72,13 @@ trait ValueToStringTrait
return '(' . get_resource_type($value) . ' resource #' . (int) $value . ')';
}
- // If we don't know what it is, use var_export().
- if (!is_object($value)) {
- return '(' . var_export($value, true) . ')';
- }
-
// From here, $value should be an object.
+ assert(is_object($value));
// __toString() is implemented
if (is_callable([$value, '__toString'])) {
- return (string) $value->__toString();
+ /** @var string */
+ return $value->__toString();
}
// object of type \DateTime
@@ -89,6 +87,6 @@ trait ValueToStringTrait
}
// unknown type
- return '(' . get_class($value) . ' Object)';
+ return '(' . $value::class . ' Object)';
}
}
diff --git a/vendor/ramsey/uuid/LICENSE b/vendor/ramsey/uuid/LICENSE
index 5e06cf4..22b4d0d 100644
--- a/vendor/ramsey/uuid/LICENSE
+++ b/vendor/ramsey/uuid/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2012-2021 Ben Ramsey
+Copyright (c) 2012-2025 Ben Ramsey
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/vendor/ramsey/uuid/composer.json b/vendor/ramsey/uuid/composer.json
index 3f3b5ac..b34d9b1 100644
--- a/vendor/ramsey/uuid/composer.json
+++ b/vendor/ramsey/uuid/composer.json
@@ -1,65 +1,49 @@
{
"name": "ramsey/uuid",
- "type": "library",
"description": "A PHP library for generating and working with universally unique identifiers (UUIDs).",
+ "license": "MIT",
+ "type": "library",
"keywords": [
"uuid",
"identifier",
"guid"
],
- "license": "MIT",
"require": {
- "php": "^7.2 || ^8.0",
- "ext-json": "*",
- "brick/math": "^0.8 || ^0.9",
- "ramsey/collection": "^1.0",
- "symfony/polyfill-ctype": "^1.8",
- "symfony/polyfill-php80": "^1.14"
+ "php": "^8.0",
+ "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12 || ^0.13 || ^0.14",
+ "ramsey/collection": "^1.2 || ^2.0"
+ },
+ "require-dev": {
+ "captainhook/captainhook": "^5.25",
+ "captainhook/plugin-composer": "^5.3",
+ "dealerdirect/phpcodesniffer-composer-installer": "^1.0",
+ "ergebnis/composer-normalize": "^2.47",
+ "mockery/mockery": "^1.6",
+ "paragonie/random-lib": "^2",
+ "php-mock/php-mock": "^2.6",
+ "php-mock/php-mock-mockery": "^1.5",
+ "php-parallel-lint/php-parallel-lint": "^1.4.0",
+ "phpbench/phpbench": "^1.2.14",
+ "phpstan/extension-installer": "^1.4",
+ "phpstan/phpstan": "^2.1",
+ "phpstan/phpstan-mockery": "^2.0",
+ "phpstan/phpstan-phpunit": "^2.0",
+ "phpunit/phpunit": "^9.6",
+ "slevomat/coding-standard": "^8.18",
+ "squizlabs/php_codesniffer": "^3.13"
},
"replace": {
"rhumsaa/uuid": "self.version"
},
- "require-dev": {
- "captainhook/captainhook": "^5.10",
- "captainhook/plugin-composer": "^5.3",
- "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
- "doctrine/annotations": "^1.8",
- "ergebnis/composer-normalize": "^2.15",
- "mockery/mockery": "^1.3",
- "moontoast/math": "^1.1",
- "paragonie/random-lib": "^2",
- "php-mock/php-mock": "^2.2",
- "php-mock/php-mock-mockery": "^1.3",
- "php-parallel-lint/php-parallel-lint": "^1.1",
- "phpbench/phpbench": "^1.0",
- "phpstan/extension-installer": "^1.0",
- "phpstan/phpstan": "^0.12",
- "phpstan/phpstan-mockery": "^0.12",
- "phpstan/phpstan-phpunit": "^0.12",
- "phpunit/phpunit": "^8.5 || ^9",
- "slevomat/coding-standard": "^7.0",
- "squizlabs/php_codesniffer": "^3.5",
- "vimeo/psalm": "^4.9"
- },
"suggest": {
"ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.",
- "ext-ctype": "Enables faster processing of character classification using ctype functions.",
"ext-gmp": "Enables faster math with arbitrary-precision integers using GMP.",
"ext-uuid": "Enables the use of PeclUuidTimeGenerator and PeclUuidRandomGenerator.",
"paragonie/random-lib": "Provides RandomLib for use with the RandomLibAdapter",
"ramsey/uuid-doctrine": "Allows the use of Ramsey\\Uuid\\Uuid as Doctrine field type."
},
- "config": {
- "sort-packages": true
- },
- "extra": {
- "branch-alias": {
- "dev-main": "4.x-dev"
- },
- "captainhook": {
- "force-install": true
- }
- },
+ "minimum-stability": "dev",
+ "prefer-stable": true,
"autoload": {
"psr-4": {
"Ramsey\\Uuid\\": "src/"
@@ -75,33 +59,56 @@
"Ramsey\\Uuid\\Test\\": "tests/"
}
},
- "minimum-stability": "dev",
- "prefer-stable": true,
+ "config": {
+ "allow-plugins": {
+ "captainhook/plugin-composer": true,
+ "dealerdirect/phpcodesniffer-composer-installer": true,
+ "ergebnis/composer-normalize": true,
+ "phpstan/extension-installer": true
+ },
+ "sort-packages": true
+ },
+ "extra": {
+ "captainhook": {
+ "force-install": true
+ }
+ },
"scripts": {
- "analyze": [
- "@phpstan",
- "@psalm"
+ "dev:analyze": "@dev:analyze:phpstan",
+ "dev:analyze:phpstan": "phpstan analyse --ansi --memory-limit 1G",
+ "dev:bench": "@php -d 'error_reporting=24575' vendor/bin/phpbench run",
+ "dev:build:clean": "git clean -fX build/",
+ "dev:lint": [
+ "@dev:lint:syntax",
+ "@dev:lint:style"
],
- "build:clean": "git clean -fX build/",
- "lint": "parallel-lint src tests",
- "lint:paths": "parallel-lint",
- "phpbench": "phpbench run",
- "phpcbf": "phpcbf -vpw --cache=build/cache/phpcs.cache",
- "phpcs": "phpcs --cache=build/cache/phpcs.cache",
- "phpstan": [
- "phpstan analyse --no-progress",
- "phpstan analyse -c phpstan-tests.neon --no-progress"
+ "dev:lint:fix": "phpcbf --cache=build/cache/phpcs.cache",
+ "dev:lint:style": "phpcs --cache=build/cache/phpcs.cache --colors",
+ "dev:lint:syntax": "parallel-lint --colors src/ tests/",
+ "dev:test": [
+ "@dev:lint",
+ "@dev:bench",
+ "@dev:analyze",
+ "@dev:test:unit"
],
- "phpunit": "phpunit --verbose --colors=always",
- "phpunit-coverage": "phpunit --verbose --colors=always --coverage-html build/coverage",
- "psalm": "psalm --show-info=false --config=psalm.xml",
- "test": [
- "@lint",
- "@phpbench",
- "@phpcs",
- "@phpstan",
- "@psalm",
- "@phpunit"
- ]
+ "dev:test:coverage:ci": "@php -d 'xdebug.mode=coverage' vendor/bin/phpunit --colors=always --coverage-text --coverage-clover build/coverage/clover.xml --coverage-cobertura build/coverage/cobertura.xml --coverage-crap4j build/coverage/crap4j.xml --coverage-xml build/coverage/coverage-xml --log-junit build/junit.xml",
+ "dev:test:coverage:html": "@php -d 'xdebug.mode=coverage' vendor/bin/phpunit --colors=always --coverage-html build/coverage/coverage-html/",
+ "dev:test:unit": "phpunit --colors=always",
+ "test": "@dev:test"
+ },
+ "scripts-descriptions": {
+ "dev:analyze": "Runs all static analysis checks.",
+ "dev:analyze:phpstan": "Runs the PHPStan static analyzer.",
+ "dev:bench": "Runs PHPBench benchmark tests.",
+ "dev:build:clean": "Cleans the build/ directory.",
+ "dev:lint": "Runs all linting checks.",
+ "dev:lint:fix": "Auto-fixes coding standards issues, if possible.",
+ "dev:lint:style": "Checks for coding standards issues.",
+ "dev:lint:syntax": "Checks for syntax errors.",
+ "dev:test": "Runs linting, static analysis, and unit tests.",
+ "dev:test:coverage:ci": "Runs unit tests and generates CI coverage reports.",
+ "dev:test:coverage:html": "Runs unit tests and generates HTML coverage report.",
+ "dev:test:unit": "Runs unit tests.",
+ "test": "Runs linting, static analysis, and unit tests."
}
}
diff --git a/vendor/ramsey/uuid/src/BinaryUtils.php b/vendor/ramsey/uuid/src/BinaryUtils.php
index fb8ba9a..d8aac2e 100644
--- a/vendor/ramsey/uuid/src/BinaryUtils.php
+++ b/vendor/ramsey/uuid/src/BinaryUtils.php
@@ -20,44 +20,35 @@ namespace Ramsey\Uuid;
class BinaryUtils
{
/**
- * Applies the RFC 4122 variant field to the 16-bit clock sequence
+ * Applies the variant field to the 16-bit clock sequence
*
- * @link http://tools.ietf.org/html/rfc4122#section-4.1.1 RFC 4122, § 4.1.1: Variant
+ * @link https://www.rfc-editor.org/rfc/rfc9562#section-4.1 RFC 9562, 4.1. Variant Field
*
- * @param int $clockSeq The 16-bit clock sequence value before the RFC 4122
- * variant is applied
+ * @param int $clockSeq The 16-bit clock sequence value before the variant is applied
*
* @return int The 16-bit clock sequence multiplexed with the UUID variant
*
- * @psalm-pure
+ * @pure
*/
public static function applyVariant(int $clockSeq): int
{
- $clockSeq = $clockSeq & 0x3fff;
- $clockSeq |= 0x8000;
-
- return $clockSeq;
+ return ($clockSeq & 0x3fff) | 0x8000;
}
/**
- * Applies the RFC 4122 version number to the 16-bit `time_hi_and_version` field
+ * Applies the version field to the 16-bit `time_hi_and_version` field
*
- * @link http://tools.ietf.org/html/rfc4122#section-4.1.3 RFC 4122, § 4.1.3: Version
+ * @link https://www.rfc-editor.org/rfc/rfc9562#section-4.2 RFC 9562, 4.2. Version Field
*
- * @param int $timeHi The value of the 16-bit `time_hi_and_version` field
- * before the RFC 4122 version is applied
- * @param int $version The RFC 4122 version to apply to the `time_hi` field
+ * @param int $timeHi The value of the 16-bit `time_hi_and_version` field before the version is applied
+ * @param int $version The version to apply to the `time_hi` field
*
- * @return int The 16-bit time_hi field of the timestamp multiplexed with
- * the UUID version number
+ * @return int The 16-bit time_hi field of the timestamp multiplexed with the UUID version number
*
- * @psalm-pure
+ * @pure
*/
public static function applyVersion(int $timeHi, int $version): int
{
- $timeHi = $timeHi & 0x0fff;
- $timeHi |= $version << 12;
-
- return $timeHi;
+ return ($timeHi & 0x0fff) | ($version << 12);
}
}
diff --git a/vendor/ramsey/uuid/src/Builder/BuilderCollection.php b/vendor/ramsey/uuid/src/Builder/BuilderCollection.php
index 89fa1e3..2b2e0a2 100644
--- a/vendor/ramsey/uuid/src/Builder/BuilderCollection.php
+++ b/vendor/ramsey/uuid/src/Builder/BuilderCollection.php
@@ -27,6 +27,11 @@ use Traversable;
/**
* A collection of UuidBuilderInterface objects
*
+ * @deprecated this class has been deprecated and will be removed in 5.0.0. The use-case for this class comes from a
+ * pre-`phpstan/phpstan` and pre-`vimeo/psalm` ecosystem, in which type safety had to be mostly enforced at runtime:
+ * that is no longer necessary, now that you can safely verify your code to be correct, and use more generic types
+ * like `iterable` instead.
+ *
* @extends AbstractCollection
*/
class BuilderCollection extends AbstractCollection
@@ -36,11 +41,6 @@ class BuilderCollection extends AbstractCollection
return UuidBuilderInterface::class;
}
- /**
- * @psalm-mutation-free
- * @psalm-suppress ImpureMethodCall
- * @psalm-suppress InvalidTemplateParam
- */
public function getIterator(): Traversable
{
return parent::getIterator();
@@ -49,11 +49,7 @@ class BuilderCollection extends AbstractCollection
/**
* Re-constructs the object from its serialized form
*
- * @param string $serialized The serialized PHP string to unserialize into
- * a UuidInterface instance
- *
- * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
- * @psalm-suppress RedundantConditionGivenDocblockType
+ * @param string $serialized The serialized PHP string to unserialize into a UuidInterface instance
*/
public function unserialize($serialized): void
{
@@ -73,8 +69,9 @@ class BuilderCollection extends AbstractCollection
$this->data = array_filter(
$data,
function ($unserialized): bool {
+ /** @phpstan-ignore instanceof.alwaysTrue */
return $unserialized instanceof UuidBuilderInterface;
- }
+ },
);
}
}
diff --git a/vendor/ramsey/uuid/src/Builder/DefaultUuidBuilder.php b/vendor/ramsey/uuid/src/Builder/DefaultUuidBuilder.php
index 7c4a6f8..3d62159 100644
--- a/vendor/ramsey/uuid/src/Builder/DefaultUuidBuilder.php
+++ b/vendor/ramsey/uuid/src/Builder/DefaultUuidBuilder.php
@@ -17,9 +17,9 @@ namespace Ramsey\Uuid\Builder;
use Ramsey\Uuid\Rfc4122\UuidBuilder as Rfc4122UuidBuilder;
/**
- * @deprecated Transition to {@see Rfc4122UuidBuilder}.
+ * @deprecated Please transition to {@see Rfc4122UuidBuilder}.
*
- * @psalm-immutable
+ * @immutable
*/
class DefaultUuidBuilder extends Rfc4122UuidBuilder
{
diff --git a/vendor/ramsey/uuid/src/Builder/DegradedUuidBuilder.php b/vendor/ramsey/uuid/src/Builder/DegradedUuidBuilder.php
index 23931e4..1554a97 100644
--- a/vendor/ramsey/uuid/src/Builder/DegradedUuidBuilder.php
+++ b/vendor/ramsey/uuid/src/Builder/DegradedUuidBuilder.php
@@ -23,34 +23,23 @@ use Ramsey\Uuid\Rfc4122\Fields as Rfc4122Fields;
use Ramsey\Uuid\UuidInterface;
/**
- * @deprecated DegradedUuid instances are no longer necessary to support 32-bit
- * systems. Transition to {@see DefaultUuidBuilder}.
+ * @deprecated DegradedUuid instances are no longer necessary to support 32-bit systems. Please transition to {@see DefaultUuidBuilder}.
*
- * @psalm-immutable
+ * @immutable
*/
class DegradedUuidBuilder implements UuidBuilderInterface
{
- /**
- * @var NumberConverterInterface
- */
- private $numberConverter;
+ private TimeConverterInterface $timeConverter;
/**
- * @var TimeConverterInterface
- */
- private $timeConverter;
-
- /**
- * @param NumberConverterInterface $numberConverter The number converter to
- * use when constructing the DegradedUuid
- * @param TimeConverterInterface|null $timeConverter The time converter to use
- * for converting timestamps extracted from a UUID to Unix timestamps
+ * @param NumberConverterInterface $numberConverter The number converter to use when constructing the DegradedUuid
+ * @param TimeConverterInterface|null $timeConverter The time converter to use for converting timestamps extracted
+ * from a UUID to Unix timestamps
*/
public function __construct(
- NumberConverterInterface $numberConverter,
+ private NumberConverterInterface $numberConverter,
?TimeConverterInterface $timeConverter = null
) {
- $this->numberConverter = $numberConverter;
$this->timeConverter = $timeConverter ?: new DegradedTimeConverter();
}
@@ -62,15 +51,10 @@ class DegradedUuidBuilder implements UuidBuilderInterface
*
* @return DegradedUuid The DegradedUuidBuild returns an instance of Ramsey\Uuid\DegradedUuid
*
- * @psalm-pure
+ * @phpstan-impure
*/
public function build(CodecInterface $codec, string $bytes): UuidInterface
{
- return new DegradedUuid(
- new Rfc4122Fields($bytes),
- $this->numberConverter,
- $codec,
- $this->timeConverter
- );
+ return new DegradedUuid(new Rfc4122Fields($bytes), $this->numberConverter, $codec, $this->timeConverter);
}
}
diff --git a/vendor/ramsey/uuid/src/Builder/FallbackBuilder.php b/vendor/ramsey/uuid/src/Builder/FallbackBuilder.php
index 470d2f7..e40f778 100644
--- a/vendor/ramsey/uuid/src/Builder/FallbackBuilder.php
+++ b/vendor/ramsey/uuid/src/Builder/FallbackBuilder.php
@@ -20,36 +20,28 @@ use Ramsey\Uuid\Exception\UnableToBuildUuidException;
use Ramsey\Uuid\UuidInterface;
/**
- * FallbackBuilder builds a UUID by stepping through a list of UUID builders
- * until a UUID can be constructed without exceptions
+ * FallbackBuilder builds a UUID by stepping through a list of UUID builders until a UUID can be constructed without exceptions
*
- * @psalm-immutable
+ * @immutable
*/
class FallbackBuilder implements UuidBuilderInterface
{
/**
- * @var BuilderCollection
+ * @param iterable $builders An array of UUID builders
*/
- private $builders;
-
- /**
- * @param BuilderCollection $builders An array of UUID builders
- */
- public function __construct(BuilderCollection $builders)
+ public function __construct(private iterable $builders)
{
- $this->builders = $builders;
}
/**
- * Builds and returns a UuidInterface instance using the first builder that
- * succeeds
+ * Builds and returns a UuidInterface instance using the first builder that succeeds
*
* @param CodecInterface $codec The codec to use for building this instance
* @param string $bytes The byte string from which to construct a UUID
*
* @return UuidInterface an instance of a UUID object
*
- * @psalm-pure
+ * @pure
*/
public function build(CodecInterface $codec, string $bytes): UuidInterface
{
@@ -68,7 +60,7 @@ class FallbackBuilder implements UuidBuilderInterface
throw new BuilderNotFoundException(
'Could not find a suitable builder for the provided codec and fields',
0,
- $lastBuilderException
+ $lastBuilderException,
);
}
}
diff --git a/vendor/ramsey/uuid/src/Builder/UuidBuilderInterface.php b/vendor/ramsey/uuid/src/Builder/UuidBuilderInterface.php
index 8e58b2b..c409878 100644
--- a/vendor/ramsey/uuid/src/Builder/UuidBuilderInterface.php
+++ b/vendor/ramsey/uuid/src/Builder/UuidBuilderInterface.php
@@ -20,7 +20,7 @@ use Ramsey\Uuid\UuidInterface;
/**
* A UUID builder builds instances of UuidInterface
*
- * @psalm-immutable
+ * @immutable
*/
interface UuidBuilderInterface
{
@@ -30,10 +30,9 @@ interface UuidBuilderInterface
* @param CodecInterface $codec The codec to use for building this UuidInterface instance
* @param string $bytes The byte string from which to construct a UUID
*
- * @return UuidInterface Implementations may choose to return more specific
- * instances of UUIDs that implement UuidInterface
+ * @return UuidInterface Implementations may choose to return more specific instances of UUIDs that implement UuidInterface
*
- * @psalm-pure
+ * @pure
*/
public function build(CodecInterface $codec, string $bytes): UuidInterface;
}
diff --git a/vendor/ramsey/uuid/src/Codec/CodecInterface.php b/vendor/ramsey/uuid/src/Codec/CodecInterface.php
index 85f8a7e..b1e554e 100644
--- a/vendor/ramsey/uuid/src/Codec/CodecInterface.php
+++ b/vendor/ramsey/uuid/src/Codec/CodecInterface.php
@@ -19,53 +19,51 @@ use Ramsey\Uuid\UuidInterface;
/**
* A codec encodes and decodes a UUID according to defined rules
*
- * @psalm-immutable
+ * @immutable
*/
interface CodecInterface
{
/**
* Returns a hexadecimal string representation of a UuidInterface
*
- * @param UuidInterface $uuid The UUID for which to create a hexadecimal
- * string representation
+ * @param UuidInterface $uuid The UUID for which to create a hexadecimal string representation
*
- * @return string Hexadecimal string representation of a UUID
+ * @return non-empty-string Hexadecimal string representation of a UUID
*
- * @psalm-return non-empty-string
+ * @pure
*/
public function encode(UuidInterface $uuid): string;
/**
* Returns a binary string representation of a UuidInterface
*
- * @param UuidInterface $uuid The UUID for which to create a binary string
- * representation
+ * @param UuidInterface $uuid The UUID for which to create a binary string representation
*
- * @return string Binary string representation of a UUID
+ * @return non-empty-string Binary string representation of a UUID
*
- * @psalm-return non-empty-string
+ * @pure
*/
public function encodeBinary(UuidInterface $uuid): string;
/**
* Returns a UuidInterface derived from a hexadecimal string representation
*
- * @param string $encodedUuid The hexadecimal string representation to
- * convert into a UuidInterface instance
+ * @param string $encodedUuid The hexadecimal string representation to convert into a UuidInterface instance
*
- * @return UuidInterface An instance of a UUID decoded from a hexadecimal
- * string representation
+ * @return UuidInterface An instance of a UUID decoded from a hexadecimal string representation
+ *
+ * @pure
*/
public function decode(string $encodedUuid): UuidInterface;
/**
* Returns a UuidInterface derived from a binary string representation
*
- * @param string $bytes The binary string representation to convert into a
- * UuidInterface instance
+ * @param string $bytes The binary string representation to convert into a UuidInterface instance
*
- * @return UuidInterface An instance of a UUID decoded from a binary string
- * representation
+ * @return UuidInterface An instance of a UUID decoded from a binary string representation
+ *
+ * @pure
*/
public function decodeBytes(string $bytes): UuidInterface;
}
diff --git a/vendor/ramsey/uuid/src/Codec/GuidStringCodec.php b/vendor/ramsey/uuid/src/Codec/GuidStringCodec.php
index f11e9d5..a1bd58a 100644
--- a/vendor/ramsey/uuid/src/Codec/GuidStringCodec.php
+++ b/vendor/ramsey/uuid/src/Codec/GuidStringCodec.php
@@ -18,6 +18,7 @@ use Ramsey\Uuid\Guid\Guid;
use Ramsey\Uuid\UuidInterface;
use function bin2hex;
+use function sprintf;
use function substr;
/**
@@ -25,20 +26,43 @@ use function substr;
*
* @see Guid
*
- * @psalm-immutable
+ * @immutable
*/
class GuidStringCodec extends StringCodec
{
+ public function encode(UuidInterface $uuid): string
+ {
+ /** @phpstan-ignore possiblyImpure.methodCall */
+ $hex = bin2hex($uuid->getFields()->getBytes());
+
+ /** @var non-empty-string */
+ return sprintf(
+ '%02s%02s%02s%02s-%02s%02s-%02s%02s-%04s-%012s',
+ substr($hex, 6, 2),
+ substr($hex, 4, 2),
+ substr($hex, 2, 2),
+ substr($hex, 0, 2),
+ substr($hex, 10, 2),
+ substr($hex, 8, 2),
+ substr($hex, 14, 2),
+ substr($hex, 12, 2),
+ substr($hex, 16, 4),
+ substr($hex, 20),
+ );
+ }
+
public function decode(string $encodedUuid): UuidInterface
{
+ /** @phpstan-ignore possiblyImpure.methodCall */
$bytes = $this->getBytes($encodedUuid);
+ /** @phpstan-ignore possiblyImpure.methodCall, possiblyImpure.methodCall */
return $this->getBuilder()->build($this, $this->swapBytes($bytes));
}
public function decodeBytes(string $bytes): UuidInterface
{
- // Specifically call parent::decode to preserve correct byte order
+ // Call parent::decode() to preserve the correct byte order.
return parent::decode(bin2hex($bytes));
}
@@ -48,8 +72,7 @@ class GuidStringCodec extends StringCodec
private function swapBytes(string $bytes): string
{
return $bytes[3] . $bytes[2] . $bytes[1] . $bytes[0]
- . $bytes[5] . $bytes[4]
- . $bytes[7] . $bytes[6]
+ . $bytes[5] . $bytes[4] . $bytes[7] . $bytes[6]
. substr($bytes, 8);
}
}
diff --git a/vendor/ramsey/uuid/src/Codec/OrderedTimeCodec.php b/vendor/ramsey/uuid/src/Codec/OrderedTimeCodec.php
index 0798ebc..ea533d9 100644
--- a/vendor/ramsey/uuid/src/Codec/OrderedTimeCodec.php
+++ b/vendor/ramsey/uuid/src/Codec/OrderedTimeCodec.php
@@ -24,59 +24,51 @@ use function strlen;
use function substr;
/**
- * OrderedTimeCodec encodes and decodes a UUID, optimizing the byte order for
- * more efficient storage
+ * OrderedTimeCodec encodes and decodes a UUID, optimizing the byte order for more efficient storage
*
- * For binary representations of version 1 UUID, this codec may be used to
- * reorganize the time fields, making the UUID closer to sequential when storing
- * the bytes. According to Percona, this optimization can improve database
- * INSERTs and SELECTs using the UUID column as a key.
+ * For binary representations of version 1 UUID, this codec may be used to reorganize the time fields, making the UUID
+ * closer to sequential when storing the bytes. According to Percona, this optimization can improve database INSERT and
+ * SELECT statements using the UUID column as a key.
*
- * The string representation of the UUID will remain unchanged. Only the binary
- * representation is reordered.
+ * The string representation of the UUID will remain unchanged. Only the binary representation is reordered.
*
- * **PLEASE NOTE:** Binary representations of UUIDs encoded with this codec must
- * be decoded with this codec. Decoding using another codec can result in
- * malformed UUIDs.
+ * PLEASE NOTE: Binary representations of UUIDs encoded with this codec must be decoded with this codec. Decoding using
+ * another codec can result in malformed UUIDs.
+ *
+ * @deprecated Please migrate to {@link https://uuid.ramsey.dev/en/stable/rfc4122/version6.html Version 6, reordered time-based UUIDs}.
*
* @link https://www.percona.com/blog/2014/12/19/store-uuid-optimized-way/ Storing UUID Values in MySQL
*
- * @psalm-immutable
+ * @immutable
*/
class OrderedTimeCodec extends StringCodec
{
/**
- * Returns a binary string representation of a UUID, with the timestamp
- * fields rearranged for optimized storage
+ * Returns a binary string representation of a UUID, with the timestamp fields rearranged for optimized storage
*
- * @inheritDoc
- * @psalm-return non-empty-string
- * @psalm-suppress MoreSpecificReturnType we know that the retrieved `string` is never empty
- * @psalm-suppress LessSpecificReturnStatement we know that the retrieved `string` is never empty
+ * @return non-empty-string
*/
public function encodeBinary(UuidInterface $uuid): string
{
if (
+ /** @phpstan-ignore possiblyImpure.methodCall */
!($uuid->getFields() instanceof Rfc4122FieldsInterface)
+ /** @phpstan-ignore possiblyImpure.methodCall */
|| $uuid->getFields()->getVersion() !== Uuid::UUID_TYPE_TIME
) {
- throw new InvalidArgumentException(
- 'Expected RFC 4122 version 1 (time-based) UUID'
- );
+ throw new InvalidArgumentException('Expected version 1 (time-based) UUID');
}
+ /** @phpstan-ignore possiblyImpure.methodCall */
$bytes = $uuid->getFields()->getBytes();
- /** @phpstan-ignore-next-line PHPStan complains that this is not a non-empty-string. */
- return $bytes[6] . $bytes[7]
- . $bytes[4] . $bytes[5]
+ return $bytes[6] . $bytes[7] . $bytes[4] . $bytes[5]
. $bytes[0] . $bytes[1] . $bytes[2] . $bytes[3]
. substr($bytes, 8);
}
/**
- * Returns a UuidInterface derived from an ordered-time binary string
- * representation
+ * Returns a UuidInterface derived from an ordered-time binary string representation
*
* @throws InvalidArgumentException if $bytes is an invalid length
*
@@ -85,26 +77,22 @@ class OrderedTimeCodec extends StringCodec
public function decodeBytes(string $bytes): UuidInterface
{
if (strlen($bytes) !== 16) {
- throw new InvalidArgumentException(
- '$bytes string should contain 16 characters.'
- );
+ throw new InvalidArgumentException('$bytes string should contain 16 characters.');
}
// Rearrange the bytes to their original order.
$rearrangedBytes = $bytes[4] . $bytes[5] . $bytes[6] . $bytes[7]
- . $bytes[2] . $bytes[3]
- . $bytes[0] . $bytes[1]
+ . $bytes[2] . $bytes[3] . $bytes[0] . $bytes[1]
. substr($bytes, 8);
$uuid = parent::decodeBytes($rearrangedBytes);
- if (
- !($uuid->getFields() instanceof Rfc4122FieldsInterface)
- || $uuid->getFields()->getVersion() !== Uuid::UUID_TYPE_TIME
- ) {
+ /** @phpstan-ignore possiblyImpure.methodCall */
+ $fields = $uuid->getFields();
+
+ if (!$fields instanceof Rfc4122FieldsInterface || $fields->getVersion() !== Uuid::UUID_TYPE_TIME) {
throw new UnsupportedOperationException(
- 'Attempting to decode a non-time-based UUID using '
- . 'OrderedTimeCodec'
+ 'Attempting to decode a non-time-based UUID using OrderedTimeCodec',
);
}
diff --git a/vendor/ramsey/uuid/src/Codec/StringCodec.php b/vendor/ramsey/uuid/src/Codec/StringCodec.php
index 58c9f58..55f4f8b 100644
--- a/vendor/ramsey/uuid/src/Codec/StringCodec.php
+++ b/vendor/ramsey/uuid/src/Codec/StringCodec.php
@@ -17,61 +17,51 @@ namespace Ramsey\Uuid\Codec;
use Ramsey\Uuid\Builder\UuidBuilderInterface;
use Ramsey\Uuid\Exception\InvalidArgumentException;
use Ramsey\Uuid\Exception\InvalidUuidStringException;
-use Ramsey\Uuid\Rfc4122\FieldsInterface;
use Ramsey\Uuid\Uuid;
use Ramsey\Uuid\UuidInterface;
+use function bin2hex;
use function hex2bin;
use function implode;
+use function sprintf;
use function str_replace;
use function strlen;
use function substr;
/**
- * StringCodec encodes and decodes RFC 4122 UUIDs
+ * StringCodec encodes and decodes RFC 9562 (formerly RFC 4122) UUIDs
*
- * @link http://tools.ietf.org/html/rfc4122
- *
- * @psalm-immutable
+ * @immutable
*/
class StringCodec implements CodecInterface
{
- /**
- * @var UuidBuilderInterface
- */
- private $builder;
-
/**
* Constructs a StringCodec
*
* @param UuidBuilderInterface $builder The builder to use when encoding UUIDs
*/
- public function __construct(UuidBuilderInterface $builder)
+ public function __construct(private UuidBuilderInterface $builder)
{
- $this->builder = $builder;
}
public function encode(UuidInterface $uuid): string
{
- /** @var FieldsInterface $fields */
- $fields = $uuid->getFields();
+ /** @phpstan-ignore possiblyImpure.methodCall */
+ $hex = bin2hex($uuid->getFields()->getBytes());
- return $fields->getTimeLow()->toString()
- . '-'
- . $fields->getTimeMid()->toString()
- . '-'
- . $fields->getTimeHiAndVersion()->toString()
- . '-'
- . $fields->getClockSeqHiAndReserved()->toString()
- . $fields->getClockSeqLow()->toString()
- . '-'
- . $fields->getNode()->toString();
+ /** @var non-empty-string */
+ return sprintf(
+ '%08s-%04s-%04s-%04s-%012s',
+ substr($hex, 0, 8),
+ substr($hex, 8, 4),
+ substr($hex, 12, 4),
+ substr($hex, 16, 4),
+ substr($hex, 20),
+ );
}
/**
- * @psalm-return non-empty-string
- * @psalm-suppress MoreSpecificReturnType we know that the retrieved `string` is never empty
- * @psalm-suppress LessSpecificReturnStatement we know that the retrieved `string` is never empty
+ * @return non-empty-string
*/
public function encodeBinary(UuidInterface $uuid): string
{
@@ -86,15 +76,14 @@ class StringCodec implements CodecInterface
*/
public function decode(string $encodedUuid): UuidInterface
{
+ /** @phpstan-ignore possiblyImpure.methodCall */
return $this->builder->build($this, $this->getBytes($encodedUuid));
}
public function decodeBytes(string $bytes): UuidInterface
{
if (strlen($bytes) !== 16) {
- throw new InvalidArgumentException(
- '$bytes string should contain 16 characters.'
- );
+ throw new InvalidArgumentException('$bytes string should contain 16 characters.');
}
return $this->builder->build($this, $bytes);
@@ -113,11 +102,7 @@ class StringCodec implements CodecInterface
*/
protected function getBytes(string $encodedUuid): string
{
- $parsedUuid = str_replace(
- ['urn:', 'uuid:', 'URN:', 'UUID:', '{', '}', '-'],
- '',
- $encodedUuid
- );
+ $parsedUuid = str_replace(['urn:', 'uuid:', 'URN:', 'UUID:', '{', '}', '-'], '', $encodedUuid);
$components = [
substr($parsedUuid, 0, 8),
@@ -128,9 +113,7 @@ class StringCodec implements CodecInterface
];
if (!Uuid::isValid(implode('-', $components))) {
- throw new InvalidUuidStringException(
- 'Invalid UUID string: ' . $encodedUuid
- );
+ throw new InvalidUuidStringException('Invalid UUID string: ' . $encodedUuid);
}
return (string) hex2bin($parsedUuid);
diff --git a/vendor/ramsey/uuid/src/Codec/TimestampFirstCombCodec.php b/vendor/ramsey/uuid/src/Codec/TimestampFirstCombCodec.php
index 0e0042d..e7c8efd 100644
--- a/vendor/ramsey/uuid/src/Codec/TimestampFirstCombCodec.php
+++ b/vendor/ramsey/uuid/src/Codec/TimestampFirstCombCodec.php
@@ -23,40 +23,39 @@ use function substr;
use function substr_replace;
/**
- * TimestampFirstCombCodec encodes and decodes COMBs, with the timestamp as the
- * first 48 bits
+ * TimestampFirstCombCodec encodes and decodes COMBs, with the timestamp as the first 48 bits
*
- * In contrast with the TimestampLastCombCodec, the TimestampFirstCombCodec
- * adds the timestamp to the first 48 bits of the COMB. To generate a
- * timestamp-first COMB, set the TimestampFirstCombCodec as the codec, along
- * with the CombGenerator as the random generator.
+ * In contrast with the TimestampLastCombCodec, the TimestampFirstCombCodec adds the timestamp to the first 48 bits of
+ * the COMB. To generate a timestamp-first COMB, set the TimestampFirstCombCodec as the codec, along with the
+ * CombGenerator as the random generator.
*
- * ``` php
+ * ```
* $factory = new UuidFactory();
*
* $factory->setCodec(new TimestampFirstCombCodec($factory->getUuidBuilder()));
*
* $factory->setRandomGenerator(new CombGenerator(
* $factory->getRandomGenerator(),
- * $factory->getNumberConverter()
+ * $factory->getNumberConverter(),
* ));
*
* $timestampFirstComb = $factory->uuid4();
* ```
*
- * @link https://www.informit.com/articles/printerfriendly/25862 The Cost of GUIDs as Primary Keys
+ * @deprecated Please migrate to {@link https://uuid.ramsey.dev/en/stable/rfc4122/version7.html Version 7, Unix Epoch Time UUIDs}.
*
- * @psalm-immutable
+ * @link https://web.archive.org/web/20240118030355/https://www.informit.com/articles/printerfriendly/25862 The Cost of GUIDs as Primary Keys
+ *
+ * @immutable
*/
class TimestampFirstCombCodec extends StringCodec
{
/**
- * @psalm-return non-empty-string
- * @psalm-suppress MoreSpecificReturnType we know that the retrieved `string` is never empty
- * @psalm-suppress LessSpecificReturnStatement we know that the retrieved `string` is never empty
+ * @return non-empty-string
*/
public function encode(UuidInterface $uuid): string
{
+ /** @phpstan-ignore possiblyImpure.methodCall */
$bytes = $this->swapBytes($uuid->getFields()->getBytes());
return sprintf(
@@ -70,9 +69,7 @@ class TimestampFirstCombCodec extends StringCodec
}
/**
- * @psalm-return non-empty-string
- * @psalm-suppress MoreSpecificReturnType we know that the retrieved `string` is never empty
- * @psalm-suppress LessSpecificReturnStatement we know that the retrieved `string` is never empty
+ * @return non-empty-string
*/
public function encodeBinary(UuidInterface $uuid): string
{
@@ -87,27 +84,29 @@ class TimestampFirstCombCodec extends StringCodec
*/
public function decode(string $encodedUuid): UuidInterface
{
+ /** @phpstan-ignore possiblyImpure.methodCall */
$bytes = $this->getBytes($encodedUuid);
+ /** @phpstan-ignore possiblyImpure.methodCall */
return $this->getBuilder()->build($this, $this->swapBytes($bytes));
}
public function decodeBytes(string $bytes): UuidInterface
{
+ /** @phpstan-ignore possiblyImpure.methodCall */
return $this->getBuilder()->build($this, $this->swapBytes($bytes));
}
/**
* Swaps bytes according to the timestamp-first COMB rules
+ *
+ * @pure
*/
private function swapBytes(string $bytes): string
{
$first48Bits = substr($bytes, 0, 6);
$last48Bits = substr($bytes, -6);
- $bytes = substr_replace($bytes, $last48Bits, 0, 6);
- $bytes = substr_replace($bytes, $first48Bits, -6);
-
- return $bytes;
+ return substr_replace(substr_replace($bytes, $last48Bits, 0, 6), $first48Bits, -6);
}
}
diff --git a/vendor/ramsey/uuid/src/Codec/TimestampLastCombCodec.php b/vendor/ramsey/uuid/src/Codec/TimestampLastCombCodec.php
index 4856dea..14d10b6 100644
--- a/vendor/ramsey/uuid/src/Codec/TimestampLastCombCodec.php
+++ b/vendor/ramsey/uuid/src/Codec/TimestampLastCombCodec.php
@@ -15,36 +15,33 @@ declare(strict_types=1);
namespace Ramsey\Uuid\Codec;
/**
- * TimestampLastCombCodec encodes and decodes COMBs, with the timestamp as the
- * last 48 bits
+ * TimestampLastCombCodec encodes and decodes COMBs, with the timestamp as the last 48 bits
*
- * The CombGenerator when used with the StringCodec (and, by proxy, the
- * TimestampLastCombCodec) adds the timestamp to the last 48 bits of the COMB.
- * The TimestampLastCombCodec is provided for the sake of consistency. In
- * practice, it is identical to the standard StringCodec but, it may be used
- * with the CombGenerator for additional context when reading code.
+ * The CombGenerator when used with the StringCodec (and, by proxy, the TimestampLastCombCodec) adds the timestamp to
+ * the last 48 bits of the COMB. The TimestampLastCombCodec is provided for the sake of consistency. In practice, it is
+ * identical to the standard StringCodec, but it may be used with the CombGenerator for additional context when reading
+ * code.
*
- * Consider the following code. By default, the codec used by UuidFactory is the
- * StringCodec, but here, we explicitly set the TimestampLastCombCodec. It is
- * redundant, but it is clear that we intend this COMB to be generated with the
+ * Consider the following code. By default, the codec used by UuidFactory is the StringCodec, but here, we explicitly
+ * set the TimestampLastCombCodec. It is redundant, but it is clear that we intend this COMB to be generated with the
* timestamp appearing at the end.
*
- * ``` php
+ * ```
* $factory = new UuidFactory();
*
* $factory->setCodec(new TimestampLastCombCodec($factory->getUuidBuilder()));
*
* $factory->setRandomGenerator(new CombGenerator(
* $factory->getRandomGenerator(),
- * $factory->getNumberConverter()
+ * $factory->getNumberConverter(),
* ));
*
* $timestampLastComb = $factory->uuid4();
* ```
*
- * @link https://www.informit.com/articles/printerfriendly/25862 The Cost of GUIDs as Primary Keys
+ * @deprecated Please use {@see StringCodec} instead.
*
- * @psalm-immutable
+ * @immutable
*/
class TimestampLastCombCodec extends StringCodec
{
diff --git a/vendor/ramsey/uuid/src/Converter/Number/BigNumberConverter.php b/vendor/ramsey/uuid/src/Converter/Number/BigNumberConverter.php
index fef63fd..ff4e1cc 100644
--- a/vendor/ramsey/uuid/src/Converter/Number/BigNumberConverter.php
+++ b/vendor/ramsey/uuid/src/Converter/Number/BigNumberConverter.php
@@ -18,19 +18,16 @@ use Ramsey\Uuid\Converter\NumberConverterInterface;
use Ramsey\Uuid\Math\BrickMathCalculator;
/**
- * Previously used to integrate moontoast/math as a bignum arithmetic library,
- * BigNumberConverter is deprecated in favor of GenericNumberConverter
+ * Previously used to integrate moontoast/math as a bignum arithmetic library, BigNumberConverter is deprecated in favor
+ * of GenericNumberConverter
*
- * @deprecated Transition to {@see GenericNumberConverter}.
+ * @deprecated Please transition to {@see GenericNumberConverter}.
*
- * @psalm-immutable
+ * @immutable
*/
class BigNumberConverter implements NumberConverterInterface
{
- /**
- * @var NumberConverterInterface
- */
- private $converter;
+ private NumberConverterInterface $converter;
public function __construct()
{
@@ -38,8 +35,7 @@ class BigNumberConverter implements NumberConverterInterface
}
/**
- * @inheritDoc
- * @psalm-pure
+ * @pure
*/
public function fromHex(string $hex): string
{
@@ -47,8 +43,7 @@ class BigNumberConverter implements NumberConverterInterface
}
/**
- * @inheritDoc
- * @psalm-pure
+ * @pure
*/
public function toHex(string $number): string
{
diff --git a/vendor/ramsey/uuid/src/Converter/Number/DegradedNumberConverter.php b/vendor/ramsey/uuid/src/Converter/Number/DegradedNumberConverter.php
index c9cfa68..54e4e8c 100644
--- a/vendor/ramsey/uuid/src/Converter/Number/DegradedNumberConverter.php
+++ b/vendor/ramsey/uuid/src/Converter/Number/DegradedNumberConverter.php
@@ -15,10 +15,10 @@ declare(strict_types=1);
namespace Ramsey\Uuid\Converter\Number;
/**
- * @deprecated DegradedNumberConverter is no longer necessary for converting
- * numbers on 32-bit systems. Transition to {@see GenericNumberConverter}.
+ * @deprecated DegradedNumberConverter is no longer necessary for converting numbers on 32-bit systems. Please
+ * transition to {@see GenericNumberConverter}.
*
- * @psalm-immutable
+ * @immutable
*/
class DegradedNumberConverter extends BigNumberConverter
{
diff --git a/vendor/ramsey/uuid/src/Converter/Number/GenericNumberConverter.php b/vendor/ramsey/uuid/src/Converter/Number/GenericNumberConverter.php
index 501eac0..86968ab 100644
--- a/vendor/ramsey/uuid/src/Converter/Number/GenericNumberConverter.php
+++ b/vendor/ramsey/uuid/src/Converter/Number/GenericNumberConverter.php
@@ -19,29 +19,18 @@ use Ramsey\Uuid\Math\CalculatorInterface;
use Ramsey\Uuid\Type\Integer as IntegerObject;
/**
- * GenericNumberConverter uses the provided calculator to convert decimal
- * numbers to and from hexadecimal values
+ * GenericNumberConverter uses the provided calculator to convert decimal numbers to and from hexadecimal values
*
- * @psalm-immutable
+ * @immutable
*/
class GenericNumberConverter implements NumberConverterInterface
{
- /**
- * @var CalculatorInterface
- */
- private $calculator;
-
- public function __construct(CalculatorInterface $calculator)
+ public function __construct(private CalculatorInterface $calculator)
{
- $this->calculator = $calculator;
}
/**
- * @inheritDoc
- * @psalm-pure
- * @psalm-return numeric-string
- * @psalm-suppress MoreSpecificReturnType we know that the retrieved `string` is never empty
- * @psalm-suppress LessSpecificReturnStatement we know that the retrieved `string` is never empty
+ * @pure
*/
public function fromHex(string $hex): string
{
@@ -49,15 +38,11 @@ class GenericNumberConverter implements NumberConverterInterface
}
/**
- * @inheritDoc
- * @psalm-pure
- * @psalm-return non-empty-string
- * @psalm-suppress MoreSpecificReturnType we know that the retrieved `string` is never empty
- * @psalm-suppress LessSpecificReturnStatement we know that the retrieved `string` is never empty
+ * @pure
*/
public function toHex(string $number): string
{
- /** @phpstan-ignore-next-line PHPStan complains that this is not a non-empty-string. */
+ /** @phpstan-ignore return.type, possiblyImpure.new */
return $this->calculator->toBase(new IntegerObject($number), 16);
}
}
diff --git a/vendor/ramsey/uuid/src/Converter/NumberConverterInterface.php b/vendor/ramsey/uuid/src/Converter/NumberConverterInterface.php
index b33ec31..63eca6c 100644
--- a/vendor/ramsey/uuid/src/Converter/NumberConverterInterface.php
+++ b/vendor/ramsey/uuid/src/Converter/NumberConverterInterface.php
@@ -15,43 +15,35 @@ declare(strict_types=1);
namespace Ramsey\Uuid\Converter;
/**
- * A number converter converts UUIDs from hexadecimal characters into
- * representations of integers and vice versa
+ * A number converter converts UUIDs from hexadecimal characters into representations of integers and vice versa
*
- * @psalm-immutable
+ * @immutable
*/
interface NumberConverterInterface
{
/**
- * Converts a hexadecimal number into an string integer representation of
- * the number
+ * Converts a hexadecimal number into a string integer representation of the number
*
- * The integer representation returned is a string representation of the
- * integer, to accommodate unsigned integers greater than PHP_INT_MAX.
+ * The integer representation returned is a string representation of the integer to accommodate unsigned integers
+ * that are greater than `PHP_INT_MAX`.
*
* @param string $hex The hexadecimal string representation to convert
*
- * @return string String representation of an integer
+ * @return numeric-string String representation of an integer
*
- * @psalm-return numeric-string
- *
- * @psalm-pure
+ * @pure
*/
public function fromHex(string $hex): string;
/**
- * Converts a string integer representation into a hexadecimal string
- * representation of the number
+ * Converts a string integer representation into a hexadecimal string representation of the number
*
- * @param string $number A string integer representation to convert; this
- * must be a numeric string to accommodate unsigned integers greater
- * than PHP_INT_MAX.
+ * @param string $number A string integer representation to convert; this must be a numeric string to accommodate
+ * unsigned integers that are greater than `PHP_INT_MAX`.
*
- * @return string Hexadecimal string
+ * @return non-empty-string Hexadecimal string
*
- * @psalm-return non-empty-string
- *
- * @psalm-pure
+ * @pure
*/
public function toHex(string $number): string;
}
diff --git a/vendor/ramsey/uuid/src/Converter/Time/BigNumberTimeConverter.php b/vendor/ramsey/uuid/src/Converter/Time/BigNumberTimeConverter.php
index 7390dad..7112495 100644
--- a/vendor/ramsey/uuid/src/Converter/Time/BigNumberTimeConverter.php
+++ b/vendor/ramsey/uuid/src/Converter/Time/BigNumberTimeConverter.php
@@ -20,19 +20,16 @@ use Ramsey\Uuid\Type\Hexadecimal;
use Ramsey\Uuid\Type\Time;
/**
- * Previously used to integrate moontoast/math as a bignum arithmetic library,
- * BigNumberTimeConverter is deprecated in favor of GenericTimeConverter
+ * Previously used to integrate moontoast/math as a bignum arithmetic library, BigNumberTimeConverter is deprecated in
+ * favor of GenericTimeConverter
*
- * @deprecated Transition to {@see GenericTimeConverter}.
+ * @deprecated Please transition to {@see GenericTimeConverter}.
*
- * @psalm-immutable
+ * @immutable
*/
class BigNumberTimeConverter implements TimeConverterInterface
{
- /**
- * @var TimeConverterInterface
- */
- private $converter;
+ private TimeConverterInterface $converter;
public function __construct()
{
diff --git a/vendor/ramsey/uuid/src/Converter/Time/DegradedTimeConverter.php b/vendor/ramsey/uuid/src/Converter/Time/DegradedTimeConverter.php
index cdc2875..4720450 100644
--- a/vendor/ramsey/uuid/src/Converter/Time/DegradedTimeConverter.php
+++ b/vendor/ramsey/uuid/src/Converter/Time/DegradedTimeConverter.php
@@ -15,10 +15,10 @@ declare(strict_types=1);
namespace Ramsey\Uuid\Converter\Time;
/**
- * @deprecated DegradedTimeConverter is no longer necessary for converting
- * time on 32-bit systems. Transition to {@see GenericTimeConverter}.
+ * @deprecated DegradedTimeConverter is no longer necessary for converting time on 32-bit systems. Please transition to
+ * {@see GenericTimeConverter}.
*
- * @psalm-immutable
+ * @immutable
*/
class DegradedTimeConverter extends BigNumberTimeConverter
{
diff --git a/vendor/ramsey/uuid/src/Converter/Time/GenericTimeConverter.php b/vendor/ramsey/uuid/src/Converter/Time/GenericTimeConverter.php
index a8aa64b..1079e88 100644
--- a/vendor/ramsey/uuid/src/Converter/Time/GenericTimeConverter.php
+++ b/vendor/ramsey/uuid/src/Converter/Time/GenericTimeConverter.php
@@ -27,16 +27,14 @@ use function str_pad;
use const STR_PAD_LEFT;
/**
- * GenericTimeConverter uses the provided calculator to calculate and convert
- * time values
+ * GenericTimeConverter uses the provided calculator to calculate and convert time values
*
- * @psalm-immutable
+ * @immutable
*/
class GenericTimeConverter implements TimeConverterInterface
{
/**
- * The number of 100-nanosecond intervals from the Gregorian calendar epoch
- * to the Unix epoch.
+ * The number of 100-nanosecond intervals from the Gregorian calendar epoch to the Unix epoch.
*/
private const GREGORIAN_TO_UNIX_INTERVALS = '122192928000000000';
@@ -50,63 +48,52 @@ class GenericTimeConverter implements TimeConverterInterface
*/
private const MICROSECOND_INTERVALS = '10';
- /**
- * @var CalculatorInterface
- */
- private $calculator;
-
- public function __construct(CalculatorInterface $calculator)
+ public function __construct(private CalculatorInterface $calculator)
{
- $this->calculator = $calculator;
}
public function calculateTime(string $seconds, string $microseconds): Hexadecimal
{
+ /** @phpstan-ignore possiblyImpure.new */
$timestamp = new Time($seconds, $microseconds);
// Convert the seconds into a count of 100-nanosecond intervals.
$sec = $this->calculator->multiply(
$timestamp->getSeconds(),
- new IntegerObject(self::SECOND_INTERVALS)
+ new IntegerObject(self::SECOND_INTERVALS), /** @phpstan-ignore possiblyImpure.new */
);
// Convert the microseconds into a count of 100-nanosecond intervals.
$usec = $this->calculator->multiply(
$timestamp->getMicroseconds(),
- new IntegerObject(self::MICROSECOND_INTERVALS)
+ new IntegerObject(self::MICROSECOND_INTERVALS), /** @phpstan-ignore possiblyImpure.new */
);
- // Combine the seconds and microseconds intervals and add the count of
- // 100-nanosecond intervals from the Gregorian calendar epoch to the
- // Unix epoch. This gives us the correct count of 100-nanosecond
- // intervals since the Gregorian calendar epoch for the given seconds
- // and microseconds.
- /** @var IntegerObject $uuidTime */
- $uuidTime = $this->calculator->add(
- $sec,
- $usec,
- new IntegerObject(self::GREGORIAN_TO_UNIX_INTERVALS)
- );
+ /**
+ * Combine the intervals of seconds and microseconds and add the count of 100-nanosecond intervals from the
+ * Gregorian calendar epoch to the Unix epoch. This gives us the correct count of 100-nanosecond intervals since
+ * the Gregorian calendar epoch for the given seconds and microseconds.
+ *
+ * @var IntegerObject $uuidTime
+ * @phpstan-ignore possiblyImpure.new
+ */
+ $uuidTime = $this->calculator->add($sec, $usec, new IntegerObject(self::GREGORIAN_TO_UNIX_INTERVALS));
- $uuidTimeHex = str_pad(
- $this->calculator->toHexadecimal($uuidTime)->toString(),
- 16,
- '0',
- STR_PAD_LEFT
- );
-
- return new Hexadecimal($uuidTimeHex);
+ /**
+ * PHPStan considers CalculatorInterface::toHexadecimal, Hexadecimal:toString impure.
+ *
+ * @phpstan-ignore possiblyImpure.new
+ */
+ return new Hexadecimal(str_pad($this->calculator->toHexadecimal($uuidTime)->toString(), 16, '0', STR_PAD_LEFT));
}
public function convertTime(Hexadecimal $uuidTimestamp): Time
{
- // From the total, subtract the number of 100-nanosecond intervals from
- // the Gregorian calendar epoch to the Unix epoch. This gives us the
- // number of 100-nanosecond intervals from the Unix epoch, which also
- // includes the microtime.
+ // From the total, subtract the number of 100-nanosecond intervals from the Gregorian calendar epoch to the Unix
+ // epoch. This gives us the number of 100-nanosecond intervals from the Unix epoch, which also includes the microtime.
$epochNanoseconds = $this->calculator->subtract(
$this->calculator->toInteger($uuidTimestamp),
- new IntegerObject(self::GREGORIAN_TO_UNIX_INTERVALS)
+ new IntegerObject(self::GREGORIAN_TO_UNIX_INTERVALS), /** @phpstan-ignore possiblyImpure.new */
);
// Convert the 100-nanosecond intervals into seconds and microseconds.
@@ -114,11 +101,12 @@ class GenericTimeConverter implements TimeConverterInterface
RoundingMode::HALF_UP,
6,
$epochNanoseconds,
- new IntegerObject(self::SECOND_INTERVALS)
+ new IntegerObject(self::SECOND_INTERVALS), /** @phpstan-ignore possiblyImpure.new */
);
$split = explode('.', (string) $unixTimestamp, 2);
+ /** @phpstan-ignore possiblyImpure.new */
return new Time($split[0], $split[1] ?? 0);
}
}
diff --git a/vendor/ramsey/uuid/src/Converter/Time/PhpTimeConverter.php b/vendor/ramsey/uuid/src/Converter/Time/PhpTimeConverter.php
index 538d2f2..67dbf88 100644
--- a/vendor/ramsey/uuid/src/Converter/Time/PhpTimeConverter.php
+++ b/vendor/ramsey/uuid/src/Converter/Time/PhpTimeConverter.php
@@ -34,48 +34,35 @@ use const STR_PAD_LEFT;
use const STR_PAD_RIGHT;
/**
- * PhpTimeConverter uses built-in PHP functions and standard math operations
- * available to the PHP programming language to provide facilities for
- * converting parts of time into representations that may be used in UUIDs
+ * PhpTimeConverter uses built-in PHP functions and standard math operations available to the PHP programming language
+ * to provide facilities for converting parts of time into representations that may be used in UUIDs
*
- * @psalm-immutable
+ * @immutable
*/
class PhpTimeConverter implements TimeConverterInterface
{
/**
- * The number of 100-nanosecond intervals from the Gregorian calendar epoch
- * to the Unix epoch.
+ * The number of 100-nanosecond intervals from the Gregorian calendar epoch to the Unix epoch.
*/
private const GREGORIAN_TO_UNIX_INTERVALS = 0x01b21dd213814000;
/**
* The number of 100-nanosecond intervals in one second.
*/
- private const SECOND_INTERVALS = 10000000;
+ private const SECOND_INTERVALS = 10_000_000;
/**
* The number of 100-nanosecond intervals in one microsecond.
*/
private const MICROSECOND_INTERVALS = 10;
- /**
- * @var CalculatorInterface
- */
- private $calculator;
-
- /**
- * @var TimeConverterInterface
- */
- private $fallbackConverter;
-
- /**
- * @var int
- */
- private $phpPrecision;
+ private int $phpPrecision;
+ private CalculatorInterface $calculator;
+ private TimeConverterInterface $fallbackConverter;
public function __construct(
?CalculatorInterface $calculator = null,
- ?TimeConverterInterface $fallbackConverter = null
+ ?TimeConverterInterface $fallbackConverter = null,
) {
if ($calculator === null) {
$calculator = new BrickMathCalculator();
@@ -92,26 +79,29 @@ class PhpTimeConverter implements TimeConverterInterface
public function calculateTime(string $seconds, string $microseconds): Hexadecimal
{
- $seconds = new IntegerObject($seconds);
- $microseconds = new IntegerObject($microseconds);
+ $seconds = new IntegerObject($seconds); /** @phpstan-ignore possiblyImpure.new */
+ $microseconds = new IntegerObject($microseconds); /** @phpstan-ignore possiblyImpure.new */
- // Calculate the count of 100-nanosecond intervals since the Gregorian
- // calendar epoch for the given seconds and microseconds.
+ // Calculate the count of 100-nanosecond intervals since the Gregorian calendar epoch
+ // for the given seconds and microseconds.
$uuidTime = ((int) $seconds->toString() * self::SECOND_INTERVALS)
+ ((int) $microseconds->toString() * self::MICROSECOND_INTERVALS)
+ self::GREGORIAN_TO_UNIX_INTERVALS;
// Check to see whether we've overflowed the max/min integer size.
// If so, we will default to a different time converter.
- /** @psalm-suppress RedundantCondition */
+ // @phpstan-ignore function.alreadyNarrowedType (the integer value might have overflowed)
if (!is_int($uuidTime)) {
return $this->fallbackConverter->calculateTime(
$seconds->toString(),
- $microseconds->toString()
+ $microseconds->toString(),
);
}
- return new Hexadecimal(str_pad(dechex($uuidTime), 16, '0', STR_PAD_LEFT));
+ /** @phpstan-ignore possiblyImpure.new */
+ return new Hexadecimal(
+ str_pad(dechex($uuidTime), 16, '0', STR_PAD_LEFT)
+ );
}
public function convertTime(Hexadecimal $uuidTimestamp): Time
@@ -120,44 +110,41 @@ class PhpTimeConverter implements TimeConverterInterface
// Convert the 100-nanosecond intervals into seconds and microseconds.
$splitTime = $this->splitTime(
- ((int) $timestamp->toString() - self::GREGORIAN_TO_UNIX_INTERVALS)
- / self::SECOND_INTERVALS
+ ((int) $timestamp->toString() - self::GREGORIAN_TO_UNIX_INTERVALS) / self::SECOND_INTERVALS,
);
if (count($splitTime) === 0) {
return $this->fallbackConverter->convertTime($uuidTimestamp);
}
+ /** @phpstan-ignore possiblyImpure.new */
return new Time($splitTime['sec'], $splitTime['usec']);
}
/**
- * @param int|float $time The time to split into seconds and microseconds
+ * @param float | int $time The time to split into seconds and microseconds
*
* @return string[]
+ *
+ * @pure
*/
- private function splitTime($time): array
+ private function splitTime(float | int $time): array
{
$split = explode('.', (string) $time, 2);
- // If the $time value is a float but $split only has 1 element, then the
- // float math was rounded up to the next second, so we want to return
- // an empty array to allow use of the fallback converter.
+ // If the $time value is a float but $split only has 1 element, then the float math was rounded up to the next
+ // second, so we want to return an empty array to allow use of the fallback converter.
if (is_float($time) && count($split) === 1) {
return [];
}
if (count($split) === 1) {
- return [
- 'sec' => $split[0],
- 'usec' => '0',
- ];
+ return ['sec' => $split[0], 'usec' => '0'];
}
- // If the microseconds are less than six characters AND the length of
- // the number is greater than or equal to the PHP precision, then it's
- // possible that we lost some precision for the microseconds. Return an
- // empty array, so that we can choose to use the fallback converter.
+ // If the microseconds are less than six characters AND the length of the number is greater than or equal to the
+ // PHP precision, then it's possible that we lost some precision for the microseconds. Return an empty array so
+ // that we can choose to use the fallback converter.
if (strlen($split[1]) < 6 && strlen((string) $time) >= $this->phpPrecision) {
return [];
}
diff --git a/vendor/ramsey/uuid/src/Converter/Time/UnixTimeConverter.php b/vendor/ramsey/uuid/src/Converter/Time/UnixTimeConverter.php
new file mode 100644
index 0000000..4bd4125
--- /dev/null
+++ b/vendor/ramsey/uuid/src/Converter/Time/UnixTimeConverter.php
@@ -0,0 +1,92 @@
+
+ * @license http://opensource.org/licenses/MIT MIT
+ */
+
+declare(strict_types=1);
+
+namespace Ramsey\Uuid\Converter\Time;
+
+use Ramsey\Uuid\Converter\TimeConverterInterface;
+use Ramsey\Uuid\Math\CalculatorInterface;
+use Ramsey\Uuid\Math\RoundingMode;
+use Ramsey\Uuid\Type\Hexadecimal;
+use Ramsey\Uuid\Type\Integer as IntegerObject;
+use Ramsey\Uuid\Type\Time;
+
+use function explode;
+use function str_pad;
+
+use const STR_PAD_LEFT;
+
+/**
+ * UnixTimeConverter converts Unix Epoch timestamps to/from hexadecimal values consisting of milliseconds elapsed since
+ * the Unix Epoch
+ *
+ * @immutable
+ */
+class UnixTimeConverter implements TimeConverterInterface
+{
+ private const MILLISECONDS = 1000;
+
+ public function __construct(private CalculatorInterface $calculator)
+ {
+ }
+
+ public function calculateTime(string $seconds, string $microseconds): Hexadecimal
+ {
+ /** @phpstan-ignore possiblyImpure.new */
+ $timestamp = new Time($seconds, $microseconds);
+
+ // Convert the seconds into milliseconds.
+ $sec = $this->calculator->multiply(
+ $timestamp->getSeconds(),
+ new IntegerObject(self::MILLISECONDS) /** @phpstan-ignore possiblyImpure.new */
+ );
+
+ // Convert the microseconds into milliseconds; the scale is zero because we need to discard the fractional part.
+ $usec = $this->calculator->divide(
+ RoundingMode::DOWN, // Always round down to stay in the previous millisecond.
+ 0,
+ $timestamp->getMicroseconds(),
+ new IntegerObject(self::MILLISECONDS), /** @phpstan-ignore possiblyImpure.new */
+ );
+
+ /** @var IntegerObject $unixTime */
+ $unixTime = $this->calculator->add($sec, $usec);
+
+ /** @phpstan-ignore possiblyImpure.new */
+ return new Hexadecimal(
+ str_pad(
+ $this->calculator->toHexadecimal($unixTime)->toString(),
+ 12,
+ '0',
+ STR_PAD_LEFT
+ ),
+ );
+ }
+
+ public function convertTime(Hexadecimal $uuidTimestamp): Time
+ {
+ $milliseconds = $this->calculator->toInteger($uuidTimestamp);
+
+ $unixTimestamp = $this->calculator->divide(
+ RoundingMode::HALF_UP,
+ 6,
+ $milliseconds,
+ new IntegerObject(self::MILLISECONDS), /** @phpstan-ignore possiblyImpure.new */
+ );
+
+ $split = explode('.', (string) $unixTimestamp, 2);
+
+ /** @phpstan-ignore possiblyImpure.new */
+ return new Time($split[0], $split[1] ?? '0');
+ }
+}
diff --git a/vendor/ramsey/uuid/src/Converter/TimeConverterInterface.php b/vendor/ramsey/uuid/src/Converter/TimeConverterInterface.php
index 1e84807..065e3b7 100644
--- a/vendor/ramsey/uuid/src/Converter/TimeConverterInterface.php
+++ b/vendor/ramsey/uuid/src/Converter/TimeConverterInterface.php
@@ -18,41 +18,36 @@ use Ramsey\Uuid\Type\Hexadecimal;
use Ramsey\Uuid\Type\Time;
/**
- * A time converter converts timestamps into representations that may be used
- * in UUIDs
+ * A time converter converts timestamps into representations that may be used in UUIDs
*
- * @psalm-immutable
+ * @immutable
*/
interface TimeConverterInterface
{
/**
- * Uses the provided seconds and micro-seconds to calculate the count of
- * 100-nanosecond intervals since UTC 00:00:00.00, 15 October 1582, for
- * RFC 4122 variant UUIDs
+ * Uses the provided seconds and micro-seconds to calculate the count of 100-nanosecond intervals since
+ * UTC 00:00:00.00, 15 October 1582, for RFC 9562 (formerly RFC 4122) variant UUIDs
*
- * @link http://tools.ietf.org/html/rfc4122#section-4.2.2 RFC 4122, § 4.2.2: Generation Details
+ * @link https://www.rfc-editor.org/rfc/rfc9562#appendix-A RFC 9562, Appendix A. Test Vectors
*
- * @param string $seconds A string representation of the number of seconds
- * since the Unix epoch for the time to calculate
- * @param string $microseconds A string representation of the micro-seconds
- * associated with the time to calculate
+ * @param string $seconds A string representation of seconds since the Unix epoch for the time to calculate
+ * @param string $microseconds A string representation of the micro-seconds associated with the time to calculate
*
* @return Hexadecimal The full UUID timestamp as a Hexadecimal value
*
- * @psalm-pure
+ * @pure
*/
public function calculateTime(string $seconds, string $microseconds): Hexadecimal;
/**
* Converts a timestamp extracted from a UUID to a Unix timestamp
*
- * @param Hexadecimal $uuidTimestamp A hexadecimal representation of a UUID
- * timestamp; a UUID timestamp is a count of 100-nanosecond intervals
- * since UTC 00:00:00.00, 15 October 1582.
+ * @param Hexadecimal $uuidTimestamp A hexadecimal representation of a UUID timestamp; a UUID timestamp is a count
+ * of 100-nanosecond intervals since UTC 00:00:00.00, 15 October 1582.
*
* @return Time An instance of {@see Time}
*
- * @psalm-pure
+ * @pure
*/
public function convertTime(Hexadecimal $uuidTimestamp): Time;
}
diff --git a/vendor/ramsey/uuid/src/DegradedUuid.php b/vendor/ramsey/uuid/src/DegradedUuid.php
index 9166042..169976e 100644
--- a/vendor/ramsey/uuid/src/DegradedUuid.php
+++ b/vendor/ramsey/uuid/src/DegradedUuid.php
@@ -15,10 +15,10 @@ declare(strict_types=1);
namespace Ramsey\Uuid;
/**
- * @deprecated DegradedUuid is no longer necessary to represent UUIDs on 32-bit
- * systems. Transition typehints to {@see UuidInterface}.
+ * @deprecated DegradedUuid is no longer necessary to represent UUIDs on 32-bit systems.
+ * Transition any type declarations using this class to {@see UuidInterface}.
*
- * @psalm-immutable
+ * @immutable
*/
class DegradedUuid extends Uuid
{
diff --git a/vendor/ramsey/uuid/src/DeprecatedUuidInterface.php b/vendor/ramsey/uuid/src/DeprecatedUuidInterface.php
index ed6d9de..91dbbc6 100644
--- a/vendor/ramsey/uuid/src/DeprecatedUuidInterface.php
+++ b/vendor/ramsey/uuid/src/DeprecatedUuidInterface.php
@@ -18,128 +18,107 @@ use DateTimeInterface;
use Ramsey\Uuid\Converter\NumberConverterInterface;
/**
- * This interface encapsulates deprecated methods for ramsey/uuid; this
- * interface and its methods will be removed in ramsey/uuid 5.0.0.
+ * This interface encapsulates deprecated methods for ramsey/uuid
*
- * @psalm-immutable
+ * @immutable
*/
interface DeprecatedUuidInterface
{
/**
- * @deprecated This method will be removed in 5.0.0. There is no alternative
- * recommendation, so plan accordingly.
+ * @deprecated This method will be removed in 5.0.0. There is no alternative recommendation, so plan accordingly.
*/
public function getNumberConverter(): NumberConverterInterface;
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance.
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see FieldsInterface} instance.
*
* @return string[]
*/
public function getFieldsHex(): array;
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see FieldsInterface} instance. If it is a
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getClockSeqHiAndReserved()}.
*/
public function getClockSeqHiAndReservedHex(): string;
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see FieldsInterface} instance. If it is a
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getClockSeqLow()}.
*/
public function getClockSeqLowHex(): string;
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see FieldsInterface} instance. If it is a
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getClockSeq()}.
*/
public function getClockSequenceHex(): string;
/**
- * @deprecated In ramsey/uuid version 5.0.0, this will be removed from the
- * interface. It is available at {@see UuidV1::getDateTime()}.
+ * @deprecated In ramsey/uuid version 5.0.0, this will be removed from the interface. It is available at
+ * {@see UuidV1::getDateTime()}.
*/
public function getDateTime(): DateTimeInterface;
/**
- * @deprecated This method will be removed in 5.0.0. There is no direct
- * alternative, but the same information may be obtained by splitting
- * in half the value returned by {@see UuidInterface::getHex()}.
+ * @deprecated This method will be removed in 5.0.0. There is no direct alternative, but the same information may be
+ * obtained by splitting in half the value returned by {@see UuidInterface::getHex()}.
*/
public function getLeastSignificantBitsHex(): string;
/**
- * @deprecated This method will be removed in 5.0.0. There is no direct
- * alternative, but the same information may be obtained by splitting
- * in half the value returned by {@see UuidInterface::getHex()}.
+ * @deprecated This method will be removed in 5.0.0. There is no direct alternative, but the same information may be
+ * obtained by splitting in half the value returned by {@see UuidInterface::getHex()}.
*/
public function getMostSignificantBitsHex(): string;
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see FieldsInterface} instance. If it is a
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getNode()}.
*/
public function getNodeHex(): string;
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see FieldsInterface} instance. If it is a
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getTimeHiAndVersion()}.
*/
public function getTimeHiAndVersionHex(): string;
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see FieldsInterface} instance. If it is a
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getTimeLow()}.
*/
public function getTimeLowHex(): string;
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see FieldsInterface} instance. If it is a
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getTimeMid()}.
*/
public function getTimeMidHex(): string;
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see FieldsInterface} instance. If it is a
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getTimestamp()}.
*/
public function getTimestampHex(): string;
/**
- * @deprecated In ramsey/uuid version 5.0.0, this will be removed from this
- * interface. It has moved to {@see \Ramsey\Uuid\Rfc4122\UuidInterface::getUrn()}.
- */
- public function getUrn(): string;
-
- /**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see FieldsInterface} instance. If it is a
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getVariant()}.
*/
public function getVariant(): ?int;
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see FieldsInterface} instance. If it is a
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getVersion()}.
*/
diff --git a/vendor/ramsey/uuid/src/DeprecatedUuidMethodsTrait.php b/vendor/ramsey/uuid/src/DeprecatedUuidMethodsTrait.php
index 3428295..fb88578 100644
--- a/vendor/ramsey/uuid/src/DeprecatedUuidMethodsTrait.php
+++ b/vendor/ramsey/uuid/src/DeprecatedUuidMethodsTrait.php
@@ -17,10 +17,8 @@ namespace Ramsey\Uuid;
use DateTimeImmutable;
use DateTimeInterface;
use Ramsey\Uuid\Converter\NumberConverterInterface;
-use Ramsey\Uuid\Converter\TimeConverterInterface;
use Ramsey\Uuid\Exception\DateTimeException;
use Ramsey\Uuid\Exception\UnsupportedOperationException;
-use Ramsey\Uuid\Rfc4122\FieldsInterface as Rfc4122FieldsInterface;
use Throwable;
use function str_pad;
@@ -29,34 +27,19 @@ use function substr;
use const STR_PAD_LEFT;
/**
- * This trait encapsulates deprecated methods for ramsey/uuid; this trait and
- * its methods will be removed in ramsey/uuid 5.0.0.
+ * This trait encapsulates deprecated methods for ramsey/uuid; this trait and its methods will be removed in ramsey/uuid 5.0.0.
*
- * @psalm-immutable
+ * @deprecated This trait and its methods will be removed in ramsey/uuid 5.0.0.
+ *
+ * @immutable
*/
trait DeprecatedUuidMethodsTrait
{
/**
- * @var Rfc4122FieldsInterface
- */
- protected $fields;
-
- /**
- * @var NumberConverterInterface
- */
- protected $numberConverter;
-
- /**
- * @var TimeConverterInterface
- */
- protected $timeConverter;
-
- /**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
- * instance, you may call {@see Rfc4122FieldsInterface::getClockSeqHiAndReserved()}
- * and use the arbitrary-precision math library of your choice to
- * convert it to a string integer.
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see \Ramsey\Uuid\Fields\FieldsInterface} instance.
+ * If it is a {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
+ * {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getClockSeqHiAndReserved()} and use the arbitrary-precision math
+ * library of your choice to convert it to a string integer.
*/
public function getClockSeqHiAndReserved(): string
{
@@ -64,9 +47,9 @@ trait DeprecatedUuidMethodsTrait
}
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
- * instance, you may call {@see Rfc4122FieldsInterface::getClockSeqHiAndReserved()}.
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see \Ramsey\Uuid\Fields\FieldsInterface} instance.
+ * If it is a {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
+ * {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getClockSeqHiAndReserved()}.
*/
public function getClockSeqHiAndReservedHex(): string
{
@@ -74,11 +57,10 @@ trait DeprecatedUuidMethodsTrait
}
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
- * instance, you may call {@see Rfc4122FieldsInterface::getClockSeqLow()}
- * and use the arbitrary-precision math library of your choice to
- * convert it to a string integer.
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see \Ramsey\Uuid\Fields\FieldsInterface} instance.
+ * If it is a {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
+ * {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getClockSeqLow()} and use the arbitrary-precision math library of
+ * your choice to convert it to a string integer.
*/
public function getClockSeqLow(): string
{
@@ -86,9 +68,9 @@ trait DeprecatedUuidMethodsTrait
}
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
- * instance, you may call {@see Rfc4122FieldsInterface::getClockSeqLow()}.
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see \Ramsey\Uuid\Fields\FieldsInterface} instance.
+ * If it is a {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
+ * {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getClockSeqLow()}.
*/
public function getClockSeqLowHex(): string
{
@@ -96,11 +78,10 @@ trait DeprecatedUuidMethodsTrait
}
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
- * instance, you may call {@see Rfc4122FieldsInterface::getClockSeq()}
- * and use the arbitrary-precision math library of your choice to
- * convert it to a string integer.
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see \Ramsey\Uuid\Fields\FieldsInterface} instance.
+ * If it is a {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
+ * {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getClockSeq()} and use the arbitrary-precision math library of
+ * your choice to convert it to a string integer.
*/
public function getClockSequence(): string
{
@@ -108,9 +89,9 @@ trait DeprecatedUuidMethodsTrait
}
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
- * instance, you may call {@see Rfc4122FieldsInterface::getClockSeq()}.
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see \Ramsey\Uuid\Fields\FieldsInterface} instance.
+ * If it is a {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
+ * {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getClockSeq()}.
*/
public function getClockSequenceHex(): string
{
@@ -118,8 +99,7 @@ trait DeprecatedUuidMethodsTrait
}
/**
- * @deprecated This method will be removed in 5.0.0. There is no alternative
- * recommendation, so plan accordingly.
+ * @deprecated This method will be removed in 5.0.0. There is no alternative recommendation, so plan accordingly.
*/
public function getNumberConverter(): NumberConverterInterface
{
@@ -127,8 +107,7 @@ trait DeprecatedUuidMethodsTrait
}
/**
- * @deprecated In ramsey/uuid version 5.0.0, this will be removed.
- * It is available at {@see UuidV1::getDateTime()}.
+ * @deprecated In ramsey/uuid version 5.0.0, this will be removed. It is available at {@see UuidV1::getDateTime()}.
*
* @return DateTimeImmutable An immutable instance of DateTimeInterface
*
@@ -156,8 +135,7 @@ trait DeprecatedUuidMethodsTrait
}
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance.
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see \Ramsey\Uuid\Fields\FieldsInterface} instance.
*
* @return string[]
*/
@@ -174,9 +152,8 @@ trait DeprecatedUuidMethodsTrait
}
/**
- * @deprecated This method will be removed in 5.0.0. There is no direct
- * alternative, but the same information may be obtained by splitting
- * in half the value returned by {@see UuidInterface::getHex()}.
+ * @deprecated This method will be removed in 5.0.0. There is no direct alternative, but the same information may be
+ * obtained by splitting in half the value returned by {@see UuidInterface::getHex()}.
*/
public function getLeastSignificantBits(): string
{
@@ -186,9 +163,8 @@ trait DeprecatedUuidMethodsTrait
}
/**
- * @deprecated This method will be removed in 5.0.0. There is no direct
- * alternative, but the same information may be obtained by splitting
- * in half the value returned by {@see UuidInterface::getHex()}.
+ * @deprecated This method will be removed in 5.0.0. There is no direct alternative, but the same information may be
+ * obtained by splitting in half the value returned by {@see UuidInterface::getHex()}.
*/
public function getLeastSignificantBitsHex(): string
{
@@ -196,9 +172,8 @@ trait DeprecatedUuidMethodsTrait
}
/**
- * @deprecated This method will be removed in 5.0.0. There is no direct
- * alternative, but the same information may be obtained by splitting
- * in half the value returned by {@see UuidInterface::getHex()}.
+ * @deprecated This method will be removed in 5.0.0. There is no direct alternative, but the same information may be
+ * obtained by splitting in half the value returned by {@see UuidInterface::getHex()}.
*/
public function getMostSignificantBits(): string
{
@@ -208,9 +183,8 @@ trait DeprecatedUuidMethodsTrait
}
/**
- * @deprecated This method will be removed in 5.0.0. There is no direct
- * alternative, but the same information may be obtained by splitting
- * in half the value returned by {@see UuidInterface::getHex()}.
+ * @deprecated This method will be removed in 5.0.0. There is no direct alternative, but the same information may be
+ * obtained by splitting in half the value returned by {@see UuidInterface::getHex()}.
*/
public function getMostSignificantBitsHex(): string
{
@@ -218,11 +192,10 @@ trait DeprecatedUuidMethodsTrait
}
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
- * instance, you may call {@see Rfc4122FieldsInterface::getNode()}
- * and use the arbitrary-precision math library of your choice to
- * convert it to a string integer.
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see \Ramsey\Uuid\Fields\FieldsInterface} instance.
+ * If it is a {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
+ * {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getNode()} and use the arbitrary-precision math library of your
+ * choice to convert it to a string integer.
*/
public function getNode(): string
{
@@ -230,9 +203,9 @@ trait DeprecatedUuidMethodsTrait
}
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
- * instance, you may call {@see Rfc4122FieldsInterface::getNode()}.
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see \Ramsey\Uuid\Fields\FieldsInterface} instance.
+ * If it is a {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
+ * {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getNode()}.
*/
public function getNodeHex(): string
{
@@ -240,11 +213,10 @@ trait DeprecatedUuidMethodsTrait
}
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
- * instance, you may call {@see Rfc4122FieldsInterface::getTimeHiAndVersion()}
- * and use the arbitrary-precision math library of your choice to
- * convert it to a string integer.
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see \Ramsey\Uuid\Fields\FieldsInterface} instance.
+ * If it is a {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
+ * {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getTimeHiAndVersion()} and use the arbitrary-precision math
+ * library of your choice to convert it to a string integer.
*/
public function getTimeHiAndVersion(): string
{
@@ -252,9 +224,9 @@ trait DeprecatedUuidMethodsTrait
}
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
- * instance, you may call {@see Rfc4122FieldsInterface::getTimeHiAndVersion()}.
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see \Ramsey\Uuid\Fields\FieldsInterface} instance.
+ * If it is a {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
+ * {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getTimeHiAndVersion()}.
*/
public function getTimeHiAndVersionHex(): string
{
@@ -262,11 +234,10 @@ trait DeprecatedUuidMethodsTrait
}
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
- * instance, you may call {@see Rfc4122FieldsInterface::getTimeLow()}
- * and use the arbitrary-precision math library of your choice to
- * convert it to a string integer.
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see \Ramsey\Uuid\Fields\FieldsInterface} instance.
+ * If it is a {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
+ * {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getTimeLow()} and use the arbitrary-precision math library of
+ * your choice to convert it to a string integer.
*/
public function getTimeLow(): string
{
@@ -274,9 +245,9 @@ trait DeprecatedUuidMethodsTrait
}
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
- * instance, you may call {@see Rfc4122FieldsInterface::getTimeLow()}.
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see \Ramsey\Uuid\Fields\FieldsInterface} instance.
+ * If it is a {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
+ * {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getTimeLow()}.
*/
public function getTimeLowHex(): string
{
@@ -284,11 +255,10 @@ trait DeprecatedUuidMethodsTrait
}
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
- * instance, you may call {@see Rfc4122FieldsInterface::getTimeMid()}
- * and use the arbitrary-precision math library of your choice to
- * convert it to a string integer.
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see \Ramsey\Uuid\Fields\FieldsInterface} instance.
+ * If it is a {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
+ * {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getTimeMid()} and use the arbitrary-precision math library of
+ * your choice to convert it to a string integer.
*/
public function getTimeMid(): string
{
@@ -296,9 +266,9 @@ trait DeprecatedUuidMethodsTrait
}
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
- * instance, you may call {@see Rfc4122FieldsInterface::getTimeMid()}.
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see \Ramsey\Uuid\Fields\FieldsInterface} instance.
+ * If it is a {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
+ * {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getTimeMid()}.
*/
public function getTimeMidHex(): string
{
@@ -306,11 +276,10 @@ trait DeprecatedUuidMethodsTrait
}
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
- * instance, you may call {@see Rfc4122FieldsInterface::getTimestamp()}
- * and use the arbitrary-precision math library of your choice to
- * convert it to a string integer.
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see \Ramsey\Uuid\Fields\FieldsInterface} instance.
+ * If it is a {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
+ * {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getTimestamp()} and use the arbitrary-precision math library of
+ * your choice to convert it to a string integer.
*/
public function getTimestamp(): string
{
@@ -322,9 +291,9 @@ trait DeprecatedUuidMethodsTrait
}
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
- * instance, you may call {@see Rfc4122FieldsInterface::getTimestamp()}.
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see \Ramsey\Uuid\Fields\FieldsInterface} instance.
+ * If it is a {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
+ * {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getTimestamp()}.
*/
public function getTimestampHex(): string
{
@@ -336,20 +305,8 @@ trait DeprecatedUuidMethodsTrait
}
/**
- * @deprecated This has moved to {@see Rfc4122FieldsInterface::getUrn()} and
- * is available on {@see \Ramsey\Uuid\Rfc4122\UuidV1},
- * {@see \Ramsey\Uuid\Rfc4122\UuidV3}, {@see \Ramsey\Uuid\Rfc4122\UuidV4},
- * and {@see \Ramsey\Uuid\Rfc4122\UuidV5}.
- */
- public function getUrn(): string
- {
- return 'urn:uuid:' . $this->toString();
- }
-
- /**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a
- * {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see \Ramsey\Uuid\Fields\FieldsInterface} instance.
+ * If it is a {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getVariant()}.
*/
public function getVariant(): ?int
@@ -358,9 +315,8 @@ trait DeprecatedUuidMethodsTrait
}
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a
- * {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see \Ramsey\Uuid\Fields\FieldsInterface} instance.
+ * If it is a {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getVersion()}.
*/
public function getVersion(): ?int
diff --git a/vendor/ramsey/uuid/src/Exception/DceSecurityException.php b/vendor/ramsey/uuid/src/Exception/DceSecurityException.php
index e6d8001..bd8ca4c 100644
--- a/vendor/ramsey/uuid/src/Exception/DceSecurityException.php
+++ b/vendor/ramsey/uuid/src/Exception/DceSecurityException.php
@@ -17,8 +17,7 @@ namespace Ramsey\Uuid\Exception;
use RuntimeException as PhpRuntimeException;
/**
- * Thrown to indicate an exception occurred while dealing with DCE Security
- * (version 2) UUIDs
+ * Thrown to indicate an exception occurred while dealing with DCE Security (version 2) UUIDs
*/
class DceSecurityException extends PhpRuntimeException implements UuidExceptionInterface
{
diff --git a/vendor/ramsey/uuid/src/Exception/InvalidUuidStringException.php b/vendor/ramsey/uuid/src/Exception/InvalidUuidStringException.php
index 6d97581..cfc7eee 100644
--- a/vendor/ramsey/uuid/src/Exception/InvalidUuidStringException.php
+++ b/vendor/ramsey/uuid/src/Exception/InvalidUuidStringException.php
@@ -17,8 +17,8 @@ namespace Ramsey\Uuid\Exception;
/**
* Thrown to indicate that the string received is not a valid UUID
*
- * The InvalidArgumentException that this extends is the ramsey/uuid version
- * of this exception. It exists in the same namespace as this class.
+ * The InvalidArgumentException that this extends is the ramsey/uuid version of this exception. It exists in the same
+ * namespace as this class.
*/
class InvalidUuidStringException extends InvalidArgumentException implements UuidExceptionInterface
{
diff --git a/vendor/ramsey/uuid/src/Exception/NameException.php b/vendor/ramsey/uuid/src/Exception/NameException.php
index fd96a1f..ee72e16 100644
--- a/vendor/ramsey/uuid/src/Exception/NameException.php
+++ b/vendor/ramsey/uuid/src/Exception/NameException.php
@@ -17,8 +17,7 @@ namespace Ramsey\Uuid\Exception;
use RuntimeException as PhpRuntimeException;
/**
- * Thrown to indicate that an error occurred while attempting to hash a
- * namespace and name
+ * Thrown to indicate that an error occurred while attempting to hash a namespace and name
*/
class NameException extends PhpRuntimeException implements UuidExceptionInterface
{
diff --git a/vendor/ramsey/uuid/src/Exception/RandomSourceException.php b/vendor/ramsey/uuid/src/Exception/RandomSourceException.php
index a44dd34..7b24604 100644
--- a/vendor/ramsey/uuid/src/Exception/RandomSourceException.php
+++ b/vendor/ramsey/uuid/src/Exception/RandomSourceException.php
@@ -19,8 +19,8 @@ use RuntimeException as PhpRuntimeException;
/**
* Thrown to indicate that the source of random data encountered an error
*
- * This exception is used mostly to indicate that random_bytes() or random_int()
- * threw an exception. However, it may be used for other sources of random data.
+ * This exception is used mostly to indicate that random_bytes() or random_int() threw an exception. However, it may be
+ * used for other sources of random data.
*/
class RandomSourceException extends PhpRuntimeException implements UuidExceptionInterface
{
diff --git a/vendor/ramsey/uuid/src/FeatureSet.php b/vendor/ramsey/uuid/src/FeatureSet.php
index a8ab2fd..88ce7c4 100644
--- a/vendor/ramsey/uuid/src/FeatureSet.php
+++ b/vendor/ramsey/uuid/src/FeatureSet.php
@@ -14,7 +14,6 @@ declare(strict_types=1);
namespace Ramsey\Uuid;
-use Ramsey\Uuid\Builder\BuilderCollection;
use Ramsey\Uuid\Builder\FallbackBuilder;
use Ramsey\Uuid\Builder\UuidBuilderInterface;
use Ramsey\Uuid\Codec\CodecInterface;
@@ -36,6 +35,7 @@ use Ramsey\Uuid\Generator\RandomGeneratorFactory;
use Ramsey\Uuid\Generator\RandomGeneratorInterface;
use Ramsey\Uuid\Generator\TimeGeneratorFactory;
use Ramsey\Uuid\Generator\TimeGeneratorInterface;
+use Ramsey\Uuid\Generator\UnixTimeGenerator;
use Ramsey\Uuid\Guid\GuidBuilder;
use Ramsey\Uuid\Math\BrickMathCalculator;
use Ramsey\Uuid\Math\CalculatorInterface;
@@ -43,7 +43,6 @@ use Ramsey\Uuid\Nonstandard\UuidBuilder as NonstandardUuidBuilder;
use Ramsey\Uuid\Provider\Dce\SystemDceSecurityProvider;
use Ramsey\Uuid\Provider\DceSecurityProviderInterface;
use Ramsey\Uuid\Provider\Node\FallbackNodeProvider;
-use Ramsey\Uuid\Provider\Node\NodeProviderCollection;
use Ramsey\Uuid\Provider\Node\RandomNodeProvider;
use Ramsey\Uuid\Provider\Node\SystemNodeProvider;
use Ramsey\Uuid\Provider\NodeProviderInterface;
@@ -58,123 +57,52 @@ use const PHP_INT_SIZE;
/**
* FeatureSet detects and exposes available features in the current environment
*
- * A feature set is used by UuidFactory to determine the available features and
- * capabilities of the environment.
+ * A feature set is used by UuidFactory to determine the available features and capabilities of the environment.
*/
class FeatureSet
{
- /**
- * @var bool
- */
- private $disableBigNumber = false;
-
- /**
- * @var bool
- */
- private $disable64Bit = false;
-
- /**
- * @var bool
- */
- private $ignoreSystemNode = false;
-
- /**
- * @var bool
- */
- private $enablePecl = false;
-
- /**
- * @var UuidBuilderInterface
- */
- private $builder;
-
- /**
- * @var CodecInterface
- */
- private $codec;
-
- /**
- * @var DceSecurityGeneratorInterface
- */
- private $dceSecurityGenerator;
-
- /**
- * @var NameGeneratorInterface
- */
- private $nameGenerator;
-
- /**
- * @var NodeProviderInterface
- */
- private $nodeProvider;
-
- /**
- * @var NumberConverterInterface
- */
- private $numberConverter;
-
- /**
- * @var TimeConverterInterface
- */
- private $timeConverter;
-
- /**
- * @var RandomGeneratorInterface
- */
- private $randomGenerator;
-
- /**
- * @var TimeGeneratorInterface
- */
- private $timeGenerator;
-
- /**
- * @var TimeProviderInterface
- */
- private $timeProvider;
-
- /**
- * @var ValidatorInterface
- */
- private $validator;
-
- /**
- * @var CalculatorInterface
- */
- private $calculator;
+ private ?TimeProviderInterface $timeProvider = null;
+ private CalculatorInterface $calculator;
+ private CodecInterface $codec;
+ private DceSecurityGeneratorInterface $dceSecurityGenerator;
+ private NameGeneratorInterface $nameGenerator;
+ private NodeProviderInterface $nodeProvider;
+ private NumberConverterInterface $numberConverter;
+ private RandomGeneratorInterface $randomGenerator;
+ private TimeConverterInterface $timeConverter;
+ private TimeGeneratorInterface $timeGenerator;
+ private TimeGeneratorInterface $unixTimeGenerator;
+ private UuidBuilderInterface $builder;
+ private ValidatorInterface $validator;
/**
* @param bool $useGuids True build UUIDs using the GuidStringCodec
- * @param bool $force32Bit True to force the use of 32-bit functionality
- * (primarily for testing purposes)
- * @param bool $forceNoBigNumber True to disable the use of moontoast/math
- * (primarily for testing purposes)
- * @param bool $ignoreSystemNode True to disable attempts to check for the
- * system node ID (primarily for testing purposes)
- * @param bool $enablePecl True to enable the use of the PeclUuidTimeGenerator
- * to generate version 1 UUIDs
+ * @param bool $force32Bit True to force the use of 32-bit functionality (primarily for testing purposes)
+ * @param bool $forceNoBigNumber (obsolete)
+ * @param bool $ignoreSystemNode True to disable attempts to check for the system node ID (primarily for testing purposes)
+ * @param bool $enablePecl True to enable the use of the PeclUuidTimeGenerator to generate version 1 UUIDs
+ *
+ * @phpstan-ignore constructor.unusedParameter ($forceNoBigNumber is deprecated)
*/
public function __construct(
bool $useGuids = false,
- bool $force32Bit = false,
+ private bool $force32Bit = false,
bool $forceNoBigNumber = false,
- bool $ignoreSystemNode = false,
- bool $enablePecl = false
+ private bool $ignoreSystemNode = false,
+ private bool $enablePecl = false,
) {
- $this->disableBigNumber = $forceNoBigNumber;
- $this->disable64Bit = $force32Bit;
- $this->ignoreSystemNode = $ignoreSystemNode;
- $this->enablePecl = $enablePecl;
-
+ $this->randomGenerator = $this->buildRandomGenerator();
$this->setCalculator(new BrickMathCalculator());
$this->builder = $this->buildUuidBuilder($useGuids);
$this->codec = $this->buildCodec($useGuids);
$this->nodeProvider = $this->buildNodeProvider();
$this->nameGenerator = $this->buildNameGenerator();
- $this->randomGenerator = $this->buildRandomGenerator();
$this->setTimeProvider(new SystemTimeProvider());
$this->setDceSecurityProvider(new SystemDceSecurityProvider());
$this->validator = new GenericValidator();
+
+ assert($this->timeProvider !== null);
+ $this->unixTimeGenerator = $this->buildUnixTimeGenerator();
}
/**
@@ -257,6 +185,14 @@ class FeatureSet
return $this->timeGenerator;
}
+ /**
+ * Returns the Unix Epoch time generator configured for this environment
+ */
+ public function getUnixTimeGenerator(): TimeGeneratorInterface
+ {
+ return $this->unixTimeGenerator;
+ }
+
/**
* Returns the validator configured for this environment
*/
@@ -274,7 +210,6 @@ class FeatureSet
$this->numberConverter = $this->buildNumberConverter($calculator);
$this->timeConverter = $this->buildTimeConverter($calculator);
- /** @psalm-suppress RedundantPropertyInitializationCheck */
if (isset($this->timeProvider)) {
$this->timeGenerator = $this->buildTimeGenerator($this->timeProvider);
}
@@ -294,7 +229,10 @@ class FeatureSet
public function setNodeProvider(NodeProviderInterface $nodeProvider): void
{
$this->nodeProvider = $nodeProvider;
- $this->timeGenerator = $this->buildTimeGenerator($this->timeProvider);
+
+ if (isset($this->timeProvider)) {
+ $this->timeGenerator = $this->buildTimeGenerator($this->timeProvider);
+ }
}
/**
@@ -332,13 +270,9 @@ class FeatureSet
* Returns a DCE Security generator configured for this environment
*/
private function buildDceSecurityGenerator(
- DceSecurityProviderInterface $dceSecurityProvider
+ DceSecurityProviderInterface $dceSecurityProvider,
): DceSecurityGeneratorInterface {
- return new DceSecurityGenerator(
- $this->numberConverter,
- $this->timeGenerator,
- $dceSecurityProvider
- );
+ return new DceSecurityGenerator($this->numberConverter, $this->timeGenerator, $dceSecurityProvider);
}
/**
@@ -350,10 +284,7 @@ class FeatureSet
return new RandomNodeProvider();
}
- return new FallbackNodeProvider(new NodeProviderCollection([
- new SystemNodeProvider(),
- new RandomNodeProvider(),
- ]));
+ return new FallbackNodeProvider([new SystemNodeProvider(), new RandomNodeProvider()]);
}
/**
@@ -388,11 +319,15 @@ class FeatureSet
return new PeclUuidTimeGenerator();
}
- return (new TimeGeneratorFactory(
- $this->nodeProvider,
- $this->timeConverter,
- $timeProvider
- ))->getGenerator();
+ return (new TimeGeneratorFactory($this->nodeProvider, $this->timeConverter, $timeProvider))->getGenerator();
+ }
+
+ /**
+ * Returns a Unix Epoch time generator configured for this environment
+ */
+ private function buildUnixTimeGenerator(): TimeGeneratorInterface
+ {
+ return new UnixTimeGenerator($this->randomGenerator);
}
/**
@@ -432,11 +367,10 @@ class FeatureSet
return new GuidBuilder($this->numberConverter, $this->timeConverter);
}
- /** @psalm-suppress ImpureArgument */
- return new FallbackBuilder(new BuilderCollection([
+ return new FallbackBuilder([
new Rfc4122UuidBuilder($this->numberConverter, $this->timeConverter),
new NonstandardUuidBuilder($this->numberConverter, $this->timeConverter),
- ]));
+ ]);
}
/**
@@ -444,6 +378,6 @@ class FeatureSet
*/
private function is64BitSystem(): bool
{
- return PHP_INT_SIZE === 8 && !$this->disable64Bit;
+ return PHP_INT_SIZE === 8 && !$this->force32Bit;
}
}
diff --git a/vendor/ramsey/uuid/src/Fields/FieldsInterface.php b/vendor/ramsey/uuid/src/Fields/FieldsInterface.php
index f1b7a29..f17ea88 100644
--- a/vendor/ramsey/uuid/src/Fields/FieldsInterface.php
+++ b/vendor/ramsey/uuid/src/Fields/FieldsInterface.php
@@ -17,16 +17,17 @@ namespace Ramsey\Uuid\Fields;
use Serializable;
/**
- * UUIDs are comprised of unsigned integers, the bytes of which are separated
- * into fields and arranged in a particular layout defined by the specification
- * for the variant
+ * UUIDs consist of unsigned integers, the bytes of which are separated into fields and arranged in a particular layout
+ * defined by the specification for the variant
*
- * @psalm-immutable
+ * @immutable
*/
interface FieldsInterface extends Serializable
{
/**
* Returns the bytes that comprise the fields
+ *
+ * @pure
*/
public function getBytes(): string;
}
diff --git a/vendor/ramsey/uuid/src/Fields/SerializableFieldsTrait.php b/vendor/ramsey/uuid/src/Fields/SerializableFieldsTrait.php
index 16e6525..9ea47c6 100644
--- a/vendor/ramsey/uuid/src/Fields/SerializableFieldsTrait.php
+++ b/vendor/ramsey/uuid/src/Fields/SerializableFieldsTrait.php
@@ -23,7 +23,7 @@ use function strlen;
/**
* Provides common serialization functionality to fields
*
- * @psalm-immutable
+ * @immutable
*/
trait SerializableFieldsTrait
{
@@ -38,7 +38,7 @@ trait SerializableFieldsTrait
abstract public function getBytes(): string;
/**
- * Returns a string representation of object
+ * Returns a string representation of the object
*/
public function serialize(): string
{
@@ -56,22 +56,19 @@ trait SerializableFieldsTrait
/**
* Constructs the object from a serialized string representation
*
- * @param string $serialized The serialized string representation of the object
- *
- * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
- * @psalm-suppress UnusedMethodCall
+ * @param string $data The serialized string representation of the object
*/
- public function unserialize($serialized): void
+ public function unserialize(string $data): void
{
- if (strlen($serialized) === 16) {
- $this->__construct($serialized);
+ if (strlen($data) === 16) {
+ $this->__construct($data);
} else {
- $this->__construct(base64_decode($serialized));
+ $this->__construct(base64_decode($data));
}
}
/**
- * @param array{bytes: string} $data
+ * @param array{bytes?: string} $data
*/
public function __unserialize(array $data): void
{
diff --git a/vendor/ramsey/uuid/src/Generator/CombGenerator.php b/vendor/ramsey/uuid/src/Generator/CombGenerator.php
index 49b0938..5f6fa1d 100644
--- a/vendor/ramsey/uuid/src/Generator/CombGenerator.php
+++ b/vendor/ramsey/uuid/src/Generator/CombGenerator.php
@@ -29,94 +29,79 @@ use const STR_PAD_LEFT;
/**
* CombGenerator generates COMBs (combined UUID/timestamp)
*
- * The CombGenerator, when used with the StringCodec (and, by proxy, the
- * TimestampLastCombCodec) or the TimestampFirstCombCodec, combines the current
- * timestamp with a UUID (hence the name "COMB"). The timestamp either appears
- * as the first or last 48 bits of the COMB, depending on the codec used.
+ * The CombGenerator, when used with the StringCodec (and, by proxy, the TimestampLastCombCodec) or the
+ * TimestampFirstCombCodec, combines the current timestamp with a UUID (hence the name "COMB"). The timestamp either
+ * appears as the first or last 48 bits of the COMB, depending on the codec used.
*
- * By default, COMBs will have the timestamp set as the last 48 bits of the
- * identifier.
+ * By default, COMBs will have the timestamp set as the last 48 bits of the identifier.
*
- * ``` php
+ * ```
* $factory = new UuidFactory();
*
* $factory->setRandomGenerator(new CombGenerator(
* $factory->getRandomGenerator(),
- * $factory->getNumberConverter()
+ * $factory->getNumberConverter(),
* ));
*
* $comb = $factory->uuid4();
* ```
*
- * To generate a COMB with the timestamp as the first 48 bits, set the
- * TimestampFirstCombCodec as the codec.
+ * To generate a COMB with the timestamp as the first 48 bits, set the TimestampFirstCombCodec as the codec.
*
- * ``` php
+ * ```
* $factory->setCodec(new TimestampFirstCombCodec($factory->getUuidBuilder()));
* ```
*
- * @link https://www.informit.com/articles/printerfriendly/25862 The Cost of GUIDs as Primary Keys
+ * @deprecated Please migrate to {@link https://uuid.ramsey.dev/en/stable/rfc4122/version7.html Version 7, Unix Epoch Time UUIDs}.
+ *
+ * @link https://web.archive.org/web/20240118030355/https://www.informit.com/articles/printerfriendly/25862 The Cost of GUIDs as Primary Keys
*/
class CombGenerator implements RandomGeneratorInterface
{
public const TIMESTAMP_BYTES = 6;
- /**
- * @var RandomGeneratorInterface
- */
- private $randomGenerator;
-
- /**
- * @var NumberConverterInterface
- */
- private $converter;
-
public function __construct(
- RandomGeneratorInterface $generator,
- NumberConverterInterface $numberConverter
+ private RandomGeneratorInterface $generator,
+ private NumberConverterInterface $numberConverter
) {
- $this->converter = $numberConverter;
- $this->randomGenerator = $generator;
}
/**
- * @throws InvalidArgumentException if $length is not a positive integer
- * greater than or equal to CombGenerator::TIMESTAMP_BYTES
+ * @throws InvalidArgumentException if $length is not a positive integer greater than or equal to CombGenerator::TIMESTAMP_BYTES
*
* @inheritDoc
*/
public function generate(int $length): string
{
- if ($length < self::TIMESTAMP_BYTES || $length < 0) {
+ if ($length < self::TIMESTAMP_BYTES) {
throw new InvalidArgumentException(
'Length must be a positive integer greater than or equal to ' . self::TIMESTAMP_BYTES
);
}
+ if ($length % 2 !== 0) {
+ throw new InvalidArgumentException('Length must be an even number');
+ }
+
$hash = '';
+
+ /** @phpstan-ignore greater.alwaysTrue (TIMESTAMP_BYTES constant could change in child classes) */
if (self::TIMESTAMP_BYTES > 0 && $length > self::TIMESTAMP_BYTES) {
- $hash = $this->randomGenerator->generate($length - self::TIMESTAMP_BYTES);
+ $hash = $this->generator->generate($length - self::TIMESTAMP_BYTES);
}
$lsbTime = str_pad(
- $this->converter->toHex($this->timestamp()),
+ $this->numberConverter->toHex($this->timestamp()),
self::TIMESTAMP_BYTES * 2,
'0',
- STR_PAD_LEFT
+ STR_PAD_LEFT,
);
- return (string) hex2bin(
- str_pad(
- bin2hex($hash),
- $length - self::TIMESTAMP_BYTES,
- '0'
- )
- . $lsbTime
- );
+ return (string) hex2bin(str_pad(bin2hex($hash), $length - self::TIMESTAMP_BYTES, '0') . $lsbTime);
}
/**
- * Returns current timestamp a string integer, precise to 0.00001 seconds
+ * Returns the current timestamp as a string integer, precise to 0.00001 seconds
*/
private function timestamp(): string
{
diff --git a/vendor/ramsey/uuid/src/Generator/DceSecurityGenerator.php b/vendor/ramsey/uuid/src/Generator/DceSecurityGenerator.php
index aca8c5d..71192c0 100644
--- a/vendor/ramsey/uuid/src/Generator/DceSecurityGenerator.php
+++ b/vendor/ramsey/uuid/src/Generator/DceSecurityGenerator.php
@@ -31,8 +31,8 @@ use function substr_replace;
use const STR_PAD_LEFT;
/**
- * DceSecurityGenerator generates strings of binary data based on a local
- * domain, local identifier, node ID, clock sequence, and the current time
+ * DceSecurityGenerator generates strings of binary data based on a local domain, local identifier, node ID, clock
+ * sequence, and the current time
*/
class DceSecurityGenerator implements DceSecurityGeneratorInterface
{
@@ -52,61 +52,37 @@ class DceSecurityGenerator implements DceSecurityGeneratorInterface
*/
private const CLOCK_SEQ_LOW = 0;
- /**
- * @var NumberConverterInterface
- */
- private $numberConverter;
-
- /**
- * @var TimeGeneratorInterface
- */
- private $timeGenerator;
-
- /**
- * @var DceSecurityProviderInterface
- */
- private $dceSecurityProvider;
-
public function __construct(
- NumberConverterInterface $numberConverter,
- TimeGeneratorInterface $timeGenerator,
- DceSecurityProviderInterface $dceSecurityProvider
+ private NumberConverterInterface $numberConverter,
+ private TimeGeneratorInterface $timeGenerator,
+ private DceSecurityProviderInterface $dceSecurityProvider,
) {
- $this->numberConverter = $numberConverter;
- $this->timeGenerator = $timeGenerator;
- $this->dceSecurityProvider = $dceSecurityProvider;
}
public function generate(
int $localDomain,
?IntegerObject $localIdentifier = null,
?Hexadecimal $node = null,
- ?int $clockSeq = null
+ ?int $clockSeq = null,
): string {
if (!in_array($localDomain, self::DOMAINS)) {
- throw new DceSecurityException(
- 'Local domain must be a valid DCE Security domain'
- );
+ throw new DceSecurityException('Local domain must be a valid DCE Security domain');
}
if ($localIdentifier && $localIdentifier->isNegative()) {
throw new DceSecurityException(
- 'Local identifier out of bounds; it must be a value between 0 and 4294967295'
+ 'Local identifier out of bounds; it must be a value between 0 and 4294967295',
);
}
if ($clockSeq > self::CLOCK_SEQ_HIGH || $clockSeq < self::CLOCK_SEQ_LOW) {
- throw new DceSecurityException(
- 'Clock sequence out of bounds; it must be a value between 0 and 63'
- );
+ throw new DceSecurityException('Clock sequence out of bounds; it must be a value between 0 and 63');
}
switch ($localDomain) {
case Uuid::DCE_DOMAIN_ORG:
if ($localIdentifier === null) {
- throw new DceSecurityException(
- 'A local identifier must be provided for the org domain'
- );
+ throw new DceSecurityException('A local identifier must be provided for the org domain');
}
break;
@@ -127,13 +103,11 @@ class DceSecurityGenerator implements DceSecurityGeneratorInterface
$identifierHex = $this->numberConverter->toHex($localIdentifier->toString());
- // The maximum value for the local identifier is 0xffffffff, or
- // 4294967295. This is 8 hexadecimal digits, so if the length of
- // hexadecimal digits is greater than 8, we know the value is greater
- // than 0xffffffff.
+ // The maximum value for the local identifier is 0xffffffff, or 4,294,967,295. This is 8 hexadecimal digits, so
+ // if the length of hexadecimal digits is greater than 8, we know the value is greater than 0xffffffff.
if (strlen($identifierHex) > 8) {
throw new DceSecurityException(
- 'Local identifier out of bounds; it must be a value between 0 and 4294967295'
+ 'Local identifier out of bounds; it must be a value between 0 and 4294967295',
);
}
@@ -153,8 +127,7 @@ class DceSecurityGenerator implements DceSecurityGeneratorInterface
// Replace bytes in the time-based UUID with DCE Security values.
$bytes = substr_replace($bytes, $identifierBytes, 0, 4);
- $bytes = substr_replace($bytes, $domainByte, 9, 1);
- return $bytes;
+ return substr_replace($bytes, $domainByte, 9, 1);
}
}
diff --git a/vendor/ramsey/uuid/src/Generator/DceSecurityGeneratorInterface.php b/vendor/ramsey/uuid/src/Generator/DceSecurityGeneratorInterface.php
index faa29a5..f52eb55 100644
--- a/vendor/ramsey/uuid/src/Generator/DceSecurityGeneratorInterface.php
+++ b/vendor/ramsey/uuid/src/Generator/DceSecurityGeneratorInterface.php
@@ -19,28 +19,23 @@ use Ramsey\Uuid\Type\Hexadecimal;
use Ramsey\Uuid\Type\Integer as IntegerObject;
/**
- * A DCE Security generator generates strings of binary data based on a local
- * domain, local identifier, node ID, clock sequence, and the current time
+ * A DCE Security generator generates strings of binary data based on a local domain, local identifier, node ID, clock
+ * sequence, and the current time
*
* @see UuidV2
*/
interface DceSecurityGeneratorInterface
{
/**
- * Generate a binary string from a local domain, local identifier, node ID,
- * clock sequence, and current time
+ * Generate a binary string from a local domain, local identifier, node ID, clock sequence, and current time
*
- * @param int $localDomain The local domain to use when generating bytes,
- * according to DCE Security
- * @param IntegerObject|null $localIdentifier The local identifier for the
- * given domain; this may be a UID or GID on POSIX systems, if the local
- * domain is person or group, or it may be a site-defined identifier
- * if the local domain is org
- * @param Hexadecimal|null $node A 48-bit number representing the hardware
- * address
- * @param int|null $clockSeq A 14-bit number used to help avoid duplicates
- * that could arise when the clock is set backwards in time or if the
- * node ID changes
+ * @param int $localDomain The local domain to use when generating bytes, according to DCE Security
+ * @param IntegerObject | null $localIdentifier The local identifier for the given domain; this may be a UID or GID
+ * on POSIX systems if the local domain is "person" or "group," or it may be a site-defined identifier if the
+ * local domain is "org"
+ * @param Hexadecimal | null $node A 48-bit number representing the hardware address
+ * @param int | null $clockSeq A 14-bit number used to help avoid duplicates that could arise when the clock is set
+ * backwards in time or if the node ID changes
*
* @return string A binary string
*/
@@ -48,6 +43,6 @@ interface DceSecurityGeneratorInterface
int $localDomain,
?IntegerObject $localIdentifier = null,
?Hexadecimal $node = null,
- ?int $clockSeq = null
+ ?int $clockSeq = null,
): string;
}
diff --git a/vendor/ramsey/uuid/src/Generator/DefaultNameGenerator.php b/vendor/ramsey/uuid/src/Generator/DefaultNameGenerator.php
index 7303e9f..cf37b45 100644
--- a/vendor/ramsey/uuid/src/Generator/DefaultNameGenerator.php
+++ b/vendor/ramsey/uuid/src/Generator/DefaultNameGenerator.php
@@ -21,28 +21,22 @@ use ValueError;
use function hash;
/**
- * DefaultNameGenerator generates strings of binary data based on a namespace,
- * name, and hashing algorithm
+ * DefaultNameGenerator generates strings of binary data based on a namespace, name, and hashing algorithm
*/
class DefaultNameGenerator implements NameGeneratorInterface
{
- /** @psalm-pure */
+ /**
+ * @pure
+ */
public function generate(UuidInterface $ns, string $name, string $hashAlgorithm): string
{
try {
- /** @var string|bool $bytes */
- $bytes = @hash($hashAlgorithm, $ns->getBytes() . $name, true);
+ return hash($hashAlgorithm, $ns->getBytes() . $name, true);
} catch (ValueError $e) {
- $bytes = false; // keep same behavior than PHP 7
+ throw new NameException(
+ message: sprintf('Unable to hash namespace and name with algorithm \'%s\'', $hashAlgorithm),
+ previous: $e,
+ );
}
-
- if ($bytes === false) {
- throw new NameException(sprintf(
- 'Unable to hash namespace and name with algorithm \'%s\'',
- $hashAlgorithm
- ));
- }
-
- return (string) $bytes;
}
}
diff --git a/vendor/ramsey/uuid/src/Generator/DefaultTimeGenerator.php b/vendor/ramsey/uuid/src/Generator/DefaultTimeGenerator.php
index d245c7b..6ded59d 100644
--- a/vendor/ramsey/uuid/src/Generator/DefaultTimeGenerator.php
+++ b/vendor/ramsey/uuid/src/Generator/DefaultTimeGenerator.php
@@ -23,11 +23,11 @@ use Ramsey\Uuid\Provider\TimeProviderInterface;
use Ramsey\Uuid\Type\Hexadecimal;
use Throwable;
-use function ctype_xdigit;
use function dechex;
use function hex2bin;
use function is_int;
use function pack;
+use function preg_match;
use function sprintf;
use function str_pad;
use function strlen;
@@ -35,34 +35,15 @@ use function strlen;
use const STR_PAD_LEFT;
/**
- * DefaultTimeGenerator generates strings of binary data based on a node ID,
- * clock sequence, and the current time
+ * DefaultTimeGenerator generates strings of binary data based on a node ID, clock sequence, and the current time
*/
class DefaultTimeGenerator implements TimeGeneratorInterface
{
- /**
- * @var NodeProviderInterface
- */
- private $nodeProvider;
-
- /**
- * @var TimeConverterInterface
- */
- private $timeConverter;
-
- /**
- * @var TimeProviderInterface
- */
- private $timeProvider;
-
public function __construct(
- NodeProviderInterface $nodeProvider,
- TimeConverterInterface $timeConverter,
- TimeProviderInterface $timeProvider
+ private NodeProviderInterface $nodeProvider,
+ private TimeConverterInterface $timeConverter,
+ private TimeProviderInterface $timeProvider,
) {
- $this->nodeProvider = $nodeProvider;
- $this->timeConverter = $timeConverter;
- $this->timeProvider = $timeProvider;
}
/**
@@ -81,14 +62,10 @@ class DefaultTimeGenerator implements TimeGeneratorInterface
if ($clockSeq === null) {
try {
- // This does not use "stable storage"; see RFC 4122, Section 4.2.1.1.
+ // This does not use "stable storage"; see RFC 9562, section 6.3.
$clockSeq = random_int(0, 0x3fff);
} catch (Throwable $exception) {
- throw new RandomSourceException(
- $exception->getMessage(),
- (int) $exception->getCode(),
- $exception
- );
+ throw new RandomSourceException($exception->getMessage(), (int) $exception->getCode(), $exception);
}
}
@@ -102,43 +79,37 @@ class DefaultTimeGenerator implements TimeGeneratorInterface
$timeHex = str_pad($uuidTime->toString(), 16, '0', STR_PAD_LEFT);
if (strlen($timeHex) !== 16) {
- throw new TimeSourceException(sprintf(
- 'The generated time of \'%s\' is larger than expected',
- $timeHex
- ));
+ throw new TimeSourceException(sprintf('The generated time of \'%s\' is larger than expected', $timeHex));
}
$timeBytes = (string) hex2bin($timeHex);
return $timeBytes[4] . $timeBytes[5] . $timeBytes[6] . $timeBytes[7]
- . $timeBytes[2] . $timeBytes[3]
- . $timeBytes[0] . $timeBytes[1]
- . pack('n*', $clockSeq)
- . $node;
+ . $timeBytes[2] . $timeBytes[3] . $timeBytes[0] . $timeBytes[1]
+ . pack('n*', $clockSeq) . $node;
}
/**
- * Uses the node provider given when constructing this instance to get
- * the node ID (usually a MAC address)
+ * Uses the node provider given when constructing this instance to get the node ID (usually a MAC address)
*
- * @param string|int|null $node A node value that may be used to override the node provider
+ * @param int | string | null $node A node value that may be used to override the node provider
*
* @return string 6-byte binary string representation of the node
*
* @throws InvalidArgumentException
*/
- private function getValidNode($node): string
+ private function getValidNode(int | string | null $node): string
{
if ($node === null) {
$node = $this->nodeProvider->getNode();
}
- // Convert the node to hex, if it is still an integer.
+ // Convert the node to hex if it is still an integer.
if (is_int($node)) {
$node = dechex($node);
}
- if (!ctype_xdigit((string) $node) || strlen((string) $node) > 12) {
+ if (!preg_match('/^[A-Fa-f0-9]+$/', (string) $node) || strlen((string) $node) > 12) {
throw new InvalidArgumentException('Invalid node value');
}
diff --git a/vendor/ramsey/uuid/src/Generator/NameGeneratorFactory.php b/vendor/ramsey/uuid/src/Generator/NameGeneratorFactory.php
index 6f08e29..d68e94b 100644
--- a/vendor/ramsey/uuid/src/Generator/NameGeneratorFactory.php
+++ b/vendor/ramsey/uuid/src/Generator/NameGeneratorFactory.php
@@ -15,8 +15,7 @@ declare(strict_types=1);
namespace Ramsey\Uuid\Generator;
/**
- * NameGeneratorFactory retrieves a default name generator, based on the
- * environment
+ * NameGeneratorFactory retrieves a default name generator, based on the environment
*/
class NameGeneratorFactory
{
diff --git a/vendor/ramsey/uuid/src/Generator/NameGeneratorInterface.php b/vendor/ramsey/uuid/src/Generator/NameGeneratorInterface.php
index cc43dd0..f0fb8da 100644
--- a/vendor/ramsey/uuid/src/Generator/NameGeneratorInterface.php
+++ b/vendor/ramsey/uuid/src/Generator/NameGeneratorInterface.php
@@ -17,14 +17,13 @@ namespace Ramsey\Uuid\Generator;
use Ramsey\Uuid\UuidInterface;
/**
- * A name generator generates strings of binary data created by hashing together
- * a namespace with a name, according to a hashing algorithm
+ * A name generator generates strings of binary data created by hashing together a namespace with a name, according to a
+ * hashing algorithm
*/
interface NameGeneratorInterface
{
/**
- * Generate a binary string from a namespace and name hashed together with
- * the specified hashing algorithm
+ * Generate a binary string from a namespace and name hashed together with the specified hashing algorithm
*
* @param UuidInterface $ns The namespace
* @param string $name The name to use for creating a UUID
@@ -32,7 +31,7 @@ interface NameGeneratorInterface
*
* @return string A binary string
*
- * @psalm-pure
+ * @pure
*/
public function generate(UuidInterface $ns, string $name, string $hashAlgorithm): string;
}
diff --git a/vendor/ramsey/uuid/src/Generator/PeclUuidNameGenerator.php b/vendor/ramsey/uuid/src/Generator/PeclUuidNameGenerator.php
index 3780c5c..d13bafc 100644
--- a/vendor/ramsey/uuid/src/Generator/PeclUuidNameGenerator.php
+++ b/vendor/ramsey/uuid/src/Generator/PeclUuidNameGenerator.php
@@ -23,32 +23,26 @@ use function uuid_generate_sha1;
use function uuid_parse;
/**
- * PeclUuidNameGenerator generates strings of binary data from a namespace and a
- * name, using ext-uuid
+ * PeclUuidNameGenerator generates strings of binary data from a namespace and a name, using ext-uuid
*
* @link https://pecl.php.net/package/uuid ext-uuid
*/
class PeclUuidNameGenerator implements NameGeneratorInterface
{
- /** @psalm-pure */
+ /**
+ * @pure
+ */
public function generate(UuidInterface $ns, string $name, string $hashAlgorithm): string
{
- switch ($hashAlgorithm) {
- case 'md5':
- $uuid = uuid_generate_md5($ns->toString(), $name);
+ $uuid = match ($hashAlgorithm) {
+ 'md5' => uuid_generate_md5($ns->toString(), $name), /** @phpstan-ignore possiblyImpure.functionCall */
+ 'sha1' => uuid_generate_sha1($ns->toString(), $name), /** @phpstan-ignore possiblyImpure.functionCall */
+ default => throw new NameException(
+ sprintf('Unable to hash namespace and name with algorithm \'%s\'', $hashAlgorithm),
+ ),
+ };
- break;
- case 'sha1':
- $uuid = uuid_generate_sha1($ns->toString(), $name);
-
- break;
- default:
- throw new NameException(sprintf(
- 'Unable to hash namespace and name with algorithm \'%s\'',
- $hashAlgorithm
- ));
- }
-
- return uuid_parse($uuid);
+ /** @phpstan-ignore possiblyImpure.functionCall */
+ return (string) uuid_parse($uuid);
}
}
diff --git a/vendor/ramsey/uuid/src/Generator/PeclUuidRandomGenerator.php b/vendor/ramsey/uuid/src/Generator/PeclUuidRandomGenerator.php
index 07c47d2..6ad45ac 100644
--- a/vendor/ramsey/uuid/src/Generator/PeclUuidRandomGenerator.php
+++ b/vendor/ramsey/uuid/src/Generator/PeclUuidRandomGenerator.php
@@ -30,6 +30,6 @@ class PeclUuidRandomGenerator implements RandomGeneratorInterface
{
$uuid = uuid_create(UUID_TYPE_RANDOM);
- return uuid_parse($uuid);
+ return (string) uuid_parse($uuid);
}
}
diff --git a/vendor/ramsey/uuid/src/Generator/PeclUuidTimeGenerator.php b/vendor/ramsey/uuid/src/Generator/PeclUuidTimeGenerator.php
index e01f44e..558abf7 100644
--- a/vendor/ramsey/uuid/src/Generator/PeclUuidTimeGenerator.php
+++ b/vendor/ramsey/uuid/src/Generator/PeclUuidTimeGenerator.php
@@ -20,8 +20,7 @@ use function uuid_parse;
use const UUID_TYPE_TIME;
/**
- * PeclUuidTimeGenerator generates strings of binary data for time-base UUIDs,
- * using ext-uuid
+ * PeclUuidTimeGenerator generates strings of binary data for time-base UUIDs, using ext-uuid
*
* @link https://pecl.php.net/package/uuid ext-uuid
*/
@@ -34,6 +33,6 @@ class PeclUuidTimeGenerator implements TimeGeneratorInterface
{
$uuid = uuid_create(UUID_TYPE_TIME);
- return uuid_parse($uuid);
+ return (string) uuid_parse($uuid);
}
}
diff --git a/vendor/ramsey/uuid/src/Generator/RandomBytesGenerator.php b/vendor/ramsey/uuid/src/Generator/RandomBytesGenerator.php
index 12edb96..c169e63 100644
--- a/vendor/ramsey/uuid/src/Generator/RandomBytesGenerator.php
+++ b/vendor/ramsey/uuid/src/Generator/RandomBytesGenerator.php
@@ -18,8 +18,7 @@ use Ramsey\Uuid\Exception\RandomSourceException;
use Throwable;
/**
- * RandomBytesGenerator generates strings of random binary data using the
- * built-in `random_bytes()` PHP function
+ * RandomBytesGenerator generates strings of random binary data using the built-in `random_bytes()` PHP function
*
* @link http://php.net/random_bytes random_bytes()
*/
@@ -35,11 +34,7 @@ class RandomBytesGenerator implements RandomGeneratorInterface
try {
return random_bytes($length);
} catch (Throwable $exception) {
- throw new RandomSourceException(
- $exception->getMessage(),
- (int) $exception->getCode(),
- $exception
- );
+ throw new RandomSourceException($exception->getMessage(), (int) $exception->getCode(), $exception);
}
}
}
diff --git a/vendor/ramsey/uuid/src/Generator/RandomGeneratorFactory.php b/vendor/ramsey/uuid/src/Generator/RandomGeneratorFactory.php
index b723ac2..f4c3a6f 100644
--- a/vendor/ramsey/uuid/src/Generator/RandomGeneratorFactory.php
+++ b/vendor/ramsey/uuid/src/Generator/RandomGeneratorFactory.php
@@ -15,8 +15,7 @@ declare(strict_types=1);
namespace Ramsey\Uuid\Generator;
/**
- * RandomGeneratorFactory retrieves a default random generator, based on the
- * environment
+ * RandomGeneratorFactory retrieves a default random generator, based on the environment
*/
class RandomGeneratorFactory
{
diff --git a/vendor/ramsey/uuid/src/Generator/RandomGeneratorInterface.php b/vendor/ramsey/uuid/src/Generator/RandomGeneratorInterface.php
index 5c83cb4..ddd8732 100644
--- a/vendor/ramsey/uuid/src/Generator/RandomGeneratorInterface.php
+++ b/vendor/ramsey/uuid/src/Generator/RandomGeneratorInterface.php
@@ -22,7 +22,7 @@ interface RandomGeneratorInterface
/**
* Generates a string of randomized binary data
*
- * @param int $length The number of bytes of random binary data to generate
+ * @param int<1, max> $length The number of bytes to generate of random binary data
*
* @return string A binary string
*/
diff --git a/vendor/ramsey/uuid/src/Generator/RandomLibAdapter.php b/vendor/ramsey/uuid/src/Generator/RandomLibAdapter.php
index 24ed569..b6d401d 100644
--- a/vendor/ramsey/uuid/src/Generator/RandomLibAdapter.php
+++ b/vendor/ramsey/uuid/src/Generator/RandomLibAdapter.php
@@ -18,25 +18,24 @@ use RandomLib\Factory;
use RandomLib\Generator;
/**
- * RandomLibAdapter generates strings of random binary data using the
- * paragonie/random-lib library
+ * RandomLibAdapter generates strings of random binary data using the paragonie/random-lib library
+ *
+ * @deprecated This class will be removed in 5.0.0. Use the default RandomBytesGenerator or implement your own generator
+ * that implements RandomGeneratorInterface.
*
* @link https://packagist.org/packages/paragonie/random-lib paragonie/random-lib
*/
class RandomLibAdapter implements RandomGeneratorInterface
{
- /**
- * @var Generator
- */
- private $generator;
+ private Generator $generator;
/**
* Constructs a RandomLibAdapter
*
- * By default, if no Generator is passed in, this creates a high-strength
- * generator to use when generating random binary data.
+ * By default, if no Generator is passed in, this creates a high-strength generator to use when generating random
+ * binary data.
*
- * @param Generator|null $generator The generator to use when generating binary data
+ * @param Generator | null $generator The generator to use when generating binary data
*/
public function __construct(?Generator $generator = null)
{
diff --git a/vendor/ramsey/uuid/src/Generator/TimeGeneratorFactory.php b/vendor/ramsey/uuid/src/Generator/TimeGeneratorFactory.php
index 3d55fc4..433e74c 100644
--- a/vendor/ramsey/uuid/src/Generator/TimeGeneratorFactory.php
+++ b/vendor/ramsey/uuid/src/Generator/TimeGeneratorFactory.php
@@ -19,34 +19,15 @@ use Ramsey\Uuid\Provider\NodeProviderInterface;
use Ramsey\Uuid\Provider\TimeProviderInterface;
/**
- * TimeGeneratorFactory retrieves a default time generator, based on the
- * environment
+ * TimeGeneratorFactory retrieves a default time generator, based on the environment
*/
class TimeGeneratorFactory
{
- /**
- * @var NodeProviderInterface
- */
- private $nodeProvider;
-
- /**
- * @var TimeConverterInterface
- */
- private $timeConverter;
-
- /**
- * @var TimeProviderInterface
- */
- private $timeProvider;
-
public function __construct(
- NodeProviderInterface $nodeProvider,
- TimeConverterInterface $timeConverter,
- TimeProviderInterface $timeProvider
+ private NodeProviderInterface $nodeProvider,
+ private TimeConverterInterface $timeConverter,
+ private TimeProviderInterface $timeProvider,
) {
- $this->nodeProvider = $nodeProvider;
- $this->timeConverter = $timeConverter;
- $this->timeProvider = $timeProvider;
}
/**
@@ -54,10 +35,6 @@ class TimeGeneratorFactory
*/
public function getGenerator(): TimeGeneratorInterface
{
- return new DefaultTimeGenerator(
- $this->nodeProvider,
- $this->timeConverter,
- $this->timeProvider
- );
+ return new DefaultTimeGenerator($this->nodeProvider, $this->timeConverter, $this->timeProvider);
}
}
diff --git a/vendor/ramsey/uuid/src/Generator/TimeGeneratorInterface.php b/vendor/ramsey/uuid/src/Generator/TimeGeneratorInterface.php
index 18f21c4..c15d820 100644
--- a/vendor/ramsey/uuid/src/Generator/TimeGeneratorInterface.php
+++ b/vendor/ramsey/uuid/src/Generator/TimeGeneratorInterface.php
@@ -17,20 +17,17 @@ namespace Ramsey\Uuid\Generator;
use Ramsey\Uuid\Type\Hexadecimal;
/**
- * A time generator generates strings of binary data based on a node ID,
- * clock sequence, and the current time
+ * A time generator generates strings of binary data based on a node ID, clock sequence, and the current time
*/
interface TimeGeneratorInterface
{
/**
* Generate a binary string from a node ID, clock sequence, and current time
*
- * @param Hexadecimal|int|string|null $node A 48-bit number representing the
- * hardware address; this number may be represented as an integer or a
- * hexadecimal string
- * @param int|null $clockSeq A 14-bit number used to help avoid duplicates
- * that could arise when the clock is set backwards in time or if the
- * node ID changes
+ * @param Hexadecimal | int | string | null $node A 48-bit number representing the hardware address; this number may
+ * be represented as an integer or a hexadecimal string
+ * @param int | null $clockSeq A 14-bit number used to help avoid duplicates that could arise when the clock is set
+ * backwards in time or if the node ID changes
*
* @return string A binary string
*/
diff --git a/vendor/ramsey/uuid/src/Generator/UnixTimeGenerator.php b/vendor/ramsey/uuid/src/Generator/UnixTimeGenerator.php
new file mode 100644
index 0000000..a2615f1
--- /dev/null
+++ b/vendor/ramsey/uuid/src/Generator/UnixTimeGenerator.php
@@ -0,0 +1,165 @@
+
+ * @license http://opensource.org/licenses/MIT MIT
+ */
+
+declare(strict_types=1);
+
+namespace Ramsey\Uuid\Generator;
+
+use Brick\Math\BigInteger;
+use DateTimeInterface;
+use Ramsey\Uuid\Type\Hexadecimal;
+
+use function assert;
+use function hash;
+use function pack;
+use function str_pad;
+use function strlen;
+use function substr;
+use function substr_replace;
+use function unpack;
+
+use const PHP_INT_SIZE;
+use const STR_PAD_LEFT;
+
+/**
+ * UnixTimeGenerator generates bytes, combining a 48-bit timestamp in milliseconds since the Unix Epoch with 80 random bits
+ *
+ * Code and concepts within this class are borrowed from the symfony/uid package and are used under the terms of the MIT
+ * license distributed with symfony/uid.
+ *
+ * symfony/uid is copyright (c) Fabien Potencier.
+ *
+ * @link https://symfony.com/components/Uid Symfony Uid component
+ * @link https://github.com/symfony/uid/blob/4f9f537e57261519808a7ce1d941490736522bbc/UuidV7.php Symfony UuidV7 class
+ * @link https://github.com/symfony/uid/blob/6.2/LICENSE MIT License
+ */
+class UnixTimeGenerator implements TimeGeneratorInterface
+{
+ private static string $time = '';
+ private static ?string $seed = null;
+ private static int $seedIndex = 0;
+
+ /** @var int[] */
+ private static array $rand = [];
+
+ /** @var int[] */
+ private static array $seedParts;
+
+ public function __construct(
+ private RandomGeneratorInterface $randomGenerator,
+ private int $intSize = PHP_INT_SIZE,
+ ) {
+ }
+
+ /**
+ * @param Hexadecimal | int | string | null $node Unused in this generator
+ * @param int | null $clockSeq Unused in this generator
+ * @param DateTimeInterface | null $dateTime A date-time instance to use when generating bytes
+ */
+ public function generate($node = null, ?int $clockSeq = null, ?DateTimeInterface $dateTime = null): string
+ {
+ if ($dateTime === null) {
+ $time = microtime(false);
+ $time = substr($time, 11) . substr($time, 2, 3);
+ } else {
+ $time = $dateTime->format('Uv');
+ }
+
+ if ($time > self::$time || ($dateTime !== null && $time !== self::$time)) {
+ $this->randomize($time);
+ } else {
+ $time = $this->increment();
+ }
+
+ if ($this->intSize >= 8) {
+ $time = substr(pack('J', (int) $time), -6);
+ } else {
+ $time = str_pad(BigInteger::of($time)->toBytes(false), 6, "\x00", STR_PAD_LEFT);
+ }
+
+ assert(strlen($time) === 6);
+
+ return $time . pack('n*', self::$rand[1], self::$rand[2], self::$rand[3], self::$rand[4], self::$rand[5]);
+ }
+
+ private function randomize(string $time): void
+ {
+ if (self::$seed === null) {
+ $seed = $this->randomGenerator->generate(16);
+ self::$seed = $seed;
+ } else {
+ $seed = $this->randomGenerator->generate(10);
+ }
+
+ /** @var int[] $rand */
+ $rand = unpack('n*', $seed);
+ $rand[1] &= 0x03ff;
+
+ self::$rand = $rand;
+ self::$time = $time;
+ }
+
+ /**
+ * Special thanks to Nicolas Grekas () for sharing the following information:
+ *
+ * Within the same ms, we increment the rand part by a random 24-bit number.
+ *
+ * Instead of getting this number from random_bytes(), which is slow, we get it by sha512-hashing self::$seed. This
+ * produces 64 bytes of entropy, which we need to split in a list of 24-bit numbers. `unpack()` first splits them
+ * into 16 x 32-bit numbers; we take the first byte of each number to get 5 extra 24-bit numbers. Then, we consume
+ * each number one-by-one and run this logic every 21 iterations.
+ *
+ * `self::$rand` holds the random part of the UUID, split into 5 x 16-bit numbers for x86 portability. We increment
+ * this random part by the next 24-bit number in the `self::$seedParts` list and decrement `self::$seedIndex`.
+ */
+ private function increment(): string
+ {
+ if (self::$seedIndex === 0 && self::$seed !== null) {
+ self::$seed = hash('sha512', self::$seed, true);
+
+ /** @var int[] $s */
+ $s = unpack('l*', self::$seed);
+ $s[] = ($s[1] >> 8 & 0xff0000) | ($s[2] >> 16 & 0xff00) | ($s[3] >> 24 & 0xff);
+ $s[] = ($s[4] >> 8 & 0xff0000) | ($s[5] >> 16 & 0xff00) | ($s[6] >> 24 & 0xff);
+ $s[] = ($s[7] >> 8 & 0xff0000) | ($s[8] >> 16 & 0xff00) | ($s[9] >> 24 & 0xff);
+ $s[] = ($s[10] >> 8 & 0xff0000) | ($s[11] >> 16 & 0xff00) | ($s[12] >> 24 & 0xff);
+ $s[] = ($s[13] >> 8 & 0xff0000) | ($s[14] >> 16 & 0xff00) | ($s[15] >> 24 & 0xff);
+
+ self::$seedParts = $s;
+ self::$seedIndex = 21;
+ }
+
+ self::$rand[5] = 0xffff & $carry = self::$rand[5] + 1 + (self::$seedParts[self::$seedIndex--] & 0xffffff);
+ self::$rand[4] = 0xffff & $carry = self::$rand[4] + ($carry >> 16);
+ self::$rand[3] = 0xffff & $carry = self::$rand[3] + ($carry >> 16);
+ self::$rand[2] = 0xffff & $carry = self::$rand[2] + ($carry >> 16);
+ self::$rand[1] += $carry >> 16;
+
+ if (0xfc00 & self::$rand[1]) {
+ $time = self::$time;
+ $mtime = (int) substr($time, -9);
+
+ if ($this->intSize >= 8 || strlen($time) < 10) {
+ $time = (string) ((int) $time + 1);
+ } elseif ($mtime === 999999999) {
+ $time = (1 + (int) substr($time, 0, -9)) . '000000000';
+ } else {
+ $mtime++;
+ $time = substr_replace($time, str_pad((string) $mtime, 9, '0', STR_PAD_LEFT), -9);
+ }
+
+ $this->randomize($time);
+ }
+
+ return self::$time;
+ }
+}
diff --git a/vendor/ramsey/uuid/src/Guid/Fields.php b/vendor/ramsey/uuid/src/Guid/Fields.php
index d8a1a2b..58aa5e1 100644
--- a/vendor/ramsey/uuid/src/Guid/Fields.php
+++ b/vendor/ramsey/uuid/src/Guid/Fields.php
@@ -17,6 +17,7 @@ namespace Ramsey\Uuid\Guid;
use Ramsey\Uuid\Exception\InvalidArgumentException;
use Ramsey\Uuid\Fields\SerializableFieldsTrait;
use Ramsey\Uuid\Rfc4122\FieldsInterface;
+use Ramsey\Uuid\Rfc4122\MaxTrait;
use Ramsey\Uuid\Rfc4122\NilTrait;
use Ramsey\Uuid\Rfc4122\VariantTrait;
use Ramsey\Uuid\Rfc4122\VersionTrait;
@@ -36,24 +37,20 @@ use function unpack;
use const STR_PAD_LEFT;
/**
- * GUIDs are comprised of a set of named fields, according to RFC 4122
+ * GUIDs consist of a set of named fields, according to RFC 9562 (formerly RFC 4122)
*
* @see Guid
*
- * @psalm-immutable
+ * @immutable
*/
final class Fields implements FieldsInterface
{
+ use MaxTrait;
use NilTrait;
use SerializableFieldsTrait;
use VariantTrait;
use VersionTrait;
- /**
- * @var string
- */
- private $bytes;
-
/**
* @param string $bytes A 16-byte binary string representation of a UUID
*
@@ -61,28 +58,23 @@ final class Fields implements FieldsInterface
* @throws InvalidArgumentException if the byte string does not represent a GUID
* @throws InvalidArgumentException if the byte string does not contain a valid version
*/
- public function __construct(string $bytes)
+ public function __construct(private string $bytes)
{
- if (strlen($bytes) !== 16) {
+ if (strlen($this->bytes) !== 16) {
throw new InvalidArgumentException(
- 'The byte string must be 16 bytes long; '
- . 'received ' . strlen($bytes) . ' bytes'
+ 'The byte string must be 16 bytes long; received ' . strlen($this->bytes) . ' bytes',
);
}
- $this->bytes = $bytes;
-
if (!$this->isCorrectVariant()) {
throw new InvalidArgumentException(
- 'The byte string received does not conform to the RFC '
- . '4122 or Microsoft Corporation variants'
+ 'The byte string received does not conform to the RFC 9562 (formerly RFC 4122) '
+ . 'or Microsoft Corporation variants',
);
}
if (!$this->isCorrectVersion()) {
- throw new InvalidArgumentException(
- 'The byte string received does not contain a valid version'
- );
+ throw new InvalidArgumentException('The byte string received does not contain a valid version');
}
}
@@ -94,47 +86,35 @@ final class Fields implements FieldsInterface
public function getTimeLow(): Hexadecimal
{
// Swap the bytes from little endian to network byte order.
- /** @var array $hex */
+ /** @var string[] $hex */
$hex = unpack(
'H*',
pack(
'v*',
hexdec(bin2hex(substr($this->bytes, 2, 2))),
- hexdec(bin2hex(substr($this->bytes, 0, 2)))
- )
+ hexdec(bin2hex(substr($this->bytes, 0, 2))),
+ ),
);
- return new Hexadecimal((string) ($hex[1] ?? ''));
+ return new Hexadecimal($hex[1] ?? '');
}
public function getTimeMid(): Hexadecimal
{
// Swap the bytes from little endian to network byte order.
- /** @var array $hex */
- $hex = unpack(
- 'H*',
- pack(
- 'v',
- hexdec(bin2hex(substr($this->bytes, 4, 2)))
- )
- );
+ /** @var string[] $hex */
+ $hex = unpack('H*', pack('v', hexdec(bin2hex(substr($this->bytes, 4, 2)))));
- return new Hexadecimal((string) ($hex[1] ?? ''));
+ return new Hexadecimal($hex[1] ?? '');
}
public function getTimeHiAndVersion(): Hexadecimal
{
// Swap the bytes from little endian to network byte order.
- /** @var array $hex */
- $hex = unpack(
- 'H*',
- pack(
- 'v',
- hexdec(bin2hex(substr($this->bytes, 6, 2)))
- )
- );
+ /** @var string[] $hex */
+ $hex = unpack('H*', pack('v', hexdec(bin2hex(substr($this->bytes, 6, 2)))));
- return new Hexadecimal((string) ($hex[1] ?? ''));
+ return new Hexadecimal($hex[1] ?? '');
}
public function getTimestamp(): Hexadecimal
@@ -149,7 +129,13 @@ final class Fields implements FieldsInterface
public function getClockSeq(): Hexadecimal
{
- $clockSeq = hexdec(bin2hex(substr($this->bytes, 8, 2))) & 0x3fff;
+ if ($this->isMax()) {
+ $clockSeq = 0xffff;
+ } elseif ($this->isNil()) {
+ $clockSeq = 0x0000;
+ } else {
+ $clockSeq = hexdec(bin2hex(substr($this->bytes, 8, 2))) & 0x3fff;
+ }
return new Hexadecimal(str_pad(dechex($clockSeq), 4, '0', STR_PAD_LEFT));
}
@@ -171,19 +157,19 @@ final class Fields implements FieldsInterface
public function getVersion(): ?int
{
- if ($this->isNil()) {
+ if ($this->isNil() || $this->isMax()) {
return null;
}
- /** @var array $parts */
+ /** @var int[] $parts */
$parts = unpack('n*', $this->bytes);
- return ((int) $parts[4] >> 4) & 0x00f;
+ return ($parts[4] >> 4) & 0x00f;
}
private function isCorrectVariant(): bool
{
- if ($this->isNil()) {
+ if ($this->isNil() || $this->isMax()) {
return true;
}
diff --git a/vendor/ramsey/uuid/src/Guid/Guid.php b/vendor/ramsey/uuid/src/Guid/Guid.php
index b3ed096..af551cf 100644
--- a/vendor/ramsey/uuid/src/Guid/Guid.php
+++ b/vendor/ramsey/uuid/src/Guid/Guid.php
@@ -24,29 +24,25 @@ use Ramsey\Uuid\Uuid;
*
* From Wikipedia:
*
- * > The first three fields are unsigned 32- and 16-bit integers and are subject
- * > to swapping, while the last two fields consist of uninterpreted bytes, not
- * > subject to swapping. This byte swapping applies even for versions 3, 4, and
- * > 5, where the canonical fields do not correspond to the content of the UUID.
+ * > The first three fields are unsigned 32- and 16-bit integers and are subject to swapping, while the last two fields
+ * > consist of uninterpreted bytes, not subject to swapping. This byte swapping applies even for versions 3, 4, and 5,
+ * > where the canonical fields do not correspond to the content of the UUID.
*
- * The first three fields of a GUID are encoded in little-endian byte order,
- * while the last three fields are in network (big-endian) byte order. This is
- * according to the history of the Microsoft definition of a GUID.
+ * The first three fields of a GUID are encoded in little-endian byte order, while the last three fields are in network
+ * (big-endian) byte order. This is according to the history of the Microsoft GUID definition.
*
* According to the .NET Guid.ToByteArray method documentation:
*
- * > Note that the order of bytes in the returned byte array is different from
- * > the string representation of a Guid value. The order of the beginning
- * > four-byte group and the next two two-byte groups is reversed, whereas the
- * > order of the last two-byte group and the closing six-byte group is the
- * > same.
+ * > Note that the order of bytes in the returned byte array is different from the string representation of a Guid value.
+ * > The order of the beginning four-byte group and the next two two-byte groups is reversed, whereas the order of the
+ * > last two-byte group and the closing six-byte group is the same.
*
* @link https://en.wikipedia.org/wiki/Universally_unique_identifier#Variants UUID Variants on Wikipedia
* @link https://docs.microsoft.com/en-us/windows/win32/api/guiddef/ns-guiddef-guid Windows GUID structure
* @link https://docs.microsoft.com/en-us/dotnet/api/system.guid .NET Guid Struct
* @link https://docs.microsoft.com/en-us/dotnet/api/system.guid.tobytearray .NET Guid.ToByteArray Method
*
- * @psalm-immutable
+ * @immutable
*/
final class Guid extends Uuid
{
@@ -54,7 +50,7 @@ final class Guid extends Uuid
Fields $fields,
NumberConverterInterface $numberConverter,
CodecInterface $codec,
- TimeConverterInterface $timeConverter
+ TimeConverterInterface $timeConverter,
) {
parent::__construct($fields, $numberConverter, $codec, $timeConverter);
}
diff --git a/vendor/ramsey/uuid/src/Guid/GuidBuilder.php b/vendor/ramsey/uuid/src/Guid/GuidBuilder.php
index 758dd6b..db743d9 100644
--- a/vendor/ramsey/uuid/src/Guid/GuidBuilder.php
+++ b/vendor/ramsey/uuid/src/Guid/GuidBuilder.php
@@ -27,32 +27,19 @@ use Throwable;
*
* @see Guid
*
- * @psalm-immutable
+ * @immutable
*/
class GuidBuilder implements UuidBuilderInterface
{
/**
- * @var NumberConverterInterface
- */
- private $numberConverter;
-
- /**
- * @var TimeConverterInterface
- */
- private $timeConverter;
-
- /**
- * @param NumberConverterInterface $numberConverter The number converter to
- * use when constructing the Guid
- * @param TimeConverterInterface $timeConverter The time converter to use
- * for converting timestamps extracted from a UUID to Unix timestamps
+ * @param NumberConverterInterface $numberConverter The number converter to use when constructing the Guid
+ * @param TimeConverterInterface $timeConverter The time converter to use for converting timestamps extracted from a
+ * UUID to Unix timestamps
*/
public function __construct(
- NumberConverterInterface $numberConverter,
- TimeConverterInterface $timeConverter
+ private NumberConverterInterface $numberConverter,
+ private TimeConverterInterface $timeConverter,
) {
- $this->numberConverter = $numberConverter;
- $this->timeConverter = $timeConverter;
}
/**
@@ -63,27 +50,27 @@ class GuidBuilder implements UuidBuilderInterface
*
* @return Guid The GuidBuilder returns an instance of Ramsey\Uuid\Guid\Guid
*
- * @psalm-pure
+ * @pure
*/
public function build(CodecInterface $codec, string $bytes): UuidInterface
{
try {
- return new Guid(
- $this->buildFields($bytes),
- $this->numberConverter,
- $codec,
- $this->timeConverter
- );
+ /** @phpstan-ignore possiblyImpure.new */
+ return new Guid($this->buildFields($bytes), $this->numberConverter, $codec, $this->timeConverter);
} catch (Throwable $e) {
+ /** @phpstan-ignore possiblyImpure.methodCall, possiblyImpure.methodCall */
throw new UnableToBuildUuidException($e->getMessage(), (int) $e->getCode(), $e);
}
}
/**
- * Proxy method to allow injecting a mock, for testing
+ * Proxy method to allow injecting a mock for testing
+ *
+ * @pure
*/
protected function buildFields(string $bytes): Fields
{
+ /** @phpstan-ignore possiblyImpure.new */
return new Fields($bytes);
}
}
diff --git a/vendor/ramsey/uuid/src/Lazy/LazyUuidFromString.php b/vendor/ramsey/uuid/src/Lazy/LazyUuidFromString.php
index 8ba7579..8d3129c 100644
--- a/vendor/ramsey/uuid/src/Lazy/LazyUuidFromString.php
+++ b/vendor/ramsey/uuid/src/Lazy/LazyUuidFromString.php
@@ -18,8 +18,8 @@ use DateTimeInterface;
use Ramsey\Uuid\Converter\NumberConverterInterface;
use Ramsey\Uuid\Exception\UnsupportedOperationException;
use Ramsey\Uuid\Fields\FieldsInterface;
-use Ramsey\Uuid\Nonstandard\UuidV6;
use Ramsey\Uuid\Rfc4122\UuidV1;
+use Ramsey\Uuid\Rfc4122\UuidV6;
use Ramsey\Uuid\Type\Hexadecimal;
use Ramsey\Uuid\Type\Integer as IntegerObject;
use Ramsey\Uuid\UuidFactory;
@@ -35,41 +35,32 @@ use function substr;
/**
* Lazy version of a UUID: its format has not been determined yet, so it is mostly only usable for string/bytes
- * conversion. This object optimizes instantiation, serialization and string conversion time, at the cost of
- * increased overhead for more advanced UUID operations.
+ * conversion. This object optimizes instantiation, serialization and string conversion time, at the cost of increased
+ * overhead for more advanced UUID operations.
*
- * @internal this type is used internally for performance reasons, and is not supposed to be directly referenced
- * in consumer libraries.
+ * > [!NOTE]
+ * > The {@see FieldsInterface} does not declare methods that deprecated API relies upon: the API has been ported from
+ * > the {@see \Ramsey\Uuid\Uuid} definition, and is deprecated anyway.
*
- * @psalm-immutable
+ * > [!NOTE]
+ * > The deprecated API from {@see \Ramsey\Uuid\Uuid} is in use here (on purpose): it will be removed once the
+ * > deprecated API is gone from this class too.
*
- * Note: the {@see FieldsInterface} does not declare methods that deprecated API
- * relies upon: the API has been ported from the {@see \Ramsey\Uuid\Uuid} definition,
- * and is deprecated anyway.
- * Note: the deprecated API from {@see \Ramsey\Uuid\Uuid} is in use here (on purpose): it will be removed
- * once the deprecated API is gone from this class too.
- *
- * @psalm-suppress UndefinedInterfaceMethod
- * @psalm-suppress DeprecatedMethod
+ * @internal this type is used internally for performance reasons and is not supposed to be directly referenced in consumer libraries.
*/
final class LazyUuidFromString implements UuidInterface
{
public const VALID_REGEX = '/\A[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\z/ms';
- /**
- * @var string
- * @psalm-var non-empty-string
- */
- private $uuid;
- /** @var UuidInterface|null */
- private $unwrapped;
- /** @psalm-param non-empty-string $uuid */
- public function __construct(string $uuid)
+ private ?UuidInterface $unwrapped = null;
+
+ /**
+ * @param non-empty-string $uuid
+ */
+ public function __construct(private string $uuid)
{
- $this->uuid = $uuid;
}
- /** @psalm-pure */
public static function fromBytes(string $bytes): self
{
$base16Uuid = bin2hex($bytes);
@@ -93,9 +84,7 @@ final class LazyUuidFromString implements UuidInterface
}
/**
- * @return array{string: string}
- *
- * @psalm-return array{string: non-empty-string}
+ * @return array{string: non-empty-string}
*/
public function __serialize(): array
{
@@ -105,19 +94,15 @@ final class LazyUuidFromString implements UuidInterface
/**
* {@inheritDoc}
*
- * @param string $serialized
- *
- * @psalm-param non-empty-string $serialized
+ * @param non-empty-string $data
*/
- public function unserialize($serialized): void
+ public function unserialize(string $data): void
{
- $this->uuid = $serialized;
+ $this->uuid = $data;
}
/**
- * @param array{string: string} $data
- *
- * @psalm-param array{string: non-empty-string} $data
+ * @param array{string?: non-empty-string} $data
*/
public function __unserialize(array $data): void
{
@@ -130,166 +115,125 @@ final class LazyUuidFromString implements UuidInterface
$this->unserialize($data['string']);
}
- /** @psalm-suppress DeprecatedMethod */
public function getNumberConverter(): NumberConverterInterface
{
- return ($this->unwrapped ?? $this->unwrap())
- ->getNumberConverter();
+ return ($this->unwrapped ?? $this->unwrap())->getNumberConverter();
}
/**
- * {@inheritDoc}
- *
- * @psalm-suppress DeprecatedMethod
+ * @inheritDoc
*/
public function getFieldsHex(): array
{
- return ($this->unwrapped ?? $this->unwrap())
- ->getFieldsHex();
+ return ($this->unwrapped ?? $this->unwrap())->getFieldsHex();
}
- /** @psalm-suppress DeprecatedMethod */
public function getClockSeqHiAndReservedHex(): string
{
- return ($this->unwrapped ?? $this->unwrap())
- ->getClockSeqHiAndReservedHex();
+ return ($this->unwrapped ?? $this->unwrap())->getClockSeqHiAndReservedHex();
}
- /** @psalm-suppress DeprecatedMethod */
public function getClockSeqLowHex(): string
{
- return ($this->unwrapped ?? $this->unwrap())
- ->getClockSeqLowHex();
+ return ($this->unwrapped ?? $this->unwrap())->getClockSeqLowHex();
}
- /** @psalm-suppress DeprecatedMethod */
public function getClockSequenceHex(): string
{
- return ($this->unwrapped ?? $this->unwrap())
- ->getClockSequenceHex();
+ return ($this->unwrapped ?? $this->unwrap())->getClockSequenceHex();
}
- /** @psalm-suppress DeprecatedMethod */
public function getDateTime(): DateTimeInterface
{
- return ($this->unwrapped ?? $this->unwrap())
- ->getDateTime();
+ return ($this->unwrapped ?? $this->unwrap())->getDateTime();
}
- /** @psalm-suppress DeprecatedMethod */
public function getLeastSignificantBitsHex(): string
{
- return ($this->unwrapped ?? $this->unwrap())
- ->getLeastSignificantBitsHex();
+ return ($this->unwrapped ?? $this->unwrap())->getLeastSignificantBitsHex();
}
- /** @psalm-suppress DeprecatedMethod */
public function getMostSignificantBitsHex(): string
{
- return ($this->unwrapped ?? $this->unwrap())
- ->getMostSignificantBitsHex();
+ return ($this->unwrapped ?? $this->unwrap())->getMostSignificantBitsHex();
}
- /** @psalm-suppress DeprecatedMethod */
public function getNodeHex(): string
{
- return ($this->unwrapped ?? $this->unwrap())
- ->getNodeHex();
+ return ($this->unwrapped ?? $this->unwrap())->getNodeHex();
}
- /** @psalm-suppress DeprecatedMethod */
public function getTimeHiAndVersionHex(): string
{
- return ($this->unwrapped ?? $this->unwrap())
- ->getTimeHiAndVersionHex();
+ return ($this->unwrapped ?? $this->unwrap())->getTimeHiAndVersionHex();
}
- /** @psalm-suppress DeprecatedMethod */
public function getTimeLowHex(): string
{
- return ($this->unwrapped ?? $this->unwrap())
- ->getTimeLowHex();
+ return ($this->unwrapped ?? $this->unwrap())->getTimeLowHex();
}
- /** @psalm-suppress DeprecatedMethod */
public function getTimeMidHex(): string
{
- return ($this->unwrapped ?? $this->unwrap())
- ->getTimeMidHex();
+ return ($this->unwrapped ?? $this->unwrap())->getTimeMidHex();
}
- /** @psalm-suppress DeprecatedMethod */
public function getTimestampHex(): string
{
- return ($this->unwrapped ?? $this->unwrap())
- ->getTimestampHex();
+ return ($this->unwrapped ?? $this->unwrap())->getTimestampHex();
}
- /** @psalm-suppress DeprecatedMethod */
public function getUrn(): string
{
- return ($this->unwrapped ?? $this->unwrap())
- ->getUrn();
+ return ($this->unwrapped ?? $this->unwrap())->getUrn();
}
- /** @psalm-suppress DeprecatedMethod */
public function getVariant(): ?int
{
- return ($this->unwrapped ?? $this->unwrap())
- ->getVariant();
+ return ($this->unwrapped ?? $this->unwrap())->getVariant();
}
- /** @psalm-suppress DeprecatedMethod */
public function getVersion(): ?int
{
- return ($this->unwrapped ?? $this->unwrap())
- ->getVersion();
+ return ($this->unwrapped ?? $this->unwrap())->getVersion();
}
public function compareTo(UuidInterface $other): int
{
- return ($this->unwrapped ?? $this->unwrap())
- ->compareTo($other);
+ return ($this->unwrapped ?? $this->unwrap())->compareTo($other);
}
public function equals(?object $other): bool
{
- if (! $other instanceof UuidInterface) {
+ if (!$other instanceof UuidInterface) {
return false;
}
return $this->uuid === $other->toString();
}
- /**
- * {@inheritDoc}
- *
- * @psalm-suppress MoreSpecificReturnType
- * @psalm-suppress LessSpecificReturnStatement we know that {@see self::$uuid} is a non-empty string, so
- * we know that {@see hex2bin} will retrieve a non-empty string too.
- */
public function getBytes(): string
{
- /** @phpstan-ignore-next-line PHPStan complains that this is not a non-empty-string. */
+ /**
+ * @var non-empty-string
+ * @phpstan-ignore possiblyImpure.functionCall, possiblyImpure.functionCall
+ */
return (string) hex2bin(str_replace('-', '', $this->uuid));
}
public function getFields(): FieldsInterface
{
- return ($this->unwrapped ?? $this->unwrap())
- ->getFields();
+ return ($this->unwrapped ?? $this->unwrap())->getFields();
}
public function getHex(): Hexadecimal
{
- return ($this->unwrapped ?? $this->unwrap())
- ->getHex();
+ return ($this->unwrapped ?? $this->unwrap())->getHex();
}
public function getInteger(): IntegerObject
{
- return ($this->unwrapped ?? $this->unwrap())
- ->getInteger();
+ return ($this->unwrapped ?? $this->unwrap())->getInteger();
}
public function toString(): string
@@ -308,232 +252,149 @@ final class LazyUuidFromString implements UuidInterface
}
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
- * instance, you may call {@see Rfc4122FieldsInterface::getClockSeqHiAndReserved()}
- * and use the arbitrary-precision math library of your choice to
- * convert it to a string integer.
- *
- * @psalm-suppress UndefinedInterfaceMethod
- * @psalm-suppress DeprecatedMethod
- * @psalm-suppress MixedArgument
- * @psalm-suppress MixedMethodCall
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see FieldsInterface} instance. If it is a
+ * {@see Rfc4122FieldsInterface} instance, you may call {@see Rfc4122FieldsInterface::getClockSeqHiAndReserved()}
+ * and use the arbitrary-precision math library of your choice to convert it to a string integer.
*/
public function getClockSeqHiAndReserved(): string
{
$instance = ($this->unwrapped ?? $this->unwrap());
- return $instance->getNumberConverter()
- ->fromHex(
- $instance->getFields()
- ->getClockSeqHiAndReserved()
- ->toString()
- );
+ $fields = $instance->getFields();
+ assert($fields instanceof \Ramsey\Uuid\Rfc4122\FieldsInterface);
+
+ return $instance->getNumberConverter()->fromHex($fields->getClockSeqHiAndReserved()->toString());
}
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
- * instance, you may call {@see Rfc4122FieldsInterface::getClockSeqLow()}
- * and use the arbitrary-precision math library of your choice to
- * convert it to a string integer.
- *
- * @psalm-suppress UndefinedInterfaceMethod
- * @psalm-suppress DeprecatedMethod
- * @psalm-suppress MixedArgument
- * @psalm-suppress MixedMethodCall
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see FieldsInterface} instance. If it is a
+ * {@see Rfc4122FieldsInterface} instance, you may call {@see Rfc4122FieldsInterface::getClockSeqLow()} and use
+ * the arbitrary-precision math library of your choice to convert it to a string integer.
*/
public function getClockSeqLow(): string
{
$instance = ($this->unwrapped ?? $this->unwrap());
- return $instance->getNumberConverter()
- ->fromHex(
- $instance->getFields()
- ->getClockSeqLow()
- ->toString()
- );
+ $fields = $instance->getFields();
+ assert($fields instanceof \Ramsey\Uuid\Rfc4122\FieldsInterface);
+
+ return $instance->getNumberConverter()->fromHex($fields->getClockSeqLow()->toString());
}
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
- * instance, you may call {@see Rfc4122FieldsInterface::getClockSeq()}
- * and use the arbitrary-precision math library of your choice to
- * convert it to a string integer.
- *
- * @psalm-suppress UndefinedInterfaceMethod
- * @psalm-suppress DeprecatedMethod
- * @psalm-suppress MixedArgument
- * @psalm-suppress MixedMethodCall
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see FieldsInterface} instance. If it is a
+ * {@see Rfc4122FieldsInterface} instance, you may call {@see Rfc4122FieldsInterface::getClockSeq()} and use the
+ * arbitrary-precision math library of your choice to convert it to a string integer.
*/
public function getClockSequence(): string
{
$instance = ($this->unwrapped ?? $this->unwrap());
- return $instance->getNumberConverter()
- ->fromHex(
- $instance->getFields()
- ->getClockSeq()
- ->toString()
- );
+ $fields = $instance->getFields();
+ assert($fields instanceof \Ramsey\Uuid\Rfc4122\FieldsInterface);
+
+ return $instance->getNumberConverter()->fromHex($fields->getClockSeq()->toString());
}
/**
- * @deprecated This method will be removed in 5.0.0. There is no direct
- * alternative, but the same information may be obtained by splitting
- * in half the value returned by {@see UuidInterface::getHex()}.
- *
- * @psalm-suppress UndefinedInterfaceMethod
- * @psalm-suppress DeprecatedMethod
- * @psalm-suppress MixedArgument
- * @psalm-suppress MixedMethodCall
+ * @deprecated This method will be removed in 5.0.0. There is no direct alternative, but the same information may be
+ * obtained by splitting in half the value returned by {@see UuidInterface::getHex()}.
*/
public function getLeastSignificantBits(): string
{
$instance = ($this->unwrapped ?? $this->unwrap());
- return $instance->getNumberConverter()
- ->fromHex(substr($instance->getHex()->toString(), 16));
+ return $instance->getNumberConverter()->fromHex(substr($instance->getHex()->toString(), 16));
}
/**
- * @deprecated This method will be removed in 5.0.0. There is no direct
- * alternative, but the same information may be obtained by splitting
- * in half the value returned by {@see UuidInterface::getHex()}.
- *
- * @psalm-suppress UndefinedInterfaceMethod
- * @psalm-suppress DeprecatedMethod
- * @psalm-suppress MixedArgument
- * @psalm-suppress MixedMethodCall
+ * @deprecated This method will be removed in 5.0.0. There is no direct alternative, but the same information may be
+ * obtained by splitting in half the value returned by {@see UuidInterface::getHex()}.
*/
public function getMostSignificantBits(): string
{
$instance = ($this->unwrapped ?? $this->unwrap());
- return $instance->getNumberConverter()
- ->fromHex(substr($instance->getHex()->toString(), 0, 16));
+ return $instance->getNumberConverter()->fromHex(substr($instance->getHex()->toString(), 0, 16));
}
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
- * instance, you may call {@see Rfc4122FieldsInterface::getNode()}
- * and use the arbitrary-precision math library of your choice to
- * convert it to a string integer.
- *
- * @psalm-suppress UndefinedInterfaceMethod
- * @psalm-suppress DeprecatedMethod
- * @psalm-suppress MixedArgument
- * @psalm-suppress MixedMethodCall
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see FieldsInterface} instance. If it is a
+ * {@see Rfc4122FieldsInterface} instance, you may call {@see Rfc4122FieldsInterface::getNode()} and use the
+ * arbitrary-precision math library of your choice to convert it to a string integer.
*/
public function getNode(): string
{
$instance = ($this->unwrapped ?? $this->unwrap());
- return $instance->getNumberConverter()
- ->fromHex(
- $instance->getFields()
- ->getNode()
- ->toString()
- );
+ $fields = $instance->getFields();
+ assert($fields instanceof \Ramsey\Uuid\Rfc4122\FieldsInterface);
+
+ return $instance->getNumberConverter()->fromHex($fields->getNode()->toString());
}
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
- * instance, you may call {@see Rfc4122FieldsInterface::getTimeHiAndVersion()}
- * and use the arbitrary-precision math library of your choice to
- * convert it to a string integer.
- *
- * @psalm-suppress UndefinedInterfaceMethod
- * @psalm-suppress DeprecatedMethod
- * @psalm-suppress MixedArgument
- * @psalm-suppress MixedMethodCall
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see FieldsInterface} instance. If it is a
+ * {@see Rfc4122FieldsInterface} instance, you may call {@see Rfc4122FieldsInterface::getTimeHiAndVersion()} and
+ * use the arbitrary-precision math library of your choice to convert it to a string integer.
*/
public function getTimeHiAndVersion(): string
{
$instance = ($this->unwrapped ?? $this->unwrap());
- return $instance->getNumberConverter()
- ->fromHex(
- $instance->getFields()
- ->getTimeHiAndVersion()
- ->toString()
- );
+ $fields = $instance->getFields();
+ assert($fields instanceof \Ramsey\Uuid\Rfc4122\FieldsInterface);
+
+ return $instance->getNumberConverter()->fromHex($fields->getTimeHiAndVersion()->toString());
}
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
- * instance, you may call {@see Rfc4122FieldsInterface::getTimeLow()}
- * and use the arbitrary-precision math library of your choice to
- * convert it to a string integer.
- *
- * @psalm-suppress UndefinedInterfaceMethod
- * @psalm-suppress DeprecatedMethod
- * @psalm-suppress MixedArgument
- * @psalm-suppress MixedMethodCall
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see FieldsInterface} instance. If it is a
+ * {@see Rfc4122FieldsInterface} instance, you may call {@see Rfc4122FieldsInterface::getTimeLow()} and use the
+ * arbitrary-precision math library of your choice to convert it to a string integer.
*/
public function getTimeLow(): string
{
$instance = ($this->unwrapped ?? $this->unwrap());
- return $instance->getNumberConverter()
- ->fromHex(
- $instance->getFields()
- ->getTimeLow()
- ->toString()
- );
+ $fields = $instance->getFields();
+ assert($fields instanceof \Ramsey\Uuid\Rfc4122\FieldsInterface);
+
+ return $instance->getNumberConverter()->fromHex($fields->getTimeLow()->toString());
}
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
- * instance, you may call {@see Rfc4122FieldsInterface::getTimeMid()}
- * and use the arbitrary-precision math library of your choice to
- * convert it to a string integer.
- *
- * @psalm-suppress UndefinedInterfaceMethod
- * @psalm-suppress DeprecatedMethod
- * @psalm-suppress MixedArgument
- * @psalm-suppress MixedMethodCall
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see FieldsInterface} instance. If it is a
+ * {@see Rfc4122FieldsInterface} instance, you may call {@see Rfc4122FieldsInterface::getTimeMid()} and use the
+ * arbitrary-precision math library of your choice to convert it to a string integer.
*/
public function getTimeMid(): string
{
$instance = ($this->unwrapped ?? $this->unwrap());
- return $instance->getNumberConverter()
- ->fromHex(
- $instance->getFields()
- ->getTimeMid()
- ->toString()
- );
+ $fields = $instance->getFields();
+ assert($fields instanceof \Ramsey\Uuid\Rfc4122\FieldsInterface);
+
+ return $instance->getNumberConverter()->fromHex($fields->getTimeMid()->toString());
}
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
- * instance, you may call {@see Rfc4122FieldsInterface::getTimestamp()}
- * and use the arbitrary-precision math library of your choice to
- * convert it to a string integer.
- *
- * @psalm-suppress UndefinedInterfaceMethod
- * @psalm-suppress DeprecatedMethod
- * @psalm-suppress MixedArgument
- * @psalm-suppress MixedMethodCall
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see FieldsInterface} instance. If it is a
+ * {@see Rfc4122FieldsInterface} instance, you may call {@see Rfc4122FieldsInterface::getTimestamp()} and use
+ * the arbitrary-precision math library of your choice to convert it to a string integer.
*/
public function getTimestamp(): string
{
$instance = ($this->unwrapped ?? $this->unwrap());
+
$fields = $instance->getFields();
+ assert($fields instanceof \Ramsey\Uuid\Rfc4122\FieldsInterface);
if ($fields->getVersion() !== 1) {
throw new UnsupportedOperationException('Not a time-based UUID');
}
- return $instance->getNumberConverter()
- ->fromHex($fields->getTimestamp()->toString());
+ return $instance->getNumberConverter()->fromHex($fields->getTimestamp()->toString());
}
public function toUuidV1(): UuidV1
@@ -558,18 +419,8 @@ final class LazyUuidFromString implements UuidInterface
return $instance;
}
- /**
- * @psalm-suppress ImpureMethodCall the retrieval of the factory is a clear violation of purity here: this is a
- * known pitfall of the design of this library, where a value object contains
- * a mutable reference to a factory. We use a fixed factory here, so the violation
- * will not have real-world effects, as this object is only instantiated with the
- * default factory settings/features.
- * @psalm-suppress InaccessibleProperty property {@see $unwrapped} is used as a cache: we don't expose it to the
- * outside world, so we should be fine here.
- */
private function unwrap(): UuidInterface
{
- return $this->unwrapped = (new UuidFactory())
- ->fromString($this->uuid);
+ return $this->unwrapped = (new UuidFactory())->fromString($this->uuid);
}
}
diff --git a/vendor/ramsey/uuid/src/Math/BrickMathCalculator.php b/vendor/ramsey/uuid/src/Math/BrickMathCalculator.php
index f2d8678..649f580 100644
--- a/vendor/ramsey/uuid/src/Math/BrickMathCalculator.php
+++ b/vendor/ramsey/uuid/src/Math/BrickMathCalculator.php
@@ -27,7 +27,7 @@ use Ramsey\Uuid\Type\NumberInterface;
/**
* A calculator using the brick/math library for arbitrary-precision arithmetic
*
- * @psalm-immutable
+ * @immutable
*/
final class BrickMathCalculator implements CalculatorInterface
{
@@ -52,6 +52,7 @@ final class BrickMathCalculator implements CalculatorInterface
$sum = $sum->plus($addend->toString());
}
+ /** @phpstan-ignore possiblyImpure.new */
return new IntegerObject((string) $sum);
}
@@ -63,6 +64,7 @@ final class BrickMathCalculator implements CalculatorInterface
$difference = $difference->minus($subtrahend->toString());
}
+ /** @phpstan-ignore possiblyImpure.new */
return new IntegerObject((string) $difference);
}
@@ -74,6 +76,7 @@ final class BrickMathCalculator implements CalculatorInterface
$product = $product->multipliedBy($multiplier->toString());
}
+ /** @phpstan-ignore possiblyImpure.new */
return new IntegerObject((string) $product);
}
@@ -81,8 +84,9 @@ final class BrickMathCalculator implements CalculatorInterface
int $roundingMode,
int $scale,
NumberInterface $dividend,
- NumberInterface ...$divisors
+ NumberInterface ...$divisors,
): NumberInterface {
+ /** @phpstan-ignore possiblyImpure.methodCall */
$brickRounding = $this->getBrickRoundingMode($roundingMode);
$quotient = BigDecimal::of($dividend->toString());
@@ -92,15 +96,18 @@ final class BrickMathCalculator implements CalculatorInterface
}
if ($scale === 0) {
+ /** @phpstan-ignore possiblyImpure.new */
return new IntegerObject((string) $quotient->toBigInteger());
}
+ /** @phpstan-ignore possiblyImpure.new */
return new Decimal((string) $quotient);
}
public function fromBase(string $value, int $base): IntegerObject
{
try {
+ /** @phpstan-ignore possiblyImpure.new */
return new IntegerObject((string) BigInteger::fromBase($value, $base));
} catch (MathException | \InvalidArgumentException $exception) {
throw new InvalidArgumentException(
@@ -126,6 +133,7 @@ final class BrickMathCalculator implements CalculatorInterface
public function toHexadecimal(IntegerObject $value): Hexadecimal
{
+ /** @phpstan-ignore possiblyImpure.new */
return new Hexadecimal($this->toBase($value, 16));
}
@@ -136,9 +144,11 @@ final class BrickMathCalculator implements CalculatorInterface
/**
* Maps ramsey/uuid rounding modes to those used by brick/math
+ *
+ * @return BrickMathRounding::*
*/
- private function getBrickRoundingMode(int $roundingMode): int
+ private function getBrickRoundingMode(int $roundingMode)
{
- return self::ROUNDING_MODE_MAP[$roundingMode] ?? 0;
+ return self::ROUNDING_MODE_MAP[$roundingMode] ?? BrickMathRounding::UNNECESSARY;
}
}
diff --git a/vendor/ramsey/uuid/src/Math/CalculatorInterface.php b/vendor/ramsey/uuid/src/Math/CalculatorInterface.php
index f03645d..e6789a6 100644
--- a/vendor/ramsey/uuid/src/Math/CalculatorInterface.php
+++ b/vendor/ramsey/uuid/src/Math/CalculatorInterface.php
@@ -21,7 +21,7 @@ use Ramsey\Uuid\Type\NumberInterface;
/**
* A calculator performs arithmetic operations on numbers
*
- * @psalm-immutable
+ * @immutable
*/
interface CalculatorInterface
{
@@ -32,6 +32,8 @@ interface CalculatorInterface
* @param NumberInterface ...$addends The additional integers to a add to the augend
*
* @return NumberInterface The sum of all the parameters
+ *
+ * @pure
*/
public function add(NumberInterface $augend, NumberInterface ...$addends): NumberInterface;
@@ -42,6 +44,8 @@ interface CalculatorInterface
* @param NumberInterface ...$subtrahends The integers to subtract from the minuend
*
* @return NumberInterface The difference after subtracting all parameters
+ *
+ * @pure
*/
public function subtract(NumberInterface $minuend, NumberInterface ...$subtrahends): NumberInterface;
@@ -52,6 +56,8 @@ interface CalculatorInterface
* @param NumberInterface ...$multipliers The factors by which to multiply the multiplicand
*
* @return NumberInterface The product of multiplying all the provided parameters
+ *
+ * @pure
*/
public function multiply(NumberInterface $multiplicand, NumberInterface ...$multipliers): NumberInterface;
@@ -61,17 +67,18 @@ interface CalculatorInterface
* @param int $roundingMode The RoundingMode constant to use for this operation
* @param int $scale The scale to use for this operation
* @param NumberInterface $dividend The integer to be divided
- * @param NumberInterface ...$divisors The integers to divide $dividend by, in
- * the order in which the division operations should take place
- * (left-to-right)
+ * @param NumberInterface ...$divisors The integers to divide $dividend by, in the order in which the division
+ * operations should take place (left-to-right)
*
* @return NumberInterface The quotient of dividing the provided parameters left-to-right
+ *
+ * @pure
*/
public function divide(
int $roundingMode,
int $scale,
NumberInterface $dividend,
- NumberInterface ...$divisors
+ NumberInterface ...$divisors,
): NumberInterface;
/**
@@ -81,6 +88,8 @@ interface CalculatorInterface
* @param int $base The base to convert from (i.e., 2, 16, 32, etc.)
*
* @return IntegerObject The base-10 integer value of the converted value
+ *
+ * @pure
*/
public function fromBase(string $value, int $base): IntegerObject;
@@ -91,16 +100,22 @@ interface CalculatorInterface
* @param int $base The base to convert to (i.e., 2, 16, 32, etc.)
*
* @return string The value represented in the specified base
+ *
+ * @pure
*/
public function toBase(IntegerObject $value, int $base): string;
/**
* Converts an Integer instance to a Hexadecimal instance
+ *
+ * @pure
*/
public function toHexadecimal(IntegerObject $value): Hexadecimal;
/**
* Converts a Hexadecimal instance to an Integer instance
+ *
+ * @pure
*/
public function toInteger(Hexadecimal $value): IntegerObject;
}
diff --git a/vendor/ramsey/uuid/src/Math/RoundingMode.php b/vendor/ramsey/uuid/src/Math/RoundingMode.php
index e710270..1497aa6 100644
--- a/vendor/ramsey/uuid/src/Math/RoundingMode.php
+++ b/vendor/ramsey/uuid/src/Math/RoundingMode.php
@@ -31,19 +31,91 @@ declare(strict_types=1);
namespace Ramsey\Uuid\Math;
/**
- * Specifies a rounding behavior for numerical operations capable of discarding
- * precision.
+ * Specifies a rounding behavior for numerical operations capable of discarding precision.
*
- * Each rounding mode indicates how the least significant returned digit of a
- * rounded result is to be calculated. If fewer digits are returned than the
- * digits needed to represent the exact numerical result, the discarded digits
- * will be referred to as the discarded fraction regardless the digits'
- * contribution to the value of the number. In other words, considered as a
- * numerical value, the discarded fraction could have an absolute value greater
- * than one.
+ * Each rounding mode indicates how the least significant returned digit of a rounded result is to be calculated. If
+ * fewer digits are returned than the digits needed to represent the exact numerical result, the discarded digits will
+ * be referred to as the discarded fraction regardless of the digits' contribution to the value of the number. In other
+ * words, considered as a numerical value, the discarded fraction could have an absolute value greater than one.
*/
final class RoundingMode
{
+ /**
+ * Asserts that the requested operation has an exact result; hence no rounding is necessary.
+ */
+ public const UNNECESSARY = 0;
+
+ /**
+ * Rounds away from zero.
+ *
+ * Always increments the digit prior to a nonzero discarded fraction. Note that this rounding mode never decreases
+ * the magnitude of the calculated value.
+ */
+ public const UP = 1;
+
+ /**
+ * Rounds towards zero.
+ *
+ * Never increments the digit prior to a discarded fraction (i.e., truncates). Note that this rounding mode never
+ * increases the magnitude of the calculated value.
+ */
+ public const DOWN = 2;
+
+ /**
+ * Rounds towards positive infinity.
+ *
+ * If the result is positive, behaves as for UP; if negative, behaves as for DOWN. Note that this rounding mode
+ * never decreases the calculated value.
+ */
+ public const CEILING = 3;
+
+ /**
+ * Rounds towards negative infinity.
+ *
+ * If the result is positive, behave as for DOWN; if negative, behave as for UP. Note that this rounding mode never
+ * increases the calculated value.
+ */
+ public const FLOOR = 4;
+
+ /**
+ * Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round up.
+ *
+ * Behaves as for UP if the discarded fraction is >= 0.5; otherwise, behaves as for DOWN. Note that this is the
+ * rounding mode commonly taught at school.
+ */
+ public const HALF_UP = 5;
+
+ /**
+ * Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round down.
+ *
+ * Behaves as for UP if the discarded fraction is > 0.5; otherwise, behaves as for DOWN.
+ */
+ public const HALF_DOWN = 6;
+
+ /**
+ * Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round towards positive infinity.
+ *
+ * If the result is positive, behaves as for HALF_UP; if negative, behaves as for HALF_DOWN.
+ */
+ public const HALF_CEILING = 7;
+
+ /**
+ * Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round towards negative infinity.
+ *
+ * If the result is positive, behaves as for HALF_DOWN; if negative, behaves as for HALF_UP.
+ */
+ public const HALF_FLOOR = 8;
+
+ /**
+ * Rounds towards the "nearest neighbor" unless both neighbors are equidistant, in which case rounds towards the even neighbor.
+ *
+ * Behaves as for HALF_UP if the digit to the left of the discarded fraction is odd; behaves as for HALF_DOWN if it's even.
+ *
+ * Note that this is the rounding mode that statistically minimizes cumulative error when applied repeatedly over a
+ * sequence of calculations. It is sometimes known as "Banker's rounding", and is chiefly used in the USA.
+ */
+ public const HALF_EVEN = 9;
+
/**
* Private constructor. This class is not instantiable.
*
@@ -52,95 +124,4 @@ final class RoundingMode
private function __construct()
{
}
-
- /**
- * Asserts that the requested operation has an exact result, hence no
- * rounding is necessary.
- */
- public const UNNECESSARY = 0;
-
- /**
- * Rounds away from zero.
- *
- * Always increments the digit prior to a nonzero discarded fraction.
- * Note that this rounding mode never decreases the magnitude of the
- * calculated value.
- */
- public const UP = 1;
-
- /**
- * Rounds towards zero.
- *
- * Never increments the digit prior to a discarded fraction (i.e.,
- * truncates). Note that this rounding mode never increases the magnitude of
- * the calculated value.
- */
- public const DOWN = 2;
-
- /**
- * Rounds towards positive infinity.
- *
- * If the result is positive, behaves as for UP; if negative, behaves as for
- * DOWN. Note that this rounding mode never decreases the calculated value.
- */
- public const CEILING = 3;
-
- /**
- * Rounds towards negative infinity.
- *
- * If the result is positive, behave as for DOWN; if negative, behave as for
- * UP. Note that this rounding mode never increases the calculated value.
- */
- public const FLOOR = 4;
-
- /**
- * Rounds towards "nearest neighbor" unless both neighbors are equidistant,
- * in which case round up.
- *
- * Behaves as for UP if the discarded fraction is >= 0.5; otherwise, behaves
- * as for DOWN. Note that this is the rounding mode commonly taught at
- * school.
- */
- public const HALF_UP = 5;
-
- /**
- * Rounds towards "nearest neighbor" unless both neighbors are equidistant,
- * in which case round down.
- *
- * Behaves as for UP if the discarded fraction is > 0.5; otherwise, behaves
- * as for DOWN.
- */
- public const HALF_DOWN = 6;
-
- /**
- * Rounds towards "nearest neighbor" unless both neighbors are equidistant,
- * in which case round towards positive infinity.
- *
- * If the result is positive, behaves as for HALF_UP; if negative, behaves
- * as for HALF_DOWN.
- */
- public const HALF_CEILING = 7;
-
- /**
- * Rounds towards "nearest neighbor" unless both neighbors are equidistant,
- * in which case round towards negative infinity.
- *
- * If the result is positive, behaves as for HALF_DOWN; if negative, behaves
- * as for HALF_UP.
- */
- public const HALF_FLOOR = 8;
-
- /**
- * Rounds towards the "nearest neighbor" unless both neighbors are
- * equidistant, in which case rounds towards the even neighbor.
- *
- * Behaves as for HALF_UP if the digit to the left of the discarded fraction
- * is odd; behaves as for HALF_DOWN if it's even.
- *
- * Note that this is the rounding mode that statistically minimizes
- * cumulative error when applied repeatedly over a sequence of calculations.
- * It is sometimes known as "Banker's rounding", and is chiefly used in the
- * USA.
- */
- public const HALF_EVEN = 9;
}
diff --git a/vendor/ramsey/uuid/src/Nonstandard/Fields.php b/vendor/ramsey/uuid/src/Nonstandard/Fields.php
index 927bc6a..d309c9a 100644
--- a/vendor/ramsey/uuid/src/Nonstandard/Fields.php
+++ b/vendor/ramsey/uuid/src/Nonstandard/Fields.php
@@ -31,42 +31,32 @@ use function substr;
use const STR_PAD_LEFT;
/**
- * Nonstandard UUID fields do not conform to the RFC 4122 standard
+ * Nonstandard UUID fields do not conform to the RFC 9562 (formerly RFC 4122) standard
*
- * Since some systems may create nonstandard UUIDs, this implements the
- * Rfc4122\FieldsInterface, so that functionality of a nonstandard UUID is not
- * degraded, in the event these UUIDs are expected to contain RFC 4122 fields.
+ * Since some systems may create nonstandard UUIDs, this implements the {@see FieldsInterface}, so that functionality of
+ * a nonstandard UUID is not degraded, in the event these UUIDs are expected to contain RFC 9562 (formerly RFC 4122) fields.
*
- * Internally, this class represents the fields together as a 16-byte binary
- * string.
+ * Internally, this class represents the fields together as a 16-byte binary string.
*
- * @psalm-immutable
+ * @immutable
*/
final class Fields implements FieldsInterface
{
use SerializableFieldsTrait;
use VariantTrait;
- /**
- * @var string
- */
- private $bytes;
-
/**
* @param string $bytes A 16-byte binary string representation of a UUID
*
* @throws InvalidArgumentException if the byte string is not exactly 16 bytes
*/
- public function __construct(string $bytes)
+ public function __construct(private string $bytes)
{
- if (strlen($bytes) !== 16) {
+ if (strlen($this->bytes) !== 16) {
throw new InvalidArgumentException(
- 'The byte string must be 16 bytes long; '
- . 'received ' . strlen($bytes) . ' bytes'
+ 'The byte string must be 16 bytes long; received ' . strlen($this->bytes) . ' bytes',
);
}
-
- $this->bytes = $bytes;
}
public function getBytes(): string
@@ -130,4 +120,9 @@ final class Fields implements FieldsInterface
{
return false;
}
+
+ public function isMax(): bool
+ {
+ return false;
+ }
}
diff --git a/vendor/ramsey/uuid/src/Nonstandard/Uuid.php b/vendor/ramsey/uuid/src/Nonstandard/Uuid.php
index 715f825..7f15e6e 100644
--- a/vendor/ramsey/uuid/src/Nonstandard/Uuid.php
+++ b/vendor/ramsey/uuid/src/Nonstandard/Uuid.php
@@ -20,9 +20,10 @@ use Ramsey\Uuid\Converter\TimeConverterInterface;
use Ramsey\Uuid\Uuid as BaseUuid;
/**
- * Nonstandard\Uuid is a UUID that doesn't conform to RFC 4122
+ * Nonstandard\Uuid is a UUID that doesn't conform to RFC 9562 (formerly RFC 4122)
*
- * @psalm-immutable
+ * @immutable
+ * @pure
*/
final class Uuid extends BaseUuid
{
@@ -30,7 +31,7 @@ final class Uuid extends BaseUuid
Fields $fields,
NumberConverterInterface $numberConverter,
CodecInterface $codec,
- TimeConverterInterface $timeConverter
+ TimeConverterInterface $timeConverter,
) {
parent::__construct($fields, $numberConverter, $codec, $timeConverter);
}
diff --git a/vendor/ramsey/uuid/src/Nonstandard/UuidBuilder.php b/vendor/ramsey/uuid/src/Nonstandard/UuidBuilder.php
index 0c89277..74da992 100644
--- a/vendor/ramsey/uuid/src/Nonstandard/UuidBuilder.php
+++ b/vendor/ramsey/uuid/src/Nonstandard/UuidBuilder.php
@@ -25,32 +25,19 @@ use Throwable;
/**
* Nonstandard\UuidBuilder builds instances of Nonstandard\Uuid
*
- * @psalm-immutable
+ * @immutable
*/
class UuidBuilder implements UuidBuilderInterface
{
/**
- * @var NumberConverterInterface
- */
- private $numberConverter;
-
- /**
- * @var TimeConverterInterface
- */
- private $timeConverter;
-
- /**
- * @param NumberConverterInterface $numberConverter The number converter to
- * use when constructing the Nonstandard\Uuid
- * @param TimeConverterInterface $timeConverter The time converter to use
- * for converting timestamps extracted from a UUID to Unix timestamps
+ * @param NumberConverterInterface $numberConverter The number converter to use when constructing the Nonstandard\Uuid
+ * @param TimeConverterInterface $timeConverter The time converter to use for converting timestamps extracted from a
+ * UUID to Unix timestamps
*/
public function __construct(
- NumberConverterInterface $numberConverter,
- TimeConverterInterface $timeConverter
+ private NumberConverterInterface $numberConverter,
+ private TimeConverterInterface $timeConverter,
) {
- $this->numberConverter = $numberConverter;
- $this->timeConverter = $timeConverter;
}
/**
@@ -59,30 +46,29 @@ class UuidBuilder implements UuidBuilderInterface
* @param CodecInterface $codec The codec to use for building this instance
* @param string $bytes The byte string from which to construct a UUID
*
- * @return Uuid The Nonstandard\UuidBuilder returns an instance of
- * Nonstandard\Uuid
+ * @return Uuid The Nonstandard\UuidBuilder returns an instance of Nonstandard\Uuid
*
- * @psalm-pure
+ * @pure
*/
public function build(CodecInterface $codec, string $bytes): UuidInterface
{
try {
- return new Uuid(
- $this->buildFields($bytes),
- $this->numberConverter,
- $codec,
- $this->timeConverter
- );
+ /** @phpstan-ignore possiblyImpure.new */
+ return new Uuid($this->buildFields($bytes), $this->numberConverter, $codec, $this->timeConverter);
} catch (Throwable $e) {
+ /** @phpstan-ignore possiblyImpure.methodCall, possiblyImpure.methodCall */
throw new UnableToBuildUuidException($e->getMessage(), (int) $e->getCode(), $e);
}
}
/**
- * Proxy method to allow injecting a mock, for testing
+ * Proxy method to allow injecting a mock for testing
+ *
+ * @pure
*/
protected function buildFields(string $bytes): Fields
{
+ /** @phpstan-ignore possiblyImpure.new */
return new Fields($bytes);
}
}
diff --git a/vendor/ramsey/uuid/src/Nonstandard/UuidV6.php b/vendor/ramsey/uuid/src/Nonstandard/UuidV6.php
index 05586b3..e277afc 100644
--- a/vendor/ramsey/uuid/src/Nonstandard/UuidV6.php
+++ b/vendor/ramsey/uuid/src/Nonstandard/UuidV6.php
@@ -14,87 +14,57 @@ declare(strict_types=1);
namespace Ramsey\Uuid\Nonstandard;
-use DateTimeImmutable;
-use DateTimeInterface;
use Ramsey\Uuid\Codec\CodecInterface;
use Ramsey\Uuid\Converter\NumberConverterInterface;
use Ramsey\Uuid\Converter\TimeConverterInterface;
-use Ramsey\Uuid\Exception\DateTimeException;
use Ramsey\Uuid\Exception\InvalidArgumentException;
use Ramsey\Uuid\Lazy\LazyUuidFromString;
use Ramsey\Uuid\Rfc4122\FieldsInterface as Rfc4122FieldsInterface;
+use Ramsey\Uuid\Rfc4122\TimeTrait;
use Ramsey\Uuid\Rfc4122\UuidInterface;
use Ramsey\Uuid\Rfc4122\UuidV1;
-use Ramsey\Uuid\Uuid;
-use Throwable;
-
-use function hex2bin;
-use function str_pad;
-use function substr;
-
-use const STR_PAD_LEFT;
+use Ramsey\Uuid\Uuid as BaseUuid;
/**
- * Ordered-time, or version 6, UUIDs include timestamp, clock sequence, and node
- * values that are combined into a 128-bit unsigned integer
+ * Reordered time, or version 6, UUIDs include timestamp, clock sequence, and node values that are combined into a
+ * 128-bit unsigned integer
+ *
+ * @deprecated Use {@see \Ramsey\Uuid\Rfc4122\UuidV6} instead.
*
* @link https://github.com/uuid6/uuid6-ietf-draft UUID version 6 IETF draft
* @link http://gh.peabody.io/uuidv6/ "Version 6" UUIDs
+ * @link https://www.rfc-editor.org/rfc/rfc9562#section-5.6 RFC 9562, 5.6. UUID Version 6
*
- * @psalm-immutable
+ * @immutable
*/
-final class UuidV6 extends Uuid implements UuidInterface
+class UuidV6 extends BaseUuid implements UuidInterface
{
+ use TimeTrait;
+
/**
- * Creates a version 6 (time-based) UUID
+ * Creates a version 6 (reordered Gregorian time) UUID
*
* @param Rfc4122FieldsInterface $fields The fields from which to construct a UUID
- * @param NumberConverterInterface $numberConverter The number converter to use
- * for converting hex values to/from integers
- * @param CodecInterface $codec The codec to use when encoding or decoding
- * UUID strings
- * @param TimeConverterInterface $timeConverter The time converter to use
- * for converting timestamps extracted from a UUID to unix timestamps
+ * @param NumberConverterInterface $numberConverter The number converter to use for converting hex values to/from integers
+ * @param CodecInterface $codec The codec to use when encoding or decoding UUID strings
+ * @param TimeConverterInterface $timeConverter The time converter to use for converting timestamps extracted from a
+ * UUID to unix timestamps
*/
public function __construct(
Rfc4122FieldsInterface $fields,
NumberConverterInterface $numberConverter,
CodecInterface $codec,
- TimeConverterInterface $timeConverter
+ TimeConverterInterface $timeConverter,
) {
- if ($fields->getVersion() !== Uuid::UUID_TYPE_PEABODY) {
+ if ($fields->getVersion() !== BaseUuid::UUID_TYPE_REORDERED_TIME) {
throw new InvalidArgumentException(
- 'Fields used to create a UuidV6 must represent a '
- . 'version 6 (ordered-time) UUID'
+ 'Fields used to create a UuidV6 must represent a version 6 (reordered time) UUID',
);
}
parent::__construct($fields, $numberConverter, $codec, $timeConverter);
}
- /**
- * Returns a DateTimeInterface object representing the timestamp associated
- * with the UUID
- *
- * @return DateTimeImmutable A PHP DateTimeImmutable instance representing
- * the timestamp of a version 6 UUID
- */
- public function getDateTime(): DateTimeInterface
- {
- $time = $this->timeConverter->convertTime($this->fields->getTimestamp());
-
- try {
- return new DateTimeImmutable(
- '@'
- . $time->getSeconds()->toString()
- . '.'
- . str_pad($time->getMicroseconds()->toString(), 6, '0', STR_PAD_LEFT)
- );
- } catch (Throwable $e) {
- throw new DateTimeException($e->getMessage(), (int) $e->getCode(), $e);
- }
- }
-
/**
* Converts this UUID into an instance of a version 1 UUID
*/
@@ -108,7 +78,7 @@ final class UuidV6 extends Uuid implements UuidInterface
. substr($hex, 16);
/** @var LazyUuidFromString $uuid */
- $uuid = Uuid::fromBytes((string) hex2bin($hex));
+ $uuid = BaseUuid::fromBytes((string) hex2bin($hex));
return $uuid->toUuidV1();
}
@@ -116,7 +86,7 @@ final class UuidV6 extends Uuid implements UuidInterface
/**
* Converts a version 1 UUID into an instance of a version 6 UUID
*/
- public static function fromUuidV1(UuidV1 $uuidV1): UuidV6
+ public static function fromUuidV1(UuidV1 $uuidV1): \Ramsey\Uuid\Rfc4122\UuidV6
{
$hex = $uuidV1->getHex()->toString();
$hex = substr($hex, 13, 3)
@@ -126,7 +96,7 @@ final class UuidV6 extends Uuid implements UuidInterface
. substr($hex, 16);
/** @var LazyUuidFromString $uuid */
- $uuid = Uuid::fromBytes((string) hex2bin($hex));
+ $uuid = BaseUuid::fromBytes((string) hex2bin($hex));
return $uuid->toUuidV6();
}
diff --git a/vendor/ramsey/uuid/src/Provider/Dce/SystemDceSecurityProvider.php b/vendor/ramsey/uuid/src/Provider/Dce/SystemDceSecurityProvider.php
index 6d6240b..830ffdd 100644
--- a/vendor/ramsey/uuid/src/Provider/Dce/SystemDceSecurityProvider.php
+++ b/vendor/ramsey/uuid/src/Provider/Dce/SystemDceSecurityProvider.php
@@ -21,7 +21,6 @@ use Ramsey\Uuid\Type\Integer as IntegerObject;
use function escapeshellarg;
use function preg_split;
use function str_getcsv;
-use function strpos;
use function strrpos;
use function strtolower;
use function strtoupper;
@@ -42,6 +41,7 @@ class SystemDceSecurityProvider implements DceSecurityProviderInterface
*/
public function getUid(): IntegerObject
{
+ /** @var IntegerObject | int | float | string | null $uid */
static $uid = null;
if ($uid instanceof IntegerObject) {
@@ -54,9 +54,8 @@ class SystemDceSecurityProvider implements DceSecurityProviderInterface
if ($uid === '') {
throw new DceSecurityException(
- 'Unable to get a user identifier using the system DCE '
- . 'Security provider; please provide a custom identifier or '
- . 'use a different provider'
+ 'Unable to get a user identifier using the system DCE Security provider; please provide a custom '
+ . 'identifier or use a different provider',
);
}
@@ -72,6 +71,7 @@ class SystemDceSecurityProvider implements DceSecurityProviderInterface
*/
public function getGid(): IntegerObject
{
+ /** @var IntegerObject | int | float | string | null $gid */
static $gid = null;
if ($gid instanceof IntegerObject) {
@@ -84,9 +84,8 @@ class SystemDceSecurityProvider implements DceSecurityProviderInterface
if ($gid === '') {
throw new DceSecurityException(
- 'Unable to get a group identifier using the system DCE '
- . 'Security provider; please provide a custom identifier or '
- . 'use a different provider'
+ 'Unable to get a group identifier using the system DCE Security provider; please provide a custom '
+ . 'identifier or use a different provider',
);
}
@@ -104,15 +103,10 @@ class SystemDceSecurityProvider implements DceSecurityProviderInterface
return '';
}
- switch ($this->getOs()) {
- case 'WIN':
- return $this->getWindowsUid();
- case 'DAR':
- case 'FRE':
- case 'LIN':
- default:
- return trim((string) shell_exec('id -u'));
- }
+ return match ($this->getOs()) {
+ 'WIN' => $this->getWindowsUid(),
+ default => trim((string) shell_exec('id -u')),
+ };
}
/**
@@ -124,15 +118,10 @@ class SystemDceSecurityProvider implements DceSecurityProviderInterface
return '';
}
- switch ($this->getOs()) {
- case 'WIN':
- return $this->getWindowsGid();
- case 'DAR':
- case 'FRE':
- case 'LIN':
- default:
- return trim((string) shell_exec('id -g'));
- }
+ return match ($this->getOs()) {
+ 'WIN' => $this->getWindowsGid(),
+ default => trim((string) shell_exec('id -g')),
+ };
}
/**
@@ -140,9 +129,7 @@ class SystemDceSecurityProvider implements DceSecurityProviderInterface
*/
private function hasShellExec(): bool
{
- $disabledFunctions = strtolower((string) ini_get('disable_functions'));
-
- return strpos($disabledFunctions, 'shell_exec') === false;
+ return !str_contains(strtolower((string) ini_get('disable_functions')), 'shell_exec');
}
/**
@@ -150,23 +137,23 @@ class SystemDceSecurityProvider implements DceSecurityProviderInterface
*/
private function getOs(): string
{
- return strtoupper(substr(constant('PHP_OS'), 0, 3));
+ /** @var string $phpOs */
+ $phpOs = constant('PHP_OS');
+
+ return strtoupper(substr($phpOs, 0, 3));
}
/**
* Returns the user identifier for a user on a Windows system
*
- * Windows does not have the same concept as an effective POSIX UID for the
- * running script. Instead, each user is uniquely identified by an SID
- * (security identifier). The SID includes three 32-bit unsigned integers
- * that make up a unique domain identifier, followed by an RID (relative
- * identifier) that we will use as the UID. The primary caveat is that this
- * UID may not be unique to the system, since it is, instead, unique to the
- * domain.
+ * Windows does not have the same concept as an effective POSIX UID for the running script. Instead, each user is
+ * uniquely identified by an SID (security identifier). The SID includes three 32-bit unsigned integers that make up
+ * a unique domain identifier, followed by an RID (relative identifier) that we will use as the UID. The primary
+ * caveat is that this UID may not be unique to the system, since it is, instead, unique to the domain.
*
* @link https://www.lifewire.com/what-is-an-sid-number-2626005 What Is an SID Number?
- * @link https://bit.ly/30vE7NM Well-known SID Structures
- * @link https://bit.ly/2FWcYKJ Well-known security identifiers in Windows operating systems
+ * @link https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/81d92bba-d22b-4a8c-908a-554ab29148ab Well-known SID Structures
+ * @link https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/manage/understand-security-identifiers#well-known-sids Well-known SIDs
* @link https://www.windows-commandline.com/get-sid-of-user/ Get SID of user
*/
private function getWindowsUid(): string
@@ -177,7 +164,7 @@ class SystemDceSecurityProvider implements DceSecurityProviderInterface
return '';
}
- $sid = str_getcsv(trim((string) $response))[1] ?? '';
+ $sid = str_getcsv(trim((string) $response), escape: '\\')[1] ?? '';
if (($lastHyphen = strrpos($sid, '-')) === false) {
return '';
@@ -189,11 +176,10 @@ class SystemDceSecurityProvider implements DceSecurityProviderInterface
/**
* Returns a group identifier for a user on a Windows system
*
- * Since Windows does not have the same concept as an effective POSIX GID
- * for the running script, we will get the local group memberships for the
- * user running the script. Then, we will get the SID (security identifier)
- * for the first group that appears in that list. Finally, we will return
- * the RID (relative identifier) for the group and use that as the GID.
+ * Since Windows does not have the same concept as an effective POSIX GID for the running script, we will get the
+ * local group memberships for the user running the script. Then, we will get the SID (security identifier) for the
+ * first group that appears in that list. Finally, we will return the RID (relative identifier) for the group and
+ * use that as the GID.
*
* @link https://www.windows-commandline.com/list-of-user-groups-command-line/ List of user groups command line
*/
@@ -205,9 +191,7 @@ class SystemDceSecurityProvider implements DceSecurityProviderInterface
return '';
}
- /** @var string[] $userGroups */
$userGroups = preg_split('/\s{2,}/', (string) $response, -1, PREG_SPLIT_NO_EMPTY);
-
$firstGroup = trim($userGroups[1] ?? '', "* \t\n\r\0\x0B");
if ($firstGroup === '') {
@@ -220,15 +204,13 @@ class SystemDceSecurityProvider implements DceSecurityProviderInterface
return '';
}
- /** @var string[] $userGroup */
$userGroup = preg_split('/\s{2,}/', (string) $response, -1, PREG_SPLIT_NO_EMPTY);
-
$sid = $userGroup[1] ?? '';
if (($lastHyphen = strrpos($sid, '-')) === false) {
return '';
}
- return trim((string) substr($sid, $lastHyphen + 1));
+ return trim(substr($sid, $lastHyphen + 1));
}
}
diff --git a/vendor/ramsey/uuid/src/Provider/DceSecurityProviderInterface.php b/vendor/ramsey/uuid/src/Provider/DceSecurityProviderInterface.php
index 8325da6..f1c3e97 100644
--- a/vendor/ramsey/uuid/src/Provider/DceSecurityProviderInterface.php
+++ b/vendor/ramsey/uuid/src/Provider/DceSecurityProviderInterface.php
@@ -18,8 +18,7 @@ use Ramsey\Uuid\Rfc4122\UuidV2;
use Ramsey\Uuid\Type\Integer as IntegerObject;
/**
- * A DCE provider provides access to local domain identifiers for version 2,
- * DCE Security, UUIDs
+ * A DCE provider provides access to local domain identifiers for version 2, DCE Security, UUIDs
*
* @see UuidV2
*/
diff --git a/vendor/ramsey/uuid/src/Provider/Node/FallbackNodeProvider.php b/vendor/ramsey/uuid/src/Provider/Node/FallbackNodeProvider.php
index cad0104..267ea9b 100644
--- a/vendor/ramsey/uuid/src/Provider/Node/FallbackNodeProvider.php
+++ b/vendor/ramsey/uuid/src/Provider/Node/FallbackNodeProvider.php
@@ -19,29 +19,22 @@ use Ramsey\Uuid\Provider\NodeProviderInterface;
use Ramsey\Uuid\Type\Hexadecimal;
/**
- * FallbackNodeProvider retrieves the system node ID by stepping through a list
- * of providers until a node ID can be obtained
+ * FallbackNodeProvider retrieves the system node ID by stepping through a list of providers until a node ID can be obtained
*/
class FallbackNodeProvider implements NodeProviderInterface
{
/**
- * @var NodeProviderCollection
+ * @param iterable $providers Array of node providers
*/
- private $nodeProviders;
-
- /**
- * @param NodeProviderCollection $providers Array of node providers
- */
- public function __construct(NodeProviderCollection $providers)
+ public function __construct(private iterable $providers)
{
- $this->nodeProviders = $providers;
}
public function getNode(): Hexadecimal
{
$lastProviderException = null;
- foreach ($this->nodeProviders as $provider) {
+ foreach ($this->providers as $provider) {
try {
return $provider->getNode();
} catch (NodeException $exception) {
@@ -51,10 +44,6 @@ class FallbackNodeProvider implements NodeProviderInterface
}
}
- throw new NodeException(
- 'Unable to find a suitable node provider',
- 0,
- $lastProviderException
- );
+ throw new NodeException(message: 'Unable to find a suitable node provider', previous: $lastProviderException);
}
}
diff --git a/vendor/ramsey/uuid/src/Provider/Node/NodeProviderCollection.php b/vendor/ramsey/uuid/src/Provider/Node/NodeProviderCollection.php
index 536cb60..1d4908a 100644
--- a/vendor/ramsey/uuid/src/Provider/Node/NodeProviderCollection.php
+++ b/vendor/ramsey/uuid/src/Provider/Node/NodeProviderCollection.php
@@ -21,6 +21,11 @@ use Ramsey\Uuid\Type\Hexadecimal;
/**
* A collection of NodeProviderInterface objects
*
+ * @deprecated this class has been deprecated and will be removed in 5.0.0. The use-case for this class comes from a
+ * pre-`phpstan/phpstan` and pre-`vimeo/psalm` ecosystem, in which type safety had to be mostly enforced at runtime:
+ * that is no longer necessary, now that you can safely verify your code to be correct and use more generic types
+ * like `iterable` instead.
+ *
* @extends AbstractCollection
*/
class NodeProviderCollection extends AbstractCollection
@@ -33,11 +38,7 @@ class NodeProviderCollection extends AbstractCollection
/**
* Re-constructs the object from its serialized form
*
- * @param string $serialized The serialized PHP string to unserialize into
- * a UuidInterface instance
- *
- * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
- * @psalm-suppress RedundantConditionGivenDocblockType
+ * @param string $serialized The serialized PHP string to unserialize into a UuidInterface instance
*/
public function unserialize($serialized): void
{
@@ -51,11 +52,7 @@ class NodeProviderCollection extends AbstractCollection
],
]);
- $this->data = array_filter(
- $data,
- function ($unserialized): bool {
- return $unserialized instanceof NodeProviderInterface;
- }
- );
+ /** @phpstan-ignore-next-line */
+ $this->data = array_filter($data, fn ($unserialized): bool => $unserialized instanceof NodeProviderInterface);
}
}
diff --git a/vendor/ramsey/uuid/src/Provider/Node/RandomNodeProvider.php b/vendor/ramsey/uuid/src/Provider/Node/RandomNodeProvider.php
index 7614136..9334ce0 100644
--- a/vendor/ramsey/uuid/src/Provider/Node/RandomNodeProvider.php
+++ b/vendor/ramsey/uuid/src/Provider/Node/RandomNodeProvider.php
@@ -31,7 +31,7 @@ use const STR_PAD_LEFT;
/**
* RandomNodeProvider generates a random node ID
*
- * @link http://tools.ietf.org/html/rfc4122#section-4.5 RFC 4122, § 4.5: Node IDs that Do Not Identify the Host
+ * @link https://www.rfc-editor.org/rfc/rfc9562#section-6.10 RFC 9562, 6.10. UUIDs That Do Not Identify the Host
*/
class RandomNodeProvider implements NodeProviderInterface
{
@@ -40,30 +40,16 @@ class RandomNodeProvider implements NodeProviderInterface
try {
$nodeBytes = random_bytes(6);
} catch (Throwable $exception) {
- throw new RandomSourceException(
- $exception->getMessage(),
- (int) $exception->getCode(),
- $exception
- );
+ throw new RandomSourceException($exception->getMessage(), (int) $exception->getCode(), $exception);
}
// Split the node bytes for math on 32-bit systems.
$nodeMsb = substr($nodeBytes, 0, 3);
$nodeLsb = substr($nodeBytes, 3);
- // Set the multicast bit; see RFC 4122, section 4.5.
- $nodeMsb = hex2bin(
- str_pad(
- dechex(hexdec(bin2hex($nodeMsb)) | 0x010000),
- 6,
- '0',
- STR_PAD_LEFT
- )
- );
+ // Set the multicast bit; see RFC 9562, section 6.10.
+ $nodeMsb = hex2bin(str_pad(dechex(hexdec(bin2hex($nodeMsb)) | 0x010000), 6, '0', STR_PAD_LEFT));
- // Recombine the node bytes.
- $node = $nodeMsb . $nodeLsb;
-
- return new Hexadecimal(str_pad(bin2hex($node), 12, '0', STR_PAD_LEFT));
+ return new Hexadecimal(str_pad(bin2hex($nodeMsb . $nodeLsb), 12, '0', STR_PAD_LEFT));
}
}
diff --git a/vendor/ramsey/uuid/src/Provider/Node/StaticNodeProvider.php b/vendor/ramsey/uuid/src/Provider/Node/StaticNodeProvider.php
index 51f1b02..612ccd9 100644
--- a/vendor/ramsey/uuid/src/Provider/Node/StaticNodeProvider.php
+++ b/vendor/ramsey/uuid/src/Provider/Node/StaticNodeProvider.php
@@ -28,14 +28,11 @@ use const STR_PAD_LEFT;
/**
* StaticNodeProvider provides a static node value with the multicast bit set
*
- * @link http://tools.ietf.org/html/rfc4122#section-4.5 RFC 4122, § 4.5: Node IDs that Do Not Identify the Host
+ * @link https://www.rfc-editor.org/rfc/rfc9562#section-6.10 RFC 9562, 6.10. UUIDs That Do Not Identify the Host
*/
class StaticNodeProvider implements NodeProviderInterface
{
- /**
- * @var Hexadecimal
- */
- private $node;
+ private Hexadecimal $node;
/**
* @param Hexadecimal $node The static node value to use
@@ -43,9 +40,7 @@ class StaticNodeProvider implements NodeProviderInterface
public function __construct(Hexadecimal $node)
{
if (strlen($node->toString()) > 12) {
- throw new InvalidArgumentException(
- 'Static node value cannot be greater than 12 hexadecimal characters'
- );
+ throw new InvalidArgumentException('Static node value cannot be greater than 12 hexadecimal characters');
}
$this->node = $this->setMulticastBit($node);
@@ -63,13 +58,7 @@ class StaticNodeProvider implements NodeProviderInterface
{
$nodeHex = str_pad($node->toString(), 12, '0', STR_PAD_LEFT);
$firstOctet = substr($nodeHex, 0, 2);
-
- $firstOctet = str_pad(
- dechex(hexdec($firstOctet) | 0x01),
- 2,
- '0',
- STR_PAD_LEFT
- );
+ $firstOctet = str_pad(dechex(hexdec($firstOctet) | 0x01), 2, '0', STR_PAD_LEFT);
return new Hexadecimal($firstOctet . substr($nodeHex, 2));
}
diff --git a/vendor/ramsey/uuid/src/Provider/Node/SystemNodeProvider.php b/vendor/ramsey/uuid/src/Provider/Node/SystemNodeProvider.php
index d512f22..05e2ea8 100644
--- a/vendor/ramsey/uuid/src/Provider/Node/SystemNodeProvider.php
+++ b/vendor/ramsey/uuid/src/Provider/Node/SystemNodeProvider.php
@@ -27,8 +27,8 @@ use function ob_start;
use function preg_match;
use function preg_match_all;
use function reset;
+use function str_contains;
use function str_replace;
-use function strpos;
use function strtolower;
use function strtoupper;
use function substr;
@@ -39,13 +39,12 @@ use const PREG_PATTERN_ORDER;
/**
* SystemNodeProvider retrieves the system node ID, if possible
*
- * The system node ID, or host ID, is often the same as the MAC address for a
- * network interface on the host.
+ * The system node ID, or host ID, is often the same as the MAC address for a network interface on the host.
*/
class SystemNodeProvider implements NodeProviderInterface
{
/**
- * Pattern to match nodes in ifconfig and ipconfig output.
+ * Pattern to match nodes in `ifconfig` and `ipconfig` output.
*/
private const IFCONFIG_PATTERN = '/[^:]([0-9a-f]{2}([:-])[0-9a-f]{2}(\2[0-9a-f]{2}){4})[^:]/i';
@@ -59,23 +58,22 @@ class SystemNodeProvider implements NodeProviderInterface
$node = $this->getNodeFromSystem();
if ($node === '') {
- throw new NodeException(
- 'Unable to fetch a node for this system'
- );
+ throw new NodeException('Unable to fetch a node for this system');
}
return new Hexadecimal($node);
}
/**
- * Returns the system node, if it can find it
+ * Returns the system node if found
*/
protected function getNodeFromSystem(): string
{
+ /** @var string | null $node */
static $node = null;
if ($node !== null) {
- return (string) $node;
+ return $node;
}
// First, try a Linux-specific approach.
@@ -98,14 +96,15 @@ class SystemNodeProvider implements NodeProviderInterface
*/
protected function getIfconfig(): string
{
- $disabledFunctions = strtolower((string) ini_get('disable_functions'));
-
- if (strpos($disabledFunctions, 'passthru') !== false) {
+ if (str_contains(strtolower((string) ini_get('disable_functions')), 'passthru')) {
return '';
}
+ /** @var string $phpOs */
+ $phpOs = constant('PHP_OS');
+
ob_start();
- switch (strtoupper(substr(constant('PHP_OS'), 0, 3))) {
+ switch (strtoupper(substr($phpOs, 0, 3))) {
case 'WIN':
passthru('ipconfig /all 2>&1');
@@ -127,12 +126,15 @@ class SystemNodeProvider implements NodeProviderInterface
$ifconfig = (string) ob_get_clean();
- $node = '';
if (preg_match_all(self::IFCONFIG_PATTERN, $ifconfig, $matches, PREG_PATTERN_ORDER)) {
- $node = $matches[1][0] ?? '';
+ foreach ($matches[1] as $iface) {
+ if ($iface !== '00:00:00:00:00:00' && $iface !== '00-00-00-00-00-00') {
+ return $iface;
+ }
+ }
}
- return $node;
+ return '';
}
/**
@@ -140,34 +142,43 @@ class SystemNodeProvider implements NodeProviderInterface
*/
protected function getSysfs(): string
{
- $mac = '';
+ /** @var string $phpOs */
+ $phpOs = constant('PHP_OS');
- if (strtoupper(constant('PHP_OS')) === 'LINUX') {
- $addressPaths = glob('/sys/class/net/*/address', GLOB_NOSORT);
-
- if ($addressPaths === false || count($addressPaths) === 0) {
- return '';
- }
-
- $macs = [];
-
- array_walk($addressPaths, function (string $addressPath) use (&$macs): void {
- if (is_readable($addressPath)) {
- $macs[] = file_get_contents($addressPath);
- }
- });
-
- $macs = array_map('trim', $macs);
-
- // Remove invalid entries.
- $macs = array_filter($macs, function (string $address) {
- return $address !== '00:00:00:00:00:00'
- && preg_match(self::SYSFS_PATTERN, $address);
- });
-
- $mac = reset($macs);
+ if (strtoupper($phpOs) !== 'LINUX') {
+ return '';
}
+ $addressPaths = glob('/sys/class/net/*/address', GLOB_NOSORT);
+
+ if ($addressPaths === false || count($addressPaths) === 0) {
+ return '';
+ }
+
+ /** @var array $macs */
+ $macs = [];
+
+ array_walk($addressPaths, function (string $addressPath) use (&$macs): void {
+ if (is_readable($addressPath)) {
+ $macs[] = file_get_contents($addressPath);
+ }
+ });
+
+ /** @var callable $trim */
+ $trim = 'trim';
+
+ $macs = array_map($trim, $macs);
+
+ // Remove invalid entries.
+ $macs = array_filter($macs, function (mixed $address): bool {
+ assert(is_string($address));
+
+ return $address !== '00:00:00:00:00:00' && preg_match(self::SYSFS_PATTERN, $address);
+ });
+
+ /** @var bool | string $mac */
+ $mac = reset($macs);
+
return (string) $mac;
}
}
diff --git a/vendor/ramsey/uuid/src/Provider/Time/FixedTimeProvider.php b/vendor/ramsey/uuid/src/Provider/Time/FixedTimeProvider.php
index b8bfd72..68d9f10 100644
--- a/vendor/ramsey/uuid/src/Provider/Time/FixedTimeProvider.php
+++ b/vendor/ramsey/uuid/src/Provider/Time/FixedTimeProvider.php
@@ -19,45 +19,38 @@ use Ramsey\Uuid\Type\Integer as IntegerObject;
use Ramsey\Uuid\Type\Time;
/**
- * FixedTimeProvider uses an known time to provide the time
+ * FixedTimeProvider uses a known time to provide the time
*
- * This provider allows the use of a previously-generated, or known, time
- * when generating time-based UUIDs.
+ * This provider allows the use of a previously generated, or known, time when generating time-based UUIDs.
*/
class FixedTimeProvider implements TimeProviderInterface
{
- /**
- * @var Time
- */
- private $fixedTime;
-
- public function __construct(Time $time)
+ public function __construct(private Time $time)
{
- $this->fixedTime = $time;
}
/**
* Sets the `usec` component of the time
*
- * @param int|string|IntegerObject $value The `usec` value to set
+ * @param IntegerObject | int | string $value The `usec` value to set
*/
public function setUsec($value): void
{
- $this->fixedTime = new Time($this->fixedTime->getSeconds(), $value);
+ $this->time = new Time($this->time->getSeconds(), $value);
}
/**
* Sets the `sec` component of the time
*
- * @param int|string|IntegerObject $value The `sec` value to set
+ * @param IntegerObject | int | string $value The `sec` value to set
*/
public function setSec($value): void
{
- $this->fixedTime = new Time($value, $this->fixedTime->getMicroseconds());
+ $this->time = new Time($value, $this->time->getMicroseconds());
}
public function getTime(): Time
{
- return $this->fixedTime;
+ return $this->time;
}
}
diff --git a/vendor/ramsey/uuid/src/Rfc4122/Fields.php b/vendor/ramsey/uuid/src/Rfc4122/Fields.php
index 2ccc20b..4f607d5 100644
--- a/vendor/ramsey/uuid/src/Rfc4122/Fields.php
+++ b/vendor/ramsey/uuid/src/Rfc4122/Fields.php
@@ -31,56 +31,51 @@ use function unpack;
use const STR_PAD_LEFT;
/**
- * RFC 4122 variant UUIDs are comprised of a set of named fields
+ * RFC 9562 (formerly RFC 4122) variant UUIDs consist of a set of named fields
*
- * Internally, this class represents the fields together as a 16-byte binary
- * string.
+ * Internally, this class represents the fields together as a 16-byte binary string.
*
- * @psalm-immutable
+ * @immutable
*/
final class Fields implements FieldsInterface
{
+ use MaxTrait;
use NilTrait;
use SerializableFieldsTrait;
use VariantTrait;
use VersionTrait;
- /**
- * @var string
- */
- private $bytes;
-
/**
* @param string $bytes A 16-byte binary string representation of a UUID
*
* @throws InvalidArgumentException if the byte string is not exactly 16 bytes
- * @throws InvalidArgumentException if the byte string does not represent an RFC 4122 UUID
+ * @throws InvalidArgumentException if the byte string does not represent an RFC 9562 (formerly RFC 4122) UUID
* @throws InvalidArgumentException if the byte string does not contain a valid version
*/
- public function __construct(string $bytes)
+ public function __construct(private string $bytes)
{
- if (strlen($bytes) !== 16) {
+ if (strlen($this->bytes) !== 16) {
throw new InvalidArgumentException(
- 'The byte string must be 16 bytes long; '
- . 'received ' . strlen($bytes) . ' bytes'
+ 'The byte string must be 16 bytes long; ' . 'received ' . strlen($this->bytes) . ' bytes',
);
}
- $this->bytes = $bytes;
-
if (!$this->isCorrectVariant()) {
throw new InvalidArgumentException(
- 'The byte string received does not conform to the RFC 4122 variant'
+ 'The byte string received does not conform to the RFC 9562 (formerly RFC 4122) variant',
);
}
if (!$this->isCorrectVersion()) {
throw new InvalidArgumentException(
- 'The byte string received does not contain a valid RFC 4122 version'
+ 'The byte string received does not contain a valid RFC 9562 (formerly RFC 4122) version',
);
}
}
+ /**
+ * @pure
+ */
public function getBytes(): string
{
return $this->bytes;
@@ -88,7 +83,13 @@ final class Fields implements FieldsInterface
public function getClockSeq(): Hexadecimal
{
- $clockSeq = hexdec(bin2hex(substr($this->bytes, 8, 2))) & 0x3fff;
+ if ($this->isMax()) {
+ $clockSeq = 0xffff;
+ } elseif ($this->isNil()) {
+ $clockSeq = 0x0000;
+ } else {
+ $clockSeq = hexdec(bin2hex(substr($this->bytes, 8, 2))) & 0x3fff;
+ }
return new Hexadecimal(str_pad(dechex($clockSeq), 4, '0', STR_PAD_LEFT));
}
@@ -126,66 +127,61 @@ final class Fields implements FieldsInterface
/**
* Returns the full 60-bit timestamp, without the version
*
- * For version 2 UUIDs, the time_low field is the local identifier and
- * should not be returned as part of the time. For this reason, we set the
- * bottom 32 bits of the timestamp to 0's. As a result, there is some loss
- * of fidelity of the timestamp, for version 2 UUIDs. The timestamp can be
- * off by a range of 0 to 429.4967295 seconds (or 7 minutes, 9 seconds, and
- * 496730 microseconds).
+ * For version 2 UUIDs, the time_low field is the local identifier and should not be returned as part of the time.
+ * For this reason, we set the bottom 32 bits of the timestamp to 0's. As a result, there is some loss of timestamp
+ * fidelity, for version 2 UUIDs. The timestamp can be off by a range of 0 to 429.4967295 seconds (or 7 minutes, 9
+ * seconds, and 496,730 microseconds).
*
- * For version 6 UUIDs, the timestamp order is reversed from the typical RFC
- * 4122 order (the time bits are in the correct bit order, so that it is
- * monotonically increasing). In returning the timestamp value, we put the
- * bits in the order: time_low + time_mid + time_hi.
+ * For version 6 UUIDs, the timestamp order is reversed from the typical RFC 9562 (formerly RFC 4122) order (the
+ * time bits are in the correct bit order, so that it is monotonically increasing). In returning the timestamp
+ * value, we put the bits in the order: time_low + time_mid + time_hi.
*/
public function getTimestamp(): Hexadecimal
{
- switch ($this->getVersion()) {
- case Uuid::UUID_TYPE_DCE_SECURITY:
- $timestamp = sprintf(
- '%03x%04s%08s',
- hexdec($this->getTimeHiAndVersion()->toString()) & 0x0fff,
- $this->getTimeMid()->toString(),
- ''
- );
-
- break;
- case Uuid::UUID_TYPE_PEABODY:
- $timestamp = sprintf(
- '%08s%04s%03x',
- $this->getTimeLow()->toString(),
- $this->getTimeMid()->toString(),
- hexdec($this->getTimeHiAndVersion()->toString()) & 0x0fff
- );
-
- break;
- default:
- $timestamp = sprintf(
- '%03x%04s%08s',
- hexdec($this->getTimeHiAndVersion()->toString()) & 0x0fff,
- $this->getTimeMid()->toString(),
- $this->getTimeLow()->toString()
- );
- }
-
- return new Hexadecimal($timestamp);
+ return new Hexadecimal(match ($this->getVersion()) {
+ Uuid::UUID_TYPE_DCE_SECURITY => sprintf(
+ '%03x%04s%08s',
+ hexdec($this->getTimeHiAndVersion()->toString()) & 0x0fff,
+ $this->getTimeMid()->toString(),
+ ''
+ ),
+ Uuid::UUID_TYPE_REORDERED_TIME => sprintf(
+ '%08s%04s%03x',
+ $this->getTimeLow()->toString(),
+ $this->getTimeMid()->toString(),
+ hexdec($this->getTimeHiAndVersion()->toString()) & 0x0fff
+ ),
+ // The Unix timestamp in version 7 UUIDs is a 48-bit number, but for consistency, we will return a 60-bit
+ // number, padded to the left with zeros.
+ Uuid::UUID_TYPE_UNIX_TIME => sprintf(
+ '%011s%04s',
+ $this->getTimeLow()->toString(),
+ $this->getTimeMid()->toString(),
+ ),
+ default => sprintf(
+ '%03x%04s%08s',
+ hexdec($this->getTimeHiAndVersion()->toString()) & 0x0fff,
+ $this->getTimeMid()->toString(),
+ $this->getTimeLow()->toString()
+ ),
+ });
}
public function getVersion(): ?int
{
- if ($this->isNil()) {
+ if ($this->isNil() || $this->isMax()) {
return null;
}
- /** @var array $parts */
+ /** @var int[] $parts */
$parts = unpack('n*', $this->bytes);
- return (int) $parts[4] >> 12;
+ return $parts[4] >> 12;
}
private function isCorrectVariant(): bool
{
- if ($this->isNil()) {
+ if ($this->isNil() || $this->isMax()) {
return true;
}
diff --git a/vendor/ramsey/uuid/src/Rfc4122/FieldsInterface.php b/vendor/ramsey/uuid/src/Rfc4122/FieldsInterface.php
index a303525..13d86d9 100644
--- a/vendor/ramsey/uuid/src/Rfc4122/FieldsInterface.php
+++ b/vendor/ramsey/uuid/src/Rfc4122/FieldsInterface.php
@@ -18,30 +18,30 @@ use Ramsey\Uuid\Fields\FieldsInterface as BaseFieldsInterface;
use Ramsey\Uuid\Type\Hexadecimal;
/**
- * RFC 4122 defines fields for a specific variant of UUID
+ * UUID fields, as defined by RFC 4122
+ *
+ * This interface defines the fields of an RFC 4122 variant UUID. Since RFC 9562 removed the concept of fields and
+ * instead defined layouts that are specific to a given version, this interface is a legacy artifact of the earlier, and
+ * now obsolete, RFC 4122.
*
* The fields of an RFC 4122 variant UUID are:
*
* * **time_low**: The low field of the timestamp, an unsigned 32-bit integer
* * **time_mid**: The middle field of the timestamp, an unsigned 16-bit integer
- * * **time_hi_and_version**: The high field of the timestamp multiplexed with
- * the version number, an unsigned 16-bit integer
- * * **clock_seq_hi_and_reserved**: The high field of the clock sequence
- * multiplexed with the variant, an unsigned 8-bit integer
- * * **clock_seq_low**: The low field of the clock sequence, an unsigned
- * 8-bit integer
- * * **node**: The spatially unique node identifier, an unsigned 48-bit
- * integer
+ * * **time_hi_and_version**: The high field of the timestamp multiplexed with the version number, an unsigned 16-bit integer
+ * * **clock_seq_hi_and_reserved**: The high field of the clock sequence multiplexed with the variant, an unsigned 8-bit integer
+ * * **clock_seq_low**: The low field of the clock sequence, an unsigned 8-bit integer
+ * * **node**: The spatially unique node identifier, an unsigned 48-bit integer
*
- * @link http://tools.ietf.org/html/rfc4122#section-4.1 RFC 4122, § 4.1: Format
+ * @link https://www.rfc-editor.org/rfc/rfc4122#section-4.1 RFC 4122, 4.1. Format
+ * @link https://www.rfc-editor.org/rfc/rfc9562#section-4 RFC 9562, 4. UUID Format
*
- * @psalm-immutable
+ * @immutable
*/
interface FieldsInterface extends BaseFieldsInterface
{
/**
- * Returns the full 16-bit clock sequence, with the variant bits (two most
- * significant bits) masked out
+ * Returns the full 16-bit clock sequence, with the variant bits (two most significant bits) masked out
*/
public function getClockSeq(): Hexadecimal;
@@ -83,44 +83,48 @@ interface FieldsInterface extends BaseFieldsInterface
/**
* Returns the variant
*
- * The variant number describes the layout of the UUID. The variant
- * number has the following meaning:
+ * The variant number describes the layout of the UUID. The variant number has the following meaning:
*
* - 0 - Reserved for NCS backward compatibility
- * - 2 - The RFC 4122 variant
+ * - 2 - The RFC 9562 (formerly RFC 4122) variant
* - 6 - Reserved, Microsoft Corporation backward compatibility
* - 7 - Reserved for future definition
*
- * For RFC 4122 variant UUIDs, this value should always be the integer `2`.
+ * For RFC 9562 (formerly RFC 4122) variant UUIDs, this value should always be the integer `2`.
*
- * @link http://tools.ietf.org/html/rfc4122#section-4.1.1 RFC 4122, § 4.1.1: Variant
+ * @link https://www.rfc-editor.org/rfc/rfc9562#section-4.1 RFC 9562, 4.1. Variant Field
*/
public function getVariant(): int;
/**
- * Returns the version
+ * Returns the UUID version
*
- * The version number describes how the UUID was generated and has the
- * following meaning:
+ * The version number describes how the UUID was generated and has the following meaning:
*
- * 1. Time-based UUID
+ * 1. Gregorian time UUID
* 2. DCE security UUID
* 3. Name-based UUID hashed with MD5
* 4. Randomly generated UUID
* 5. Name-based UUID hashed with SHA-1
+ * 6. Reordered Gregorian time UUID
+ * 7. Unix Epoch time UUID
+ * 8. Custom format UUID
*
- * This returns `null` if the UUID is not an RFC 4122 variant, since version
- * is only meaningful for this variant.
+ * This returns `null` if the UUID is not an RFC 9562 (formerly RFC 4122) variant, since the version is only
+ * meaningful for this variant.
*
- * @link http://tools.ietf.org/html/rfc4122#section-4.1.3 RFC 4122, § 4.1.3: Version
+ * @link https://www.rfc-editor.org/rfc/rfc9562#section-4.2 RFC 9562, 4.2. Version Field
+ *
+ * @pure
*/
public function getVersion(): ?int;
/**
* Returns true if these fields represent a nil UUID
*
- * The nil UUID is special form of UUID that is specified to have all 128
- * bits set to zero.
+ * The nil UUID is a special form of UUID that is specified to have all 128 bits set to zero.
+ *
+ * @pure
*/
public function isNil(): bool;
}
diff --git a/vendor/ramsey/uuid/src/Rfc4122/MaxTrait.php b/vendor/ramsey/uuid/src/Rfc4122/MaxTrait.php
new file mode 100644
index 0000000..8646e6a
--- /dev/null
+++ b/vendor/ramsey/uuid/src/Rfc4122/MaxTrait.php
@@ -0,0 +1,40 @@
+
+ * @license http://opensource.org/licenses/MIT MIT
+ */
+
+declare(strict_types=1);
+
+namespace Ramsey\Uuid\Rfc4122;
+
+/**
+ * Provides common functionality for max UUIDs
+ *
+ * @immutable
+ */
+trait MaxTrait
+{
+ /**
+ * Returns the bytes that comprise the fields
+ *
+ * @pure
+ */
+ abstract public function getBytes(): string;
+
+ /**
+ * Returns true if the byte string represents a max UUID
+ *
+ * @pure
+ */
+ public function isMax(): bool
+ {
+ return $this->getBytes() === "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff";
+ }
+}
diff --git a/vendor/ramsey/uuid/src/Rfc4122/MaxUuid.php b/vendor/ramsey/uuid/src/Rfc4122/MaxUuid.php
new file mode 100644
index 0000000..ac50bce
--- /dev/null
+++ b/vendor/ramsey/uuid/src/Rfc4122/MaxUuid.php
@@ -0,0 +1,28 @@
+
+ * @license http://opensource.org/licenses/MIT MIT
+ */
+
+declare(strict_types=1);
+
+namespace Ramsey\Uuid\Rfc4122;
+
+use Ramsey\Uuid\Uuid;
+
+/**
+ * The max UUID is a special form of UUID that has all 128 bits set to one (`1`)
+ *
+ * @link https://www.rfc-editor.org/rfc/rfc9562#section-5.10 RFC 9562, 5.10. Max UUID
+ *
+ * @immutable
+ */
+final class MaxUuid extends Uuid implements UuidInterface
+{
+}
diff --git a/vendor/ramsey/uuid/src/Rfc4122/NilTrait.php b/vendor/ramsey/uuid/src/Rfc4122/NilTrait.php
index 9a9774d..19d1377 100644
--- a/vendor/ramsey/uuid/src/Rfc4122/NilTrait.php
+++ b/vendor/ramsey/uuid/src/Rfc4122/NilTrait.php
@@ -17,17 +17,14 @@ namespace Ramsey\Uuid\Rfc4122;
/**
* Provides common functionality for nil UUIDs
*
- * The nil UUID is special form of UUID that is specified to have all 128 bits
- * set to zero.
- *
- * @link https://tools.ietf.org/html/rfc4122#section-4.1.7 RFC 4122, § 4.1.7: Nil UUID
- *
- * @psalm-immutable
+ * @immutable
*/
trait NilTrait
{
/**
* Returns the bytes that comprise the fields
+ *
+ * @pure
*/
abstract public function getBytes(): string;
diff --git a/vendor/ramsey/uuid/src/Rfc4122/NilUuid.php b/vendor/ramsey/uuid/src/Rfc4122/NilUuid.php
index c49b994..a139de7 100644
--- a/vendor/ramsey/uuid/src/Rfc4122/NilUuid.php
+++ b/vendor/ramsey/uuid/src/Rfc4122/NilUuid.php
@@ -17,10 +17,11 @@ namespace Ramsey\Uuid\Rfc4122;
use Ramsey\Uuid\Uuid;
/**
- * The nil UUID is special form of UUID that is specified to have all 128 bits
- * set to zero
+ * The nil UUID is a special form of UUID that has all 128 bits set to zero (`0`)
*
- * @psalm-immutable
+ * @link https://www.rfc-editor.org/rfc/rfc9562#section-5.9 RFC 9562, 5.9. Nil UUID
+ *
+ * @immutable
*/
final class NilUuid extends Uuid implements UuidInterface
{
diff --git a/vendor/ramsey/uuid/src/Rfc4122/TimeTrait.php b/vendor/ramsey/uuid/src/Rfc4122/TimeTrait.php
new file mode 100644
index 0000000..c468c9b
--- /dev/null
+++ b/vendor/ramsey/uuid/src/Rfc4122/TimeTrait.php
@@ -0,0 +1,53 @@
+
+ * @license http://opensource.org/licenses/MIT MIT
+ */
+
+declare(strict_types=1);
+
+namespace Ramsey\Uuid\Rfc4122;
+
+use DateTimeImmutable;
+use DateTimeInterface;
+use Ramsey\Uuid\Exception\DateTimeException;
+use Throwable;
+
+use function str_pad;
+
+use const STR_PAD_LEFT;
+
+/**
+ * Provides common functionality for getting the time from a time-based UUID
+ *
+ * @immutable
+ */
+trait TimeTrait
+{
+ /**
+ * Returns a DateTimeInterface object representing the timestamp associated with the UUID
+ *
+ * @return DateTimeImmutable A PHP DateTimeImmutable instance representing the timestamp of a time-based UUID
+ */
+ public function getDateTime(): DateTimeInterface
+ {
+ $time = $this->timeConverter->convertTime($this->fields->getTimestamp());
+
+ try {
+ return new DateTimeImmutable(
+ '@'
+ . $time->getSeconds()->toString()
+ . '.'
+ . str_pad($time->getMicroseconds()->toString(), 6, '0', STR_PAD_LEFT)
+ );
+ } catch (Throwable $e) {
+ throw new DateTimeException($e->getMessage(), (int) $e->getCode(), $e);
+ }
+ }
+}
diff --git a/vendor/ramsey/uuid/src/Rfc4122/UuidBuilder.php b/vendor/ramsey/uuid/src/Rfc4122/UuidBuilder.php
index 736931a..787a0b7 100644
--- a/vendor/ramsey/uuid/src/Rfc4122/UuidBuilder.php
+++ b/vendor/ramsey/uuid/src/Rfc4122/UuidBuilder.php
@@ -17,45 +17,40 @@ namespace Ramsey\Uuid\Rfc4122;
use Ramsey\Uuid\Builder\UuidBuilderInterface;
use Ramsey\Uuid\Codec\CodecInterface;
use Ramsey\Uuid\Converter\NumberConverterInterface;
+use Ramsey\Uuid\Converter\Time\UnixTimeConverter;
use Ramsey\Uuid\Converter\TimeConverterInterface;
use Ramsey\Uuid\Exception\UnableToBuildUuidException;
use Ramsey\Uuid\Exception\UnsupportedOperationException;
-use Ramsey\Uuid\Nonstandard\UuidV6;
+use Ramsey\Uuid\Math\BrickMathCalculator;
use Ramsey\Uuid\Rfc4122\UuidInterface as Rfc4122UuidInterface;
+use Ramsey\Uuid\Uuid;
use Ramsey\Uuid\UuidInterface;
use Throwable;
/**
- * UuidBuilder builds instances of RFC 4122 UUIDs
+ * UuidBuilder builds instances of RFC 9562 (formerly 4122) UUIDs
*
- * @psalm-immutable
+ * @immutable
*/
class UuidBuilder implements UuidBuilderInterface
{
- /**
- * @var NumberConverterInterface
- */
- private $numberConverter;
-
- /**
- * @var TimeConverterInterface
- */
- private $timeConverter;
+ private TimeConverterInterface $unixTimeConverter;
/**
* Constructs the DefaultUuidBuilder
*
- * @param NumberConverterInterface $numberConverter The number converter to
- * use when constructing the Uuid
- * @param TimeConverterInterface $timeConverter The time converter to use
- * for converting timestamps extracted from a UUID to Unix timestamps
+ * @param NumberConverterInterface $numberConverter The number converter to use when constructing the Uuid
+ * @param TimeConverterInterface $timeConverter The time converter to use for converting Gregorian time extracted
+ * from version 1, 2, and 6 UUIDs to Unix timestamps
+ * @param TimeConverterInterface | null $unixTimeConverter The time converter to use for converter Unix Epoch time
+ * extracted from version 7 UUIDs to Unix timestamps
*/
public function __construct(
- NumberConverterInterface $numberConverter,
- TimeConverterInterface $timeConverter
+ private NumberConverterInterface $numberConverter,
+ private TimeConverterInterface $timeConverter,
+ ?TimeConverterInterface $unixTimeConverter = null,
) {
- $this->numberConverter = $numberConverter;
- $this->timeConverter = $timeConverter;
+ $this->unixTimeConverter = $unixTimeConverter ?? new UnixTimeConverter(new BrickMathCalculator());
}
/**
@@ -66,46 +61,62 @@ class UuidBuilder implements UuidBuilderInterface
*
* @return Rfc4122UuidInterface UuidBuilder returns instances of Rfc4122UuidInterface
*
- * @psalm-pure
+ * @pure
*/
public function build(CodecInterface $codec, string $bytes): UuidInterface
{
try {
+ /** @var Fields $fields */
$fields = $this->buildFields($bytes);
if ($fields->isNil()) {
+ /** @phpstan-ignore possiblyImpure.new */
return new NilUuid($fields, $this->numberConverter, $codec, $this->timeConverter);
}
- switch ($fields->getVersion()) {
- case 1:
- return new UuidV1($fields, $this->numberConverter, $codec, $this->timeConverter);
- case 2:
- return new UuidV2($fields, $this->numberConverter, $codec, $this->timeConverter);
- case 3:
- return new UuidV3($fields, $this->numberConverter, $codec, $this->timeConverter);
- case 4:
- return new UuidV4($fields, $this->numberConverter, $codec, $this->timeConverter);
- case 5:
- return new UuidV5($fields, $this->numberConverter, $codec, $this->timeConverter);
- case 6:
- return new UuidV6($fields, $this->numberConverter, $codec, $this->timeConverter);
+ if ($fields->isMax()) {
+ /** @phpstan-ignore possiblyImpure.new */
+ return new MaxUuid($fields, $this->numberConverter, $codec, $this->timeConverter);
}
- throw new UnsupportedOperationException(
- 'The UUID version in the given fields is not supported '
- . 'by this UUID builder'
- );
+ return match ($fields->getVersion()) {
+ /** @phpstan-ignore possiblyImpure.new */
+ Uuid::UUID_TYPE_TIME => new UuidV1($fields, $this->numberConverter, $codec, $this->timeConverter),
+ Uuid::UUID_TYPE_DCE_SECURITY
+ /** @phpstan-ignore possiblyImpure.new */
+ => new UuidV2($fields, $this->numberConverter, $codec, $this->timeConverter),
+ /** @phpstan-ignore possiblyImpure.new */
+ Uuid::UUID_TYPE_HASH_MD5 => new UuidV3($fields, $this->numberConverter, $codec, $this->timeConverter),
+ /** @phpstan-ignore possiblyImpure.new */
+ Uuid::UUID_TYPE_RANDOM => new UuidV4($fields, $this->numberConverter, $codec, $this->timeConverter),
+ /** @phpstan-ignore possiblyImpure.new */
+ Uuid::UUID_TYPE_HASH_SHA1 => new UuidV5($fields, $this->numberConverter, $codec, $this->timeConverter),
+ Uuid::UUID_TYPE_REORDERED_TIME
+ /** @phpstan-ignore possiblyImpure.new */
+ => new UuidV6($fields, $this->numberConverter, $codec, $this->timeConverter),
+ Uuid::UUID_TYPE_UNIX_TIME
+ /** @phpstan-ignore possiblyImpure.new */
+ => new UuidV7($fields, $this->numberConverter, $codec, $this->unixTimeConverter),
+ /** @phpstan-ignore possiblyImpure.new */
+ Uuid::UUID_TYPE_CUSTOM => new UuidV8($fields, $this->numberConverter, $codec, $this->timeConverter),
+ default => throw new UnsupportedOperationException(
+ 'The UUID version in the given fields is not supported by this UUID builder',
+ ),
+ };
} catch (Throwable $e) {
+ /** @phpstan-ignore possiblyImpure.methodCall, possiblyImpure.methodCall */
throw new UnableToBuildUuidException($e->getMessage(), (int) $e->getCode(), $e);
}
}
/**
- * Proxy method to allow injecting a mock, for testing
+ * Proxy method to allow injecting a mock for testing
+ *
+ * @pure
*/
protected function buildFields(string $bytes): FieldsInterface
{
+ /** @phpstan-ignore possiblyImpure.new */
return new Fields($bytes);
}
}
diff --git a/vendor/ramsey/uuid/src/Rfc4122/UuidInterface.php b/vendor/ramsey/uuid/src/Rfc4122/UuidInterface.php
index 3e4d9fa..5918306 100644
--- a/vendor/ramsey/uuid/src/Rfc4122/UuidInterface.php
+++ b/vendor/ramsey/uuid/src/Rfc4122/UuidInterface.php
@@ -17,20 +17,12 @@ namespace Ramsey\Uuid\Rfc4122;
use Ramsey\Uuid\UuidInterface as BaseUuidInterface;
/**
- * Also known as a Leach-Salz variant UUID, an RFC 4122 variant UUID is a
- * universally unique identifier defined by RFC 4122
+ * A universally unique identifier (UUID), as defined in RFC 9562 (formerly RFC 4122)
*
- * @link https://tools.ietf.org/html/rfc4122 RFC 4122
+ * @link https://www.rfc-editor.org/rfc/rfc9562 RFC 9562
*
- * @psalm-immutable
+ * @immutable
*/
interface UuidInterface extends BaseUuidInterface
{
- /**
- * Returns the string standard representation of the UUID as a URN
- *
- * @link http://en.wikipedia.org/wiki/Uniform_Resource_Name Uniform Resource Name
- * @link https://tools.ietf.org/html/rfc4122#section-3 RFC 4122, § 3: Namespace Registration Template
- */
- public function getUrn(): string;
}
diff --git a/vendor/ramsey/uuid/src/Rfc4122/UuidV1.php b/vendor/ramsey/uuid/src/Rfc4122/UuidV1.php
index 764e42f..df2af6f 100644
--- a/vendor/ramsey/uuid/src/Rfc4122/UuidV1.php
+++ b/vendor/ramsey/uuid/src/Rfc4122/UuidV1.php
@@ -14,79 +14,45 @@ declare(strict_types=1);
namespace Ramsey\Uuid\Rfc4122;
-use DateTimeImmutable;
-use DateTimeInterface;
use Ramsey\Uuid\Codec\CodecInterface;
use Ramsey\Uuid\Converter\NumberConverterInterface;
use Ramsey\Uuid\Converter\TimeConverterInterface;
-use Ramsey\Uuid\Exception\DateTimeException;
use Ramsey\Uuid\Exception\InvalidArgumentException;
use Ramsey\Uuid\Rfc4122\FieldsInterface as Rfc4122FieldsInterface;
use Ramsey\Uuid\Uuid;
-use Throwable;
-
-use function str_pad;
-
-use const STR_PAD_LEFT;
/**
- * Time-based, or version 1, UUIDs include timestamp, clock sequence, and node
- * values that are combined into a 128-bit unsigned integer
+ * Gregorian time, or version 1, UUIDs include timestamp, clock sequence, and node values, combined into a 128-bit unsigned integer
*
- * @psalm-immutable
+ * @link https://www.rfc-editor.org/rfc/rfc9562#section-5.1 RFC 9562, 5.1. UUID Version 1
+ *
+ * @immutable
*/
final class UuidV1 extends Uuid implements UuidInterface
{
+ use TimeTrait;
+
/**
- * Creates a version 1 (time-based) UUID
+ * Creates a version 1 (Gregorian time) UUID
*
* @param Rfc4122FieldsInterface $fields The fields from which to construct a UUID
- * @param NumberConverterInterface $numberConverter The number converter to use
- * for converting hex values to/from integers
- * @param CodecInterface $codec The codec to use when encoding or decoding
- * UUID strings
- * @param TimeConverterInterface $timeConverter The time converter to use
- * for converting timestamps extracted from a UUID to unix timestamps
+ * @param NumberConverterInterface $numberConverter The number converter to use for converting hex values to/from integers
+ * @param CodecInterface $codec The codec to use when encoding or decoding UUID strings
+ * @param TimeConverterInterface $timeConverter The time converter to use for converting timestamps extracted from a
+ * UUID to unix timestamps
*/
public function __construct(
Rfc4122FieldsInterface $fields,
NumberConverterInterface $numberConverter,
CodecInterface $codec,
- TimeConverterInterface $timeConverter
+ TimeConverterInterface $timeConverter,
) {
if ($fields->getVersion() !== Uuid::UUID_TYPE_TIME) {
throw new InvalidArgumentException(
- 'Fields used to create a UuidV1 must represent a '
- . 'version 1 (time-based) UUID'
+ 'Fields used to create a UuidV1 must represent a version 1 (time-based) UUID',
);
}
parent::__construct($fields, $numberConverter, $codec, $timeConverter);
}
-
- /**
- * Returns a DateTimeInterface object representing the timestamp associated
- * with the UUID
- *
- * The timestamp value is only meaningful in a time-based UUID, which
- * has version type 1.
- *
- * @return DateTimeImmutable A PHP DateTimeImmutable instance representing
- * the timestamp of a version 1 UUID
- */
- public function getDateTime(): DateTimeInterface
- {
- $time = $this->timeConverter->convertTime($this->fields->getTimestamp());
-
- try {
- return new DateTimeImmutable(
- '@'
- . $time->getSeconds()->toString()
- . '.'
- . str_pad($time->getMicroseconds()->toString(), 6, '0', STR_PAD_LEFT)
- );
- } catch (Throwable $e) {
- throw new DateTimeException($e->getMessage(), (int) $e->getCode(), $e);
- }
- }
}
diff --git a/vendor/ramsey/uuid/src/Rfc4122/UuidV2.php b/vendor/ramsey/uuid/src/Rfc4122/UuidV2.php
index 74906f0..c3417d7 100644
--- a/vendor/ramsey/uuid/src/Rfc4122/UuidV2.php
+++ b/vendor/ramsey/uuid/src/Rfc4122/UuidV2.php
@@ -14,28 +14,30 @@ declare(strict_types=1);
namespace Ramsey\Uuid\Rfc4122;
-use DateTimeImmutable;
-use DateTimeInterface;
use Ramsey\Uuid\Codec\CodecInterface;
use Ramsey\Uuid\Converter\NumberConverterInterface;
use Ramsey\Uuid\Converter\TimeConverterInterface;
-use Ramsey\Uuid\Exception\DateTimeException;
use Ramsey\Uuid\Exception\InvalidArgumentException;
use Ramsey\Uuid\Rfc4122\FieldsInterface as Rfc4122FieldsInterface;
use Ramsey\Uuid\Type\Integer as IntegerObject;
use Ramsey\Uuid\Uuid;
-use Throwable;
use function hexdec;
-use function str_pad;
-
-use const STR_PAD_LEFT;
/**
- * DCE Security version, or version 2, UUIDs include local domain identifier,
- * local ID for the specified domain, and node values that are combined into a
- * 128-bit unsigned integer
+ * DCE Security version, or version 2, UUIDs include local domain identifier, local ID for the specified domain, and
+ * node values that are combined into a 128-bit unsigned integer
*
+ * It is important to note that a version 2 UUID suffers from some loss of timestamp fidelity, due to replacing the
+ * time_low field with the local identifier. When constructing the timestamp value for date purposes, we replace the
+ * local identifier bits with zeros. As a result, the timestamp can be off by a range of 0 to 429.4967295 seconds (or 7
+ * minutes, 9 seconds, and 496,730 microseconds).
+ *
+ * Astute observers might note this value directly corresponds to `2^32-1`, or `0xffffffff`. The local identifier is
+ * 32-bits, and we have set each of these bits to `0`, so the maximum range of timestamp drift is `0x00000000` to
+ * `0xffffffff` (counted in 100-nanosecond intervals).
+ *
+ * @link https://www.rfc-editor.org/rfc/rfc9562#section-5.2 RFC 9562, 5.2. UUID Version 2
* @link https://publications.opengroup.org/c311 DCE 1.1: Authentication and Security Services
* @link https://publications.opengroup.org/c706 DCE 1.1: Remote Procedure Call
* @link https://pubs.opengroup.org/onlinepubs/9696989899/chap5.htm#tagcjh_08_02_01_01 DCE 1.1: Auth & Sec, §5.2.1.1
@@ -43,72 +45,36 @@ use const STR_PAD_LEFT;
* @link https://pubs.opengroup.org/onlinepubs/9629399/apdxa.htm DCE 1.1: RPC, Appendix A
* @link https://github.com/google/uuid Go package for UUIDs (includes DCE implementation)
*
- * @psalm-immutable
+ * @immutable
*/
final class UuidV2 extends Uuid implements UuidInterface
{
+ use TimeTrait;
+
/**
* Creates a version 2 (DCE Security) UUID
*
* @param Rfc4122FieldsInterface $fields The fields from which to construct a UUID
- * @param NumberConverterInterface $numberConverter The number converter to use
- * for converting hex values to/from integers
- * @param CodecInterface $codec The codec to use when encoding or decoding
- * UUID strings
- * @param TimeConverterInterface $timeConverter The time converter to use
- * for converting timestamps extracted from a UUID to unix timestamps
+ * @param NumberConverterInterface $numberConverter The number converter to use for converting hex values to/from integers
+ * @param CodecInterface $codec The codec to use when encoding or decoding UUID strings
+ * @param TimeConverterInterface $timeConverter The time converter to use for converting timestamps extracted from a
+ * UUID to unix timestamps
*/
public function __construct(
Rfc4122FieldsInterface $fields,
NumberConverterInterface $numberConverter,
CodecInterface $codec,
- TimeConverterInterface $timeConverter
+ TimeConverterInterface $timeConverter,
) {
if ($fields->getVersion() !== Uuid::UUID_TYPE_DCE_SECURITY) {
throw new InvalidArgumentException(
- 'Fields used to create a UuidV2 must represent a '
- . 'version 2 (DCE Security) UUID'
+ 'Fields used to create a UuidV2 must represent a version 2 (DCE Security) UUID'
);
}
parent::__construct($fields, $numberConverter, $codec, $timeConverter);
}
- /**
- * Returns a DateTimeInterface object representing the timestamp associated
- * with the UUID
- *
- * It is important to note that a version 2 UUID suffers from some loss of
- * fidelity of the timestamp, due to replacing the time_low field with the
- * local identifier. When constructing the timestamp value for date
- * purposes, we replace the local identifier bits with zeros. As a result,
- * the timestamp can be off by a range of 0 to 429.4967295 seconds (or 7
- * minutes, 9 seconds, and 496730 microseconds).
- *
- * Astute observers might note this value directly corresponds to 2^32 - 1,
- * or 0xffffffff. The local identifier is 32-bits, and we have set each of
- * these bits to 0, so the maximum range of timestamp drift is 0x00000000
- * to 0xffffffff (counted in 100-nanosecond intervals).
- *
- * @return DateTimeImmutable A PHP DateTimeImmutable instance representing
- * the timestamp of a version 2 UUID
- */
- public function getDateTime(): DateTimeInterface
- {
- $time = $this->timeConverter->convertTime($this->fields->getTimestamp());
-
- try {
- return new DateTimeImmutable(
- '@'
- . $time->getSeconds()->toString()
- . '.'
- . str_pad($time->getMicroseconds()->toString(), 6, '0', STR_PAD_LEFT)
- );
- } catch (Throwable $e) {
- throw new DateTimeException($e->getMessage(), (int) $e->getCode(), $e);
- }
- }
-
/**
* Returns the local domain used to create this version 2 UUID
*/
@@ -136,8 +102,6 @@ final class UuidV2 extends Uuid implements UuidInterface
/** @var Rfc4122FieldsInterface $fields */
$fields = $this->getFields();
- return new IntegerObject(
- $this->numberConverter->fromHex($fields->getTimeLow()->toString())
- );
+ return new IntegerObject($this->numberConverter->fromHex($fields->getTimeLow()->toString()));
}
}
diff --git a/vendor/ramsey/uuid/src/Rfc4122/UuidV3.php b/vendor/ramsey/uuid/src/Rfc4122/UuidV3.php
index deaa54e..1b065e2 100644
--- a/vendor/ramsey/uuid/src/Rfc4122/UuidV3.php
+++ b/vendor/ramsey/uuid/src/Rfc4122/UuidV3.php
@@ -22,10 +22,12 @@ use Ramsey\Uuid\Rfc4122\FieldsInterface as Rfc4122FieldsInterface;
use Ramsey\Uuid\Uuid;
/**
- * Version 3 UUIDs are named-based, using combination of a namespace and name
- * that are hashed into a 128-bit unsigned integer using MD5
+ * Version 3 UUIDs are named-based, using a combination of a namespace and name that are hashed into a 128-bit unsigned
+ * integer using the MD5 hashing algorithm
*
- * @psalm-immutable
+ * @link https://www.rfc-editor.org/rfc/rfc9562#section-5.3 RFC 9562, 5.3. UUID Version 3
+ *
+ * @immutable
*/
final class UuidV3 extends Uuid implements UuidInterface
{
@@ -33,23 +35,20 @@ final class UuidV3 extends Uuid implements UuidInterface
* Creates a version 3 (name-based, MD5-hashed) UUID
*
* @param Rfc4122FieldsInterface $fields The fields from which to construct a UUID
- * @param NumberConverterInterface $numberConverter The number converter to use
- * for converting hex values to/from integers
- * @param CodecInterface $codec The codec to use when encoding or decoding
- * UUID strings
- * @param TimeConverterInterface $timeConverter The time converter to use
- * for converting timestamps extracted from a UUID to unix timestamps
+ * @param NumberConverterInterface $numberConverter The number converter to use for converting hex values to/from integers
+ * @param CodecInterface $codec The codec to use when encoding or decoding UUID strings
+ * @param TimeConverterInterface $timeConverter The time converter to use for converting timestamps extracted from a
+ * UUID to unix timestamps
*/
public function __construct(
Rfc4122FieldsInterface $fields,
NumberConverterInterface $numberConverter,
CodecInterface $codec,
- TimeConverterInterface $timeConverter
+ TimeConverterInterface $timeConverter,
) {
if ($fields->getVersion() !== Uuid::UUID_TYPE_HASH_MD5) {
throw new InvalidArgumentException(
- 'Fields used to create a UuidV3 must represent a '
- . 'version 3 (name-based, MD5-hashed) UUID'
+ 'Fields used to create a UuidV3 must represent a version 3 (name-based, MD5-hashed) UUID',
);
}
diff --git a/vendor/ramsey/uuid/src/Rfc4122/UuidV4.php b/vendor/ramsey/uuid/src/Rfc4122/UuidV4.php
index 2e57246..e28ddc3 100644
--- a/vendor/ramsey/uuid/src/Rfc4122/UuidV4.php
+++ b/vendor/ramsey/uuid/src/Rfc4122/UuidV4.php
@@ -22,10 +22,11 @@ use Ramsey\Uuid\Rfc4122\FieldsInterface as Rfc4122FieldsInterface;
use Ramsey\Uuid\Uuid;
/**
- * Random, or version 4, UUIDs are randomly or pseudo-randomly generated 128-bit
- * integers
+ * Random, or version 4, UUIDs are randomly or pseudo-randomly generated 128-bit integers
*
- * @psalm-immutable
+ * @link https://www.rfc-editor.org/rfc/rfc9562#section-5.4 RFC 9562, 5.4. UUID Version 4
+ *
+ * @immutable
*/
final class UuidV4 extends Uuid implements UuidInterface
{
@@ -33,23 +34,20 @@ final class UuidV4 extends Uuid implements UuidInterface
* Creates a version 4 (random) UUID
*
* @param Rfc4122FieldsInterface $fields The fields from which to construct a UUID
- * @param NumberConverterInterface $numberConverter The number converter to use
- * for converting hex values to/from integers
- * @param CodecInterface $codec The codec to use when encoding or decoding
- * UUID strings
- * @param TimeConverterInterface $timeConverter The time converter to use
- * for converting timestamps extracted from a UUID to unix timestamps
+ * @param NumberConverterInterface $numberConverter The number converter to use for converting hex values to/from integers
+ * @param CodecInterface $codec The codec to use when encoding or decoding UUID strings
+ * @param TimeConverterInterface $timeConverter The time converter to use for converting timestamps extracted from a
+ * UUID to unix timestamps
*/
public function __construct(
Rfc4122FieldsInterface $fields,
NumberConverterInterface $numberConverter,
CodecInterface $codec,
- TimeConverterInterface $timeConverter
+ TimeConverterInterface $timeConverter,
) {
if ($fields->getVersion() !== Uuid::UUID_TYPE_RANDOM) {
throw new InvalidArgumentException(
- 'Fields used to create a UuidV4 must represent a '
- . 'version 4 (random) UUID'
+ 'Fields used to create a UuidV4 must represent a version 4 (random) UUID',
);
}
diff --git a/vendor/ramsey/uuid/src/Rfc4122/UuidV5.php b/vendor/ramsey/uuid/src/Rfc4122/UuidV5.php
index 2ef6ab3..be43908 100644
--- a/vendor/ramsey/uuid/src/Rfc4122/UuidV5.php
+++ b/vendor/ramsey/uuid/src/Rfc4122/UuidV5.php
@@ -22,10 +22,12 @@ use Ramsey\Uuid\Rfc4122\FieldsInterface as Rfc4122FieldsInterface;
use Ramsey\Uuid\Uuid;
/**
- * Version 5 UUIDs are named-based, using combination of a namespace and name
- * that are hashed into a 128-bit unsigned integer using SHA1
+ * Version 5 UUIDs are named-based, using a combination of a namespace and name that are hashed into a 128-bit unsigned
+ * integer using the SHA1 hashing algorithm
*
- * @psalm-immutable
+ * @link https://www.rfc-editor.org/rfc/rfc9562#section-5.5 RFC 9562, 5.5. UUID Version 5
+ *
+ * @immutable
*/
final class UuidV5 extends Uuid implements UuidInterface
{
@@ -33,23 +35,20 @@ final class UuidV5 extends Uuid implements UuidInterface
* Creates a version 5 (name-based, SHA1-hashed) UUID
*
* @param Rfc4122FieldsInterface $fields The fields from which to construct a UUID
- * @param NumberConverterInterface $numberConverter The number converter to use
- * for converting hex values to/from integers
- * @param CodecInterface $codec The codec to use when encoding or decoding
- * UUID strings
- * @param TimeConverterInterface $timeConverter The time converter to use
- * for converting timestamps extracted from a UUID to unix timestamps
+ * @param NumberConverterInterface $numberConverter The number converter to use for converting hex values to/from integers
+ * @param CodecInterface $codec The codec to use when encoding or decoding UUID strings
+ * @param TimeConverterInterface $timeConverter The time converter to use for converting timestamps extracted from a
+ * UUID to unix timestamps
*/
public function __construct(
Rfc4122FieldsInterface $fields,
NumberConverterInterface $numberConverter,
CodecInterface $codec,
- TimeConverterInterface $timeConverter
+ TimeConverterInterface $timeConverter,
) {
if ($fields->getVersion() !== Uuid::UUID_TYPE_HASH_SHA1) {
throw new InvalidArgumentException(
- 'Fields used to create a UuidV5 must represent a '
- . 'version 5 (named-based, SHA1-hashed) UUID'
+ 'Fields used to create a UuidV5 must represent a version 5 (named-based, SHA1-hashed) UUID',
);
}
diff --git a/vendor/ramsey/uuid/src/Rfc4122/UuidV6.php b/vendor/ramsey/uuid/src/Rfc4122/UuidV6.php
new file mode 100644
index 0000000..3ae4ffc
--- /dev/null
+++ b/vendor/ramsey/uuid/src/Rfc4122/UuidV6.php
@@ -0,0 +1,29 @@
+
+ * @license http://opensource.org/licenses/MIT MIT
+ */
+
+declare(strict_types=1);
+
+namespace Ramsey\Uuid\Rfc4122;
+
+use Ramsey\Uuid\Nonstandard\UuidV6 as NonstandardUuidV6;
+
+/**
+ * Reordered Gregorian time, or version 6, UUIDs include timestamp, clock sequence, and node values that are combined
+ * into a 128-bit unsigned integer
+ *
+ * @link https://www.rfc-editor.org/rfc/rfc9562#section-5.6 RFC 9562, 5.6. UUID Version 6
+ *
+ * @immutable
+ */
+final class UuidV6 extends NonstandardUuidV6 implements UuidInterface
+{
+}
diff --git a/vendor/ramsey/uuid/src/Rfc4122/UuidV7.php b/vendor/ramsey/uuid/src/Rfc4122/UuidV7.php
new file mode 100644
index 0000000..1f2f4b5
--- /dev/null
+++ b/vendor/ramsey/uuid/src/Rfc4122/UuidV7.php
@@ -0,0 +1,58 @@
+
+ * @license http://opensource.org/licenses/MIT MIT
+ */
+
+declare(strict_types=1);
+
+namespace Ramsey\Uuid\Rfc4122;
+
+use Ramsey\Uuid\Codec\CodecInterface;
+use Ramsey\Uuid\Converter\NumberConverterInterface;
+use Ramsey\Uuid\Converter\TimeConverterInterface;
+use Ramsey\Uuid\Exception\InvalidArgumentException;
+use Ramsey\Uuid\Rfc4122\FieldsInterface as Rfc4122FieldsInterface;
+use Ramsey\Uuid\Uuid;
+
+/**
+ * Unix Epoch time, or version 7, UUIDs include a timestamp in milliseconds since the Unix Epoch, along with random bytes
+ *
+ * @link https://www.rfc-editor.org/rfc/rfc9562#section-5.7 RFC 9562, 5.7. UUID Version 7
+ *
+ * @immutable
+ */
+final class UuidV7 extends Uuid implements UuidInterface
+{
+ use TimeTrait;
+
+ /**
+ * Creates a version 7 (Unix Epoch time) UUID
+ *
+ * @param Rfc4122FieldsInterface $fields The fields from which to construct a UUID
+ * @param NumberConverterInterface $numberConverter The number converter to use for converting hex values to/from integers
+ * @param CodecInterface $codec The codec to use when encoding or decoding UUID strings
+ * @param TimeConverterInterface $timeConverter The time converter to use for converting timestamps extracted from a
+ * UUID to unix timestamps
+ */
+ public function __construct(
+ Rfc4122FieldsInterface $fields,
+ NumberConverterInterface $numberConverter,
+ CodecInterface $codec,
+ TimeConverterInterface $timeConverter,
+ ) {
+ if ($fields->getVersion() !== Uuid::UUID_TYPE_UNIX_TIME) {
+ throw new InvalidArgumentException(
+ 'Fields used to create a UuidV7 must represent a version 7 (Unix Epoch time) UUID',
+ );
+ }
+
+ parent::__construct($fields, $numberConverter, $codec, $timeConverter);
+ }
+}
diff --git a/vendor/ramsey/uuid/src/Rfc4122/UuidV8.php b/vendor/ramsey/uuid/src/Rfc4122/UuidV8.php
new file mode 100644
index 0000000..ea57ec2
--- /dev/null
+++ b/vendor/ramsey/uuid/src/Rfc4122/UuidV8.php
@@ -0,0 +1,60 @@
+
+ * @license http://opensource.org/licenses/MIT MIT
+ */
+
+declare(strict_types=1);
+
+namespace Ramsey\Uuid\Rfc4122;
+
+use Ramsey\Uuid\Codec\CodecInterface;
+use Ramsey\Uuid\Converter\NumberConverterInterface;
+use Ramsey\Uuid\Converter\TimeConverterInterface;
+use Ramsey\Uuid\Exception\InvalidArgumentException;
+use Ramsey\Uuid\Rfc4122\FieldsInterface as Rfc4122FieldsInterface;
+use Ramsey\Uuid\Uuid;
+
+/**
+ * Custom format, or version 8, UUIDs provide an RFC-compatible format for experimental or vendor-specific uses
+ *
+ * The only requirement for version 8 UUIDs is that the version and variant bits must be set. Otherwise, implementations
+ * are free to set the other bits according to their needs. As a result, the uniqueness of version 8 UUIDs is
+ * implementation-specific and should not be assumed.
+ *
+ * @link https://www.rfc-editor.org/rfc/rfc9562#section-5.8 RFC 9562, 5.8. UUID Version 8
+ *
+ * @immutable
+ */
+final class UuidV8 extends Uuid implements UuidInterface
+{
+ /**
+ * Creates a version 8 (custom format) UUID
+ *
+ * @param Rfc4122FieldsInterface $fields The fields from which to construct a UUID
+ * @param NumberConverterInterface $numberConverter The number converter to use for converting hex values to/from integers
+ * @param CodecInterface $codec The codec to use when encoding or decoding UUID strings
+ * @param TimeConverterInterface $timeConverter The time converter to use for converting timestamps extracted from a
+ * UUID to unix timestamps
+ */
+ public function __construct(
+ Rfc4122FieldsInterface $fields,
+ NumberConverterInterface $numberConverter,
+ CodecInterface $codec,
+ TimeConverterInterface $timeConverter,
+ ) {
+ if ($fields->getVersion() !== Uuid::UUID_TYPE_CUSTOM) {
+ throw new InvalidArgumentException(
+ 'Fields used to create a UuidV8 must represent a version 8 (custom format) UUID',
+ );
+ }
+
+ parent::__construct($fields, $numberConverter, $codec, $timeConverter);
+ }
+}
diff --git a/vendor/ramsey/uuid/src/Rfc4122/Validator.php b/vendor/ramsey/uuid/src/Rfc4122/Validator.php
index ed43c98..1736286 100644
--- a/vendor/ramsey/uuid/src/Rfc4122/Validator.php
+++ b/vendor/ramsey/uuid/src/Rfc4122/Validator.php
@@ -21,19 +21,17 @@ use function preg_match;
use function str_replace;
/**
- * Rfc4122\Validator validates strings as UUIDs of the RFC 4122 variant
+ * Rfc4122\Validator validates strings as UUIDs of the RFC 9562 (formerly RFC 4122) variant
*
- * @psalm-immutable
+ * @immutable
*/
final class Validator implements ValidatorInterface
{
private const VALID_PATTERN = '\A[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-'
- . '[1-5]{1}[0-9A-Fa-f]{3}-[ABab89]{1}[0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}\z';
+ . '[1-8][0-9A-Fa-f]{3}-[ABab89][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}\z';
/**
- * @psalm-return non-empty-string
- * @psalm-suppress MoreSpecificReturnType we know that the retrieved `string` is never empty
- * @psalm-suppress LessSpecificReturnStatement we know that the retrieved `string` is never empty
+ * @return non-empty-string
*/
public function getPattern(): string
{
@@ -42,8 +40,10 @@ final class Validator implements ValidatorInterface
public function validate(string $uuid): bool
{
- $uuid = str_replace(['urn:', 'uuid:', 'URN:', 'UUID:', '{', '}'], '', $uuid);
+ /** @phpstan-ignore possiblyImpure.functionCall */
+ $uuid = strtolower(str_replace(['urn:', 'uuid:', 'URN:', 'UUID:', '{', '}'], '', $uuid));
- return $uuid === Uuid::NIL || preg_match('/' . self::VALID_PATTERN . '/Dms', $uuid);
+ /** @phpstan-ignore possiblyImpure.functionCall */
+ return $uuid === Uuid::NIL || $uuid === Uuid::MAX || preg_match('/' . self::VALID_PATTERN . '/Dms', $uuid);
}
}
diff --git a/vendor/ramsey/uuid/src/Rfc4122/VariantTrait.php b/vendor/ramsey/uuid/src/Rfc4122/VariantTrait.php
index 4c98165..3d39369 100644
--- a/vendor/ramsey/uuid/src/Rfc4122/VariantTrait.php
+++ b/vendor/ramsey/uuid/src/Rfc4122/VariantTrait.php
@@ -19,17 +19,17 @@ use Ramsey\Uuid\Uuid;
use function decbin;
use function str_pad;
+use function str_starts_with;
use function strlen;
-use function strpos;
use function substr;
use function unpack;
use const STR_PAD_LEFT;
/**
- * Provides common functionality for handling the variant, as defined by RFC 4122
+ * Provides common functionality for handling the variant, as defined by RFC 9562 (formerly RFC 4122)
*
- * @psalm-immutable
+ * @immutable
*/
trait VariantTrait
{
@@ -39,18 +39,18 @@ trait VariantTrait
abstract public function getBytes(): string;
/**
- * Returns the variant identifier, according to RFC 4122, for the given bytes
+ * Returns the variant
*
- * The following values may be returned:
+ * The variant number describes the layout of the UUID. The variant number has the following meaning:
*
- * - `0` -- Reserved, NCS backward compatibility.
- * - `2` -- The variant specified in RFC 4122.
- * - `6` -- Reserved, Microsoft Corporation backward compatibility.
- * - `7` -- Reserved for future definition.
+ * - 0 - Reserved for NCS backward compatibility
+ * - 2 - The RFC 9562 (formerly RFC 4122) variant
+ * - 6 - Reserved, Microsoft Corporation backward compatibility
+ * - 7 - Reserved for future definition
*
- * @link https://tools.ietf.org/html/rfc4122#section-4.1.1 RFC 4122, § 4.1.1: Variant
+ * For RFC 9562 (formerly RFC 4122) variant UUIDs, this value should always be the integer `2`.
*
- * @return int The variant identifier, according to RFC 4122
+ * @link https://www.rfc-editor.org/rfc/rfc9562#section-4.1 RFC 9562, 4.1. Variant Field
*/
public function getVariant(): int
{
@@ -58,33 +58,36 @@ trait VariantTrait
throw new InvalidBytesException('Invalid number of bytes');
}
- /** @var array $parts */
- $parts = unpack('n*', $this->getBytes());
-
- // $parts[5] is a 16-bit, unsigned integer containing the variant bits
- // of the UUID. We convert this integer into a string containing a
- // binary representation, padded to 16 characters. We analyze the first
- // three characters (three most-significant bits) to determine the
- // variant.
- $binary = str_pad(
- decbin((int) $parts[5]),
- 16,
- '0',
- STR_PAD_LEFT
- );
-
- $msb = substr($binary, 0, 3);
-
- if ($msb === '111') {
- $variant = Uuid::RESERVED_FUTURE;
- } elseif ($msb === '110') {
- $variant = Uuid::RESERVED_MICROSOFT;
- } elseif (strpos($msb, '10') === 0) {
- $variant = Uuid::RFC_4122;
- } else {
- $variant = Uuid::RESERVED_NCS;
+ // According to RFC 9562, sections {@link https://www.rfc-editor.org/rfc/rfc9562#section-4.1 4.1} and
+ // {@link https://www.rfc-editor.org/rfc/rfc9562#section-5.10 5.10}, the Max UUID falls within the range
+ // of the future variant.
+ if ($this->isMax()) {
+ return Uuid::RESERVED_FUTURE;
}
- return $variant;
+ // According to RFC 9562, sections {@link https://www.rfc-editor.org/rfc/rfc9562#section-4.1 4.1} and
+ // {@link https://www.rfc-editor.org/rfc/rfc9562#section-5.9 5.9}, the Nil UUID falls within the range
+ // of the Apollo NCS variant.
+ if ($this->isNil()) {
+ return Uuid::RESERVED_NCS;
+ }
+
+ /** @var int[] $parts */
+ $parts = unpack('n*', $this->getBytes());
+
+ // $parts[5] is a 16-bit, unsigned integer containing the variant bits of the UUID. We convert this integer into
+ // a string containing a binary representation, padded to 16 characters. We analyze the first three characters
+ // (three most-significant bits) to determine the variant.
+ $msb = substr(str_pad(decbin($parts[5]), 16, '0', STR_PAD_LEFT), 0, 3);
+
+ if ($msb === '111') {
+ return Uuid::RESERVED_FUTURE;
+ } elseif ($msb === '110') {
+ return Uuid::RESERVED_MICROSOFT;
+ } elseif (str_starts_with($msb, '10')) {
+ return Uuid::RFC_4122;
+ }
+
+ return Uuid::RESERVED_NCS;
}
}
diff --git a/vendor/ramsey/uuid/src/Rfc4122/VersionTrait.php b/vendor/ramsey/uuid/src/Rfc4122/VersionTrait.php
index cee55fb..5f4e17b 100644
--- a/vendor/ramsey/uuid/src/Rfc4122/VersionTrait.php
+++ b/vendor/ramsey/uuid/src/Rfc4122/VersionTrait.php
@@ -14,44 +14,65 @@ declare(strict_types=1);
namespace Ramsey\Uuid\Rfc4122;
+use Ramsey\Uuid\Uuid;
+
/**
- * Provides common functionality for handling the version, as defined by RFC 4122
+ * Provides common functionality for handling the version, as defined by RFC 9562 (formerly RFC 4122)
*
- * @psalm-immutable
+ * @immutable
*/
trait VersionTrait
{
/**
- * Returns the version
+ * Returns the UUID version
+ *
+ * The version number describes how the UUID was generated and has the following meaning:
+ *
+ * 1. Gregorian time UUID
+ * 2. DCE security UUID
+ * 3. Name-based UUID hashed with MD5
+ * 4. Randomly generated UUID
+ * 5. Name-based UUID hashed with SHA-1
+ * 6. Reordered Gregorian time UUID
+ * 7. Unix Epoch time UUID
+ * 8. Custom format UUID
+ *
+ * This returns `null` if the UUID is not an RFC 9562 (formerly RFC 4122) variant, since the version is only
+ * meaningful for this variant.
+ *
+ * @link https://www.rfc-editor.org/rfc/rfc9562#section-4.2 RFC 9562, 4.2. Version Field
+ *
+ * @pure
*/
abstract public function getVersion(): ?int;
+ /**
+ * Returns true if these fields represent a max UUID
+ */
+ abstract public function isMax(): bool;
+
/**
* Returns true if these fields represent a nil UUID
*/
abstract public function isNil(): bool;
/**
- * Returns true if the version matches one of those defined by RFC 4122
+ * Returns true if the version matches one of those defined by RFC 9562 (formerly RFC 4122)
*
* @return bool True if the UUID version is valid, false otherwise
*/
private function isCorrectVersion(): bool
{
- if ($this->isNil()) {
+ if ($this->isNil() || $this->isMax()) {
return true;
}
- switch ($this->getVersion()) {
- case 1:
- case 2:
- case 3:
- case 4:
- case 5:
- case 6:
- return true;
- }
-
- return false;
+ return match ($this->getVersion()) {
+ Uuid::UUID_TYPE_TIME, Uuid::UUID_TYPE_DCE_SECURITY,
+ Uuid::UUID_TYPE_HASH_MD5, Uuid::UUID_TYPE_RANDOM,
+ Uuid::UUID_TYPE_HASH_SHA1, Uuid::UUID_TYPE_REORDERED_TIME,
+ Uuid::UUID_TYPE_UNIX_TIME, Uuid::UUID_TYPE_CUSTOM => true,
+ default => false,
+ };
}
}
diff --git a/vendor/ramsey/uuid/src/Type/Decimal.php b/vendor/ramsey/uuid/src/Type/Decimal.php
index 10f9384..b5b4f97 100644
--- a/vendor/ramsey/uuid/src/Type/Decimal.php
+++ b/vendor/ramsey/uuid/src/Type/Decimal.php
@@ -19,35 +19,24 @@ use ValueError;
use function is_numeric;
use function sprintf;
+use function str_starts_with;
/**
* A value object representing a decimal
*
- * This class exists for type-safety purposes, to ensure that decimals
- * returned from ramsey/uuid methods as strings are truly decimals and not some
- * other kind of string.
+ * This class exists for type-safety purposes, to ensure that decimals returned from ramsey/uuid methods as strings are
+ * truly decimals and not some other kind of string.
*
- * To support values as true decimals and not as floats or doubles, we store the
- * decimals as strings.
+ * To support values as true decimals and not as floats or doubles, we store the decimals as strings.
*
- * @psalm-immutable
+ * @immutable
*/
final class Decimal implements NumberInterface
{
- /**
- * @var string
- */
- private $value;
+ private string $value;
+ private bool $isNegative;
- /**
- * @var bool
- */
- private $isNegative = false;
-
- /**
- * @param mixed $value The decimal value to store
- */
- public function __construct($value)
+ public function __construct(float | int | string | self $value)
{
$value = (string) $value;
@@ -59,7 +48,7 @@ final class Decimal implements NumberInterface
}
// Remove the leading +-symbol.
- if (strpos($value, '+') === 0) {
+ if (str_starts_with($value, '+')) {
$value = substr($value, 1);
}
@@ -68,8 +57,10 @@ final class Decimal implements NumberInterface
$value = '0';
}
- if (strpos($value, '-') === 0) {
+ if (str_starts_with($value, '-')) {
$this->isNegative = true;
+ } else {
+ $this->isNegative = false;
}
$this->value = $value;
@@ -111,18 +102,15 @@ final class Decimal implements NumberInterface
/**
* Constructs the object from a serialized string representation
*
- * @param string $serialized The serialized string representation of the object
- *
- * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
- * @psalm-suppress UnusedMethodCall
+ * @param string $data The serialized string representation of the object
*/
- public function unserialize($serialized): void
+ public function unserialize(string $data): void
{
- $this->__construct($serialized);
+ $this->__construct($data);
}
/**
- * @param array{string: string} $data
+ * @param array{string?: string} $data
*/
public function __unserialize(array $data): void
{
diff --git a/vendor/ramsey/uuid/src/Type/Hexadecimal.php b/vendor/ramsey/uuid/src/Type/Hexadecimal.php
index 88adc2e..c411764 100644
--- a/vendor/ramsey/uuid/src/Type/Hexadecimal.php
+++ b/vendor/ramsey/uuid/src/Type/Hexadecimal.php
@@ -17,63 +17,62 @@ namespace Ramsey\Uuid\Type;
use Ramsey\Uuid\Exception\InvalidArgumentException;
use ValueError;
-use function ctype_xdigit;
+use function preg_match;
use function sprintf;
-use function strpos;
-use function strtolower;
use function substr;
/**
* A value object representing a hexadecimal number
*
- * This class exists for type-safety purposes, to ensure that hexadecimal numbers
- * returned from ramsey/uuid methods as strings are truly hexadecimal and not some
- * other kind of string.
+ * This class exists for type-safety purposes, to ensure that hexadecimal numbers returned from ramsey/uuid methods as
+ * strings are truly hexadecimal and not some other kind of string.
*
- * @psalm-immutable
+ * @immutable
*/
final class Hexadecimal implements TypeInterface
{
/**
- * @var string
+ * @var non-empty-string
*/
- private $value;
+ private string $value;
/**
- * @param string $value The hexadecimal value to store
+ * @param self | string $value The hexadecimal value to store
*/
- public function __construct(string $value)
+ public function __construct(self | string $value)
{
- $value = strtolower($value);
-
- if (strpos($value, '0x') === 0) {
- $value = substr($value, 2);
- }
-
- if (!ctype_xdigit($value)) {
- throw new InvalidArgumentException(
- 'Value must be a hexadecimal number'
- );
- }
-
- $this->value = $value;
+ $this->value = $value instanceof self ? (string) $value : $this->prepareValue($value);
}
+ /**
+ * @return non-empty-string
+ *
+ * @pure
+ */
public function toString(): string
{
return $this->value;
}
+ /**
+ * @return non-empty-string
+ */
public function __toString(): string
{
return $this->toString();
}
+ /**
+ * @return non-empty-string
+ */
public function jsonSerialize(): string
{
return $this->toString();
}
+ /**
+ * @return non-empty-string
+ */
public function serialize(): string
{
return $this->toString();
@@ -90,18 +89,15 @@ final class Hexadecimal implements TypeInterface
/**
* Constructs the object from a serialized string representation
*
- * @param string $serialized The serialized string representation of the object
- *
- * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
- * @psalm-suppress UnusedMethodCall
+ * @param string $data The serialized string representation of the object
*/
- public function unserialize($serialized): void
+ public function unserialize(string $data): void
{
- $this->__construct($serialized);
+ $this->__construct($data);
}
/**
- * @param array{string: string} $data
+ * @param array{string?: string} $data
*/
public function __unserialize(array $data): void
{
@@ -113,4 +109,23 @@ final class Hexadecimal implements TypeInterface
$this->unserialize($data['string']);
}
+
+ /**
+ * @return non-empty-string
+ */
+ private function prepareValue(string $value): string
+ {
+ $value = strtolower($value);
+
+ if (str_starts_with($value, '0x')) {
+ $value = substr($value, 2);
+ }
+
+ if (!preg_match('/^[A-Fa-f0-9]+$/', $value)) {
+ throw new InvalidArgumentException('Value must be a hexadecimal number');
+ }
+
+ /** @var non-empty-string */
+ return $value;
+ }
}
diff --git a/vendor/ramsey/uuid/src/Type/Integer.php b/vendor/ramsey/uuid/src/Type/Integer.php
index 7690f6c..ed6c82d 100644
--- a/vendor/ramsey/uuid/src/Type/Integer.php
+++ b/vendor/ramsey/uuid/src/Type/Integer.php
@@ -17,75 +17,38 @@ namespace Ramsey\Uuid\Type;
use Ramsey\Uuid\Exception\InvalidArgumentException;
use ValueError;
-use function ctype_digit;
-use function ltrim;
+use function assert;
+use function is_numeric;
+use function preg_match;
use function sprintf;
-use function strpos;
use function substr;
/**
* A value object representing an integer
*
- * This class exists for type-safety purposes, to ensure that integers
- * returned from ramsey/uuid methods as strings are truly integers and not some
- * other kind of string.
+ * This class exists for type-safety purposes, to ensure that integers returned from ramsey/uuid methods as strings are
+ * truly integers and not some other kind of string.
*
- * To support large integers beyond PHP_INT_MAX and PHP_INT_MIN on both 64-bit
- * and 32-bit systems, we store the integers as strings.
+ * To support large integers beyond PHP_INT_MAX and PHP_INT_MIN on both 64-bit and 32-bit systems, we store the integers
+ * as strings.
*
- * @psalm-immutable
+ * @immutable
*/
final class Integer implements NumberInterface
{
/**
- * @psalm-var numeric-string
+ * @var numeric-string
*/
- private $value;
+ private string $value;
/**
- * @var bool
+ * @phpstan-ignore property.readOnlyByPhpDocDefaultValue
*/
- private $isNegative = false;
+ private bool $isNegative = false;
- /**
- * @param mixed $value The integer value to store
- */
- public function __construct($value)
+ public function __construct(self | float | int | string $value)
{
- $value = (string) $value;
- $sign = '+';
-
- // If the value contains a sign, remove it for ctype_digit() check.
- if (strpos($value, '-') === 0 || strpos($value, '+') === 0) {
- $sign = substr($value, 0, 1);
- $value = substr($value, 1);
- }
-
- if (!ctype_digit($value)) {
- throw new InvalidArgumentException(
- 'Value must be a signed integer or a string containing only '
- . 'digits 0-9 and, optionally, a sign (+ or -)'
- );
- }
-
- // Trim any leading zeros.
- $value = ltrim($value, '0');
-
- // Set to zero if the string is empty after trimming zeros.
- if ($value === '') {
- $value = '0';
- }
-
- // Add the negative sign back to the value.
- if ($sign === '-' && $value !== '0') {
- $value = $sign . $value;
- $this->isNegative = true;
- }
-
- /** @psalm-var numeric-string $numericValue */
- $numericValue = $value;
-
- $this->value = $numericValue;
+ $this->value = $value instanceof self ? (string) $value : $this->prepareValue($value);
}
public function isNegative(): bool
@@ -94,13 +57,18 @@ final class Integer implements NumberInterface
}
/**
- * @psalm-return numeric-string
+ * @return numeric-string
+ *
+ * @pure
*/
public function toString(): string
{
return $this->value;
}
+ /**
+ * @return numeric-string
+ */
public function __toString(): string
{
return $this->toString();
@@ -127,18 +95,15 @@ final class Integer implements NumberInterface
/**
* Constructs the object from a serialized string representation
*
- * @param string $serialized The serialized string representation of the object
- *
- * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
- * @psalm-suppress UnusedMethodCall
+ * @param string $data The serialized string representation of the object
*/
- public function unserialize($serialized): void
+ public function unserialize(string $data): void
{
- $this->__construct($serialized);
+ $this->__construct($data);
}
/**
- * @param array{string: string} $data
+ * @param array{string?: string} $data
*/
public function __unserialize(array $data): void
{
@@ -150,4 +115,46 @@ final class Integer implements NumberInterface
$this->unserialize($data['string']);
}
+
+ /**
+ * @return numeric-string
+ */
+ private function prepareValue(float | int | string $value): string
+ {
+ $value = (string) $value;
+ $sign = '+';
+
+ // If the value contains a sign, remove it for the digit pattern check.
+ if (str_starts_with($value, '-') || str_starts_with($value, '+')) {
+ $sign = substr($value, 0, 1);
+ $value = substr($value, 1);
+ }
+
+ if (!preg_match('/^\d+$/', $value)) {
+ throw new InvalidArgumentException(
+ 'Value must be a signed integer or a string containing only '
+ . 'digits 0-9 and, optionally, a sign (+ or -)'
+ );
+ }
+
+ // Trim any leading zeros.
+ $value = ltrim($value, '0');
+
+ // Set to zero if the string is empty after trimming zeros.
+ if ($value === '') {
+ $value = '0';
+ }
+
+ // Add the negative sign back to the value.
+ if ($sign === '-' && $value !== '0') {
+ $value = $sign . $value;
+
+ /** @phpstan-ignore property.readOnlyByPhpDocAssignNotInConstructor */
+ $this->isNegative = true;
+ }
+
+ assert(is_numeric($value));
+
+ return $value;
+ }
}
diff --git a/vendor/ramsey/uuid/src/Type/NumberInterface.php b/vendor/ramsey/uuid/src/Type/NumberInterface.php
index bf4ae9d..d85e103 100644
--- a/vendor/ramsey/uuid/src/Type/NumberInterface.php
+++ b/vendor/ramsey/uuid/src/Type/NumberInterface.php
@@ -17,7 +17,7 @@ namespace Ramsey\Uuid\Type;
/**
* NumberInterface ensures consistency in numeric values returned by ramsey/uuid
*
- * @psalm-immutable
+ * @immutable
*/
interface NumberInterface extends TypeInterface
{
diff --git a/vendor/ramsey/uuid/src/Type/Time.php b/vendor/ramsey/uuid/src/Type/Time.php
index dd1b8bc..2556c5b 100644
--- a/vendor/ramsey/uuid/src/Type/Time.php
+++ b/vendor/ramsey/uuid/src/Type/Time.php
@@ -17,7 +17,6 @@ namespace Ramsey\Uuid\Type;
use Ramsey\Uuid\Exception\UnsupportedOperationException;
use Ramsey\Uuid\Type\Integer as IntegerObject;
use ValueError;
-use stdClass;
use function json_decode;
use function json_encode;
@@ -26,39 +25,35 @@ use function sprintf;
/**
* A value object representing a timestamp
*
- * This class exists for type-safety purposes, to ensure that timestamps used
- * by ramsey/uuid are truly timestamp integers and not some other kind of string
- * or integer.
+ * This class exists for type-safety purposes, to ensure that timestamps used by ramsey/uuid are truly timestamp
+ * integers and not some other kind of string or integer.
*
- * @psalm-immutable
+ * @immutable
*/
final class Time implements TypeInterface
{
- /**
- * @var IntegerObject
- */
- private $seconds;
+ private IntegerObject $seconds;
+ private IntegerObject $microseconds;
- /**
- * @var IntegerObject
- */
- private $microseconds;
-
- /**
- * @param mixed $seconds
- * @param mixed $microseconds
- */
- public function __construct($seconds, $microseconds = 0)
- {
+ public function __construct(
+ IntegerObject | float | int | string $seconds,
+ IntegerObject | float | int | string $microseconds = 0,
+ ) {
$this->seconds = new IntegerObject($seconds);
$this->microseconds = new IntegerObject($microseconds);
}
+ /**
+ * @pure
+ */
public function getSeconds(): IntegerObject
{
return $this->seconds;
}
+ /**
+ * @pure
+ */
public function getMicroseconds(): IntegerObject
{
return $this->microseconds;
@@ -66,7 +61,7 @@ final class Time implements TypeInterface
public function toString(): string
{
- return $this->seconds->toString() . '.' . $this->microseconds->toString();
+ return $this->seconds->toString() . '.' . sprintf('%06s', $this->microseconds->toString());
}
public function __toString(): string
@@ -104,27 +99,22 @@ final class Time implements TypeInterface
/**
* Constructs the object from a serialized string representation
*
- * @param string $serialized The serialized string representation of the object
- *
- * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
- * @psalm-suppress UnusedMethodCall
+ * @param string $data The serialized string representation of the object
*/
- public function unserialize($serialized): void
+ public function unserialize(string $data): void
{
- /** @var stdClass $time */
- $time = json_decode($serialized);
+ /** @var array{seconds?: float | int | string, microseconds?: float | int | string} $time */
+ $time = json_decode($data, true);
- if (!isset($time->seconds) || !isset($time->microseconds)) {
- throw new UnsupportedOperationException(
- 'Attempted to unserialize an invalid value'
- );
+ if (!isset($time['seconds']) || !isset($time['microseconds'])) {
+ throw new UnsupportedOperationException('Attempted to unserialize an invalid value');
}
- $this->__construct($time->seconds, $time->microseconds);
+ $this->__construct($time['seconds'], $time['microseconds']);
}
/**
- * @param array{seconds: string, microseconds: string} $data
+ * @param array{seconds?: string, microseconds?: string} $data
*/
public function __unserialize(array $data): void
{
diff --git a/vendor/ramsey/uuid/src/Type/TypeInterface.php b/vendor/ramsey/uuid/src/Type/TypeInterface.php
index da2d8b2..0c88a28 100644
--- a/vendor/ramsey/uuid/src/Type/TypeInterface.php
+++ b/vendor/ramsey/uuid/src/Type/TypeInterface.php
@@ -20,11 +20,17 @@ use Serializable;
/**
* TypeInterface ensures consistency in typed values returned by ramsey/uuid
*
- * @psalm-immutable
+ * @immutable
*/
interface TypeInterface extends JsonSerializable, Serializable
{
+ /**
+ * @pure
+ */
public function toString(): string;
+ /**
+ * @pure
+ */
public function __toString(): string;
}
diff --git a/vendor/ramsey/uuid/src/Uuid.php b/vendor/ramsey/uuid/src/Uuid.php
index 945480b..0f05bbf 100644
--- a/vendor/ramsey/uuid/src/Uuid.php
+++ b/vendor/ramsey/uuid/src/Uuid.php
@@ -14,10 +14,13 @@ declare(strict_types=1);
namespace Ramsey\Uuid;
+use BadMethodCallException;
use DateTimeInterface;
use Ramsey\Uuid\Codec\CodecInterface;
use Ramsey\Uuid\Converter\NumberConverterInterface;
use Ramsey\Uuid\Converter\TimeConverterInterface;
+use Ramsey\Uuid\Exception\InvalidArgumentException;
+use Ramsey\Uuid\Exception\UnsupportedOperationException;
use Ramsey\Uuid\Fields\FieldsInterface;
use Ramsey\Uuid\Lazy\LazyUuidFromString;
use Ramsey\Uuid\Rfc4122\FieldsInterface as Rfc4122FieldsInterface;
@@ -27,6 +30,7 @@ use ValueError;
use function assert;
use function bin2hex;
+use function method_exists;
use function preg_match;
use function sprintf;
use function str_replace;
@@ -38,75 +42,87 @@ use function substr;
/**
* Uuid provides constants and static methods for working with and generating UUIDs
*
- * @psalm-immutable
+ * @immutable
*/
class Uuid implements UuidInterface
{
use DeprecatedUuidMethodsTrait;
/**
- * When this namespace is specified, the name string is a fully-qualified
- * domain name
+ * When this namespace is specified, the name string is a fully qualified domain name
*
- * @link http://tools.ietf.org/html/rfc4122#appendix-C RFC 4122, Appendix C: Some Name Space IDs
+ * @link https://www.rfc-editor.org/rfc/rfc9562#section-6.6 RFC 9562, 6.6. Namespace ID Usage and Allocation
*/
public const NAMESPACE_DNS = '6ba7b810-9dad-11d1-80b4-00c04fd430c8';
/**
* When this namespace is specified, the name string is a URL
*
- * @link http://tools.ietf.org/html/rfc4122#appendix-C RFC 4122, Appendix C: Some Name Space IDs
+ * @link https://www.rfc-editor.org/rfc/rfc9562#section-6.6 RFC 9562, 6.6. Namespace ID Usage and Allocation
*/
public const NAMESPACE_URL = '6ba7b811-9dad-11d1-80b4-00c04fd430c8';
/**
* When this namespace is specified, the name string is an ISO OID
*
- * @link http://tools.ietf.org/html/rfc4122#appendix-C RFC 4122, Appendix C: Some Name Space IDs
+ * @link https://www.rfc-editor.org/rfc/rfc9562#section-6.6 RFC 9562, 6.6. Namespace ID Usage and Allocation
*/
public const NAMESPACE_OID = '6ba7b812-9dad-11d1-80b4-00c04fd430c8';
/**
- * When this namespace is specified, the name string is an X.500 DN in DER
- * or a text output format
+ * When this namespace is specified, the name string is an X.500 DN (in DER or a text output format)
*
- * @link http://tools.ietf.org/html/rfc4122#appendix-C RFC 4122, Appendix C: Some Name Space IDs
+ * @link https://www.rfc-editor.org/rfc/rfc9562#section-6.6 RFC 9562, 6.6. Namespace ID Usage and Allocation
*/
public const NAMESPACE_X500 = '6ba7b814-9dad-11d1-80b4-00c04fd430c8';
/**
- * The nil UUID is a special form of UUID that is specified to have all 128
- * bits set to zero
+ * The Nil UUID is a special form of UUID that is specified to have all 128 bits set to zero
*
- * @link http://tools.ietf.org/html/rfc4122#section-4.1.7 RFC 4122, § 4.1.7: Nil UUID
+ * @link https://www.rfc-editor.org/rfc/rfc9562#section-5.9 RFC 9562, 5.9. Nil UUID
*/
public const NIL = '00000000-0000-0000-0000-000000000000';
+ /**
+ * The Max UUID is a special form of UUID that is specified to have all 128 bits set to one
+ *
+ * @link https://www.rfc-editor.org/rfc/rfc9562#section-5.10 RFC 9562, 5.10. Max UUID
+ */
+ public const MAX = 'ffffffff-ffff-ffff-ffff-ffffffffffff';
+
/**
* Variant: reserved, NCS backward compatibility
*
- * @link http://tools.ietf.org/html/rfc4122#section-4.1.1 RFC 4122, § 4.1.1: Variant
+ * @link https://www.rfc-editor.org/rfc/rfc9562#section-4.1 RFC 9562, 4.1. Variant Field
*/
public const RESERVED_NCS = 0;
/**
- * Variant: the UUID layout specified in RFC 4122
+ * Variant: the UUID layout specified in RFC 9562 (formerly RFC 4122)
*
- * @link http://tools.ietf.org/html/rfc4122#section-4.1.1 RFC 4122, § 4.1.1: Variant
+ * @link https://www.rfc-editor.org/rfc/rfc9562#section-4.1 RFC 9562, 4.1. Variant Field
+ * @see Uuid::RFC_9562
*/
public const RFC_4122 = 2;
+ /**
+ * Variant: the UUID layout specified in RFC 9562 (formerly RFC 4122)
+ *
+ * @link https://www.rfc-editor.org/rfc/rfc9562#section-4.1 RFC 9562, 4.1. Variant Field
+ */
+ public const RFC_9562 = 2;
+
/**
* Variant: reserved, Microsoft Corporation backward compatibility
*
- * @link http://tools.ietf.org/html/rfc4122#section-4.1.1 RFC 4122, § 4.1.1: Variant
+ * @link https://www.rfc-editor.org/rfc/rfc9562#section-4.1 RFC 9562, 4.1. Variant Field
*/
public const RESERVED_MICROSOFT = 6;
/**
* Variant: reserved for future definition
*
- * @link http://tools.ietf.org/html/rfc4122#section-4.1.1 RFC 4122, § 4.1.1: Variant
+ * @link https://www.rfc-editor.org/rfc/rfc9562#section-4.1 RFC 9562, 4.1. Variant Field
*/
public const RESERVED_FUTURE = 7;
@@ -116,16 +132,16 @@ class Uuid implements UuidInterface
public const VALID_PATTERN = '^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}$';
/**
- * Version 1 (time-based) UUID
+ * Version 1 (Gregorian time) UUID
*
- * @link https://tools.ietf.org/html/rfc4122#section-4.1.3 RFC 4122, § 4.1.3: Version
+ * @link https://www.rfc-editor.org/rfc/rfc9562#section-4.2 RFC 9562, 4.2. Version Field
*/
public const UUID_TYPE_TIME = 1;
/**
* Version 2 (DCE Security) UUID
*
- * @link https://tools.ietf.org/html/rfc4122#section-4.1.3 RFC 4122, § 4.1.3: Version
+ * @link https://www.rfc-editor.org/rfc/rfc9562#section-4.2 RFC 9562, 4.2. Version Field
*/
public const UUID_TYPE_DCE_SECURITY = 2;
@@ -137,35 +153,50 @@ class Uuid implements UuidInterface
/**
* Version 3 (name-based and hashed with MD5) UUID
*
- * @link https://tools.ietf.org/html/rfc4122#section-4.1.3 RFC 4122, § 4.1.3: Version
+ * @link https://www.rfc-editor.org/rfc/rfc9562#section-4.2 RFC 9562, 4.2. Version Field
*/
public const UUID_TYPE_HASH_MD5 = 3;
/**
* Version 4 (random) UUID
*
- * @link https://tools.ietf.org/html/rfc4122#section-4.1.3 RFC 4122, § 4.1.3: Version
+ * @link https://www.rfc-editor.org/rfc/rfc9562#section-4.2 RFC 9562, 4.2. Version Field
*/
public const UUID_TYPE_RANDOM = 4;
/**
* Version 5 (name-based and hashed with SHA1) UUID
*
- * @link https://tools.ietf.org/html/rfc4122#section-4.1.3 RFC 4122, § 4.1.3: Version
+ * @link https://www.rfc-editor.org/rfc/rfc9562#section-4.2 RFC 9562, 4.2. Version Field
*/
public const UUID_TYPE_HASH_SHA1 = 5;
/**
- * Version 6 (ordered-time) UUID
- *
- * This is named `UUID_TYPE_PEABODY`, since the specification is still in
- * draft form, and the primary author/editor's name is Brad Peabody.
- *
- * @link https://github.com/uuid6/uuid6-ietf-draft UUID version 6 IETF draft
- * @link http://gh.peabody.io/uuidv6/ "Version 6" UUIDs
+ * @deprecated Use {@see Uuid::UUID_TYPE_REORDERED_TIME} instead.
*/
public const UUID_TYPE_PEABODY = 6;
+ /**
+ * Version 6 (reordered Gregorian time) UUID
+ *
+ * @link https://www.rfc-editor.org/rfc/rfc9562#section-4.2 RFC 9562, 4.2. Version Field
+ */
+ public const UUID_TYPE_REORDERED_TIME = 6;
+
+ /**
+ * Version 7 (Unix Epoch time) UUID
+ *
+ * @link https://www.rfc-editor.org/rfc/rfc9562#section-4.2 RFC 9562, 4.2. Version Field
+ */
+ public const UUID_TYPE_UNIX_TIME = 7;
+
+ /**
+ * Version 8 (custom format) UUID
+ *
+ * @link https://www.rfc-editor.org/rfc/rfc9562#section-4.2 RFC 9562, 4.2. Version Field
+ */
+ public const UUID_TYPE_CUSTOM = 8;
+
/**
* DCE Security principal domain
*
@@ -199,44 +230,27 @@ class Uuid implements UuidInterface
];
/**
- * @var UuidFactoryInterface|null
+ * @phpstan-ignore property.readOnlyByPhpDocDefaultValue
*/
- private static $factory = null;
+ private static ?UuidFactoryInterface $factory = null;
/**
- * @var bool flag to detect if the UUID factory was replaced internally, which disables all optimizations
- * for the default/happy path internal scenarios
+ * @var bool flag to detect if the UUID factory was replaced internally, which disables all optimizations for the
+ * default/happy path internal scenarios
+ * @phpstan-ignore property.readOnlyByPhpDocDefaultValue
*/
- private static $factoryReplaced = false;
+ private static bool $factoryReplaced = false;
- /**
- * @var CodecInterface
- */
- protected $codec;
-
- /**
- * The fields that make up this UUID
- *
- * @var Rfc4122FieldsInterface
- */
- protected $fields;
-
- /**
- * @var NumberConverterInterface
- */
- protected $numberConverter;
-
- /**
- * @var TimeConverterInterface
- */
- protected $timeConverter;
+ protected CodecInterface $codec;
+ protected NumberConverterInterface $numberConverter;
+ protected Rfc4122FieldsInterface $fields;
+ protected TimeConverterInterface $timeConverter;
/**
* Creates a universally unique identifier (UUID) from an array of fields
*
- * Unless you're making advanced use of this library to generate identifiers
- * that deviate from RFC 4122, you probably do not want to instantiate a
- * UUID directly. Use the static methods, instead:
+ * Unless you're making advanced use of this library to generate identifiers that deviate from RFC 9562 (formerly
+ * RFC 4122), you probably do not want to instantiate a UUID directly. Use the static methods, instead:
*
* ```
* use Ramsey\Uuid\Uuid;
@@ -248,18 +262,16 @@ class Uuid implements UuidInterface
* ```
*
* @param Rfc4122FieldsInterface $fields The fields from which to construct a UUID
- * @param NumberConverterInterface $numberConverter The number converter to use
- * for converting hex values to/from integers
- * @param CodecInterface $codec The codec to use when encoding or decoding
- * UUID strings
- * @param TimeConverterInterface $timeConverter The time converter to use
- * for converting timestamps extracted from a UUID to unix timestamps
+ * @param NumberConverterInterface $numberConverter The number converter to use for converting hex values to/from integers
+ * @param CodecInterface $codec The codec to use when encoding or decoding UUID strings
+ * @param TimeConverterInterface $timeConverter The time converter to use for converting timestamps extracted from a
+ * UUID to unix timestamps
*/
public function __construct(
Rfc4122FieldsInterface $fields,
NumberConverterInterface $numberConverter,
CodecInterface $codec,
- TimeConverterInterface $timeConverter
+ TimeConverterInterface $timeConverter,
) {
$this->fields = $fields;
$this->codec = $codec;
@@ -268,7 +280,7 @@ class Uuid implements UuidInterface
}
/**
- * @psalm-return non-empty-string
+ * @return non-empty-string
*/
public function __toString(): string
{
@@ -288,7 +300,7 @@ class Uuid implements UuidInterface
*/
public function serialize(): string
{
- return $this->getFields()->getBytes();
+ return $this->codec->encode($this);
}
/**
@@ -302,29 +314,33 @@ class Uuid implements UuidInterface
/**
* Re-constructs the object from its serialized form
*
- * @param string $serialized The serialized PHP string to unserialize into
- * a UuidInterface instance
- *
- * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
+ * @param string $data The serialized PHP string to unserialize into a UuidInterface instance
*/
- public function unserialize($serialized): void
+ public function unserialize(string $data): void
{
- if (strlen($serialized) === 16) {
+ if (strlen($data) === 16) {
/** @var Uuid $uuid */
- $uuid = self::getFactory()->fromBytes($serialized);
+ $uuid = self::getFactory()->fromBytes($data);
} else {
/** @var Uuid $uuid */
- $uuid = self::getFactory()->fromString($serialized);
+ $uuid = self::getFactory()->fromString($data);
}
+ /** @phpstan-ignore property.readOnlyByPhpDocAssignNotInConstructor */
$this->codec = $uuid->codec;
+
+ /** @phpstan-ignore property.readOnlyByPhpDocAssignNotInConstructor */
$this->numberConverter = $uuid->numberConverter;
+
+ /** @phpstan-ignore property.readOnlyByPhpDocAssignNotInConstructor */
$this->fields = $uuid->fields;
+
+ /** @phpstan-ignore property.readOnlyByPhpDocAssignNotInConstructor */
$this->timeConverter = $uuid->timeConverter;
}
/**
- * @param array{bytes: string} $data
+ * @param array{bytes?: string} $data
*/
public function __unserialize(array $data): void
{
@@ -362,7 +378,7 @@ class Uuid implements UuidInterface
}
/**
- * @psalm-return non-empty-string
+ * @return non-empty-string
*/
public function getBytes(): string
{
@@ -384,8 +400,13 @@ class Uuid implements UuidInterface
return new IntegerObject($this->numberConverter->fromHex($this->getHex()->toString()));
}
+ public function getUrn(): string
+ {
+ return 'urn:uuid:' . $this->toString();
+ }
+
/**
- * @psalm-return non-empty-string
+ * @return non-empty-string
*/
public function toString(): string
{
@@ -407,8 +428,7 @@ class Uuid implements UuidInterface
/**
* Sets the factory used to create UUIDs
*
- * @param UuidFactoryInterface $factory A factory that will be used by this
- * class to create UUIDs
+ * @param UuidFactoryInterface $factory A factory that will be used by this class to create UUIDs
*/
public static function setFactory(UuidFactoryInterface $factory): void
{
@@ -425,36 +445,33 @@ class Uuid implements UuidInterface
*
* @param string $bytes A binary string
*
- * @return UuidInterface A UuidInterface instance created from a binary
- * string representation
+ * @return UuidInterface A UuidInterface instance created from a binary string representation
*
- * @psalm-pure note: changing the internal factory is an edge case not covered by purity invariants,
- * but under constant factory setups, this method operates in functionally pure manners
+ * @throws InvalidArgumentException
*
- * @psalm-suppress ImpureStaticProperty we know that the factory being replaced can lead to massive
- * havoc across all consumers: that should never happen, and
- * is generally to be discouraged. Until the factory is kept
- * un-replaced, this method is effectively pure.
+ * @pure
*/
public static function fromBytes(string $bytes): UuidInterface
{
- if (! self::$factoryReplaced && strlen($bytes) === 16) {
+ /** @phpstan-ignore impure.staticPropertyAccess */
+ if (!self::$factoryReplaced && strlen($bytes) === 16) {
$base16Uuid = bin2hex($bytes);
// Note: we are calling `fromString` internally because we don't know if the given `$bytes` is a valid UUID
return self::fromString(
substr($base16Uuid, 0, 8)
- . '-'
- . substr($base16Uuid, 8, 4)
- . '-'
- . substr($base16Uuid, 12, 4)
- . '-'
- . substr($base16Uuid, 16, 4)
- . '-'
- . substr($base16Uuid, 20, 12)
+ . '-'
+ . substr($base16Uuid, 8, 4)
+ . '-'
+ . substr($base16Uuid, 12, 4)
+ . '-'
+ . substr($base16Uuid, 16, 4)
+ . '-'
+ . substr($base16Uuid, 20, 12),
);
}
+ /** @phpstan-ignore possiblyImpure.methodCall */
return self::getFactory()->fromBytes($bytes);
}
@@ -463,25 +480,25 @@ class Uuid implements UuidInterface
*
* @param string $uuid A hexadecimal string
*
- * @return UuidInterface A UuidInterface instance created from a hexadecimal
- * string representation
+ * @return UuidInterface A UuidInterface instance created from a hexadecimal string representation
*
- * @psalm-pure note: changing the internal factory is an edge case not covered by purity invariants,
- * but under constant factory setups, this method operates in functionally pure manners
+ * @throws InvalidArgumentException
*
- * @psalm-suppress ImpureStaticProperty we know that the factory being replaced can lead to massive
- * havoc across all consumers: that should never happen, and
- * is generally to be discouraged. Until the factory is kept
- * un-replaced, this method is effectively pure.
+ * @pure
*/
public static function fromString(string $uuid): UuidInterface
{
- if (! self::$factoryReplaced && preg_match(LazyUuidFromString::VALID_REGEX, $uuid) === 1) {
+ $uuid = strtolower($uuid);
+ /** @phpstan-ignore impure.staticPropertyAccess, possiblyImpure.functionCall */
+ if (!self::$factoryReplaced && preg_match(LazyUuidFromString::VALID_REGEX, $uuid) === 1) {
+ /** @phpstan-ignore possiblyImpure.functionCall */
assert($uuid !== '');
- return new LazyUuidFromString(strtolower($uuid));
+ /** @phpstan-ignore possiblyImpure.new */
+ return new LazyUuidFromString($uuid);
}
+ /** @phpstan-ignore possiblyImpure.methodCall */
return self::getFactory()->fromString($uuid);
}
@@ -489,14 +506,11 @@ class Uuid implements UuidInterface
* Creates a UUID from a DateTimeInterface instance
*
* @param DateTimeInterface $dateTime The date and time
- * @param Hexadecimal|null $node A 48-bit number representing the hardware
- * address
- * @param int|null $clockSeq A 14-bit number used to help avoid duplicates
- * that could arise when the clock is set backwards in time or if the
- * node ID changes
+ * @param Hexadecimal | null $node A 48-bit number representing the hardware address
+ * @param int | null $clockSeq A 14-bit number used to help avoid duplicates that could arise when the clock is set
+ * backwards in time or if the node ID changes
*
- * @return UuidInterface A UuidInterface instance that represents a
- * version 1 UUID created from a DateTimeInterface instance
+ * @return UuidInterface A UuidInterface instance that represents a version 1 UUID created from a DateTimeInterface instance
*/
public static function fromDateTime(
DateTimeInterface $dateTime,
@@ -506,19 +520,48 @@ class Uuid implements UuidInterface
return self::getFactory()->fromDateTime($dateTime, $node, $clockSeq);
}
+ /**
+ * Creates a UUID from the Hexadecimal object
+ *
+ * @param Hexadecimal $hex Hexadecimal object representing a hexadecimal number
+ *
+ * @return UuidInterface A UuidInterface instance created from the Hexadecimal object representing a hexadecimal number
+ *
+ * @throws InvalidArgumentException
+ *
+ * @pure
+ */
+ public static function fromHexadecimal(Hexadecimal $hex): UuidInterface
+ {
+ /** @phpstan-ignore possiblyImpure.methodCall */
+ $factory = self::getFactory();
+
+ if (method_exists($factory, 'fromHexadecimal')) {
+ /** @phpstan-ignore possiblyImpure.methodCall */
+ $uuid = $factory->fromHexadecimal($hex);
+ /** @phpstan-ignore possiblyImpure.functionCall */
+ assert($uuid instanceof UuidInterface);
+
+ return $uuid;
+ }
+
+ throw new BadMethodCallException('The method fromHexadecimal() does not exist on the provided factory');
+ }
+
/**
* Creates a UUID from a 128-bit integer string
*
* @param string $integer String representation of 128-bit integer
*
- * @return UuidInterface A UuidInterface instance created from the string
- * representation of a 128-bit integer
+ * @return UuidInterface A UuidInterface instance created from the string representation of a 128-bit integer
*
- * @psalm-pure note: changing the internal factory is an edge case not covered by purity invariants,
- * but under constant factory setups, this method operates in functionally pure manners
+ * @throws InvalidArgumentException
+ *
+ * @pure
*/
public static function fromInteger(string $integer): UuidInterface
{
+ /** @phpstan-ignore possiblyImpure.methodCall */
return self::getFactory()->fromInteger($integer);
}
@@ -529,27 +572,25 @@ class Uuid implements UuidInterface
*
* @return bool True if the string is a valid UUID, false otherwise
*
- * @psalm-pure note: changing the internal factory is an edge case not covered by purity invariants,
- * but under constant factory setups, this method operates in functionally pure manners
+ * @phpstan-assert-if-true =non-empty-string $uuid
+ *
+ * @pure
*/
public static function isValid(string $uuid): bool
{
+ /** @phpstan-ignore possiblyImpure.methodCall, possiblyImpure.methodCall */
return self::getFactory()->getValidator()->validate($uuid);
}
/**
- * Returns a version 1 (time-based) UUID from a host ID, sequence number,
- * and the current time
+ * Returns a version 1 (Gregorian time) UUID from a host ID, sequence number, and the current time
*
- * @param Hexadecimal|int|string|null $node A 48-bit number representing the
- * hardware address; this number may be represented as an integer or a
- * hexadecimal string
- * @param int $clockSeq A 14-bit number used to help avoid duplicates that
- * could arise when the clock is set backwards in time or if the node ID
- * changes
+ * @param Hexadecimal | int | string | null $node A 48-bit number representing the hardware address; this number may
+ * be represented as an integer or a hexadecimal string
+ * @param int | null $clockSeq A 14-bit number used to help avoid duplicates that could arise when the clock is set
+ * backwards in time or if the node ID changes
*
- * @return UuidInterface A UuidInterface instance that represents a
- * version 1 UUID
+ * @return UuidInterface A UuidInterface instance that represents a version 1 UUID
*/
public static function uuid1($node = null, ?int $clockSeq = null): UuidInterface
{
@@ -557,24 +598,18 @@ class Uuid implements UuidInterface
}
/**
- * Returns a version 2 (DCE Security) UUID from a local domain, local
- * identifier, host ID, clock sequence, and the current time
+ * Returns a version 2 (DCE Security) UUID from a local domain, local identifier, host ID, clock sequence, and the current time
*
- * @param int $localDomain The local domain to use when generating bytes,
- * according to DCE Security
- * @param IntegerObject|null $localIdentifier The local identifier for the
- * given domain; this may be a UID or GID on POSIX systems, if the local
- * domain is person or group, or it may be a site-defined identifier
- * if the local domain is org
- * @param Hexadecimal|null $node A 48-bit number representing the hardware
- * address
- * @param int|null $clockSeq A 14-bit number used to help avoid duplicates
- * that could arise when the clock is set backwards in time or if the
- * node ID changes (in a version 2 UUID, the lower 8 bits of this number
- * are replaced with the domain).
+ * @param int $localDomain The local domain to use when generating bytes, according to DCE Security
+ * @param IntegerObject | null $localIdentifier The local identifier for the given domain; this may be a UID or GID
+ * on POSIX systems, if the local domain is "person" or "group," or it may be a site-defined identifier if the
+ * local domain is "org"
+ * @param Hexadecimal | null $node A 48-bit number representing the hardware address
+ * @param int | null $clockSeq A 14-bit number used to help avoid duplicates that could arise when the clock is set
+ * backwards in time or if the node ID changes (in a version 2 UUID, the lower 8 bits of this number are
+ * replaced with the domain).
*
- * @return UuidInterface A UuidInterface instance that represents a
- * version 2 UUID
+ * @return UuidInterface A UuidInterface instance that represents a version 2 UUID
*/
public static function uuid2(
int $localDomain,
@@ -586,33 +621,25 @@ class Uuid implements UuidInterface
}
/**
- * Returns a version 3 (name-based) UUID based on the MD5 hash of a
- * namespace ID and a name
+ * Returns a version 3 (name-based) UUID based on the MD5 hash of a namespace ID and a name
*
- * @param string|UuidInterface $ns The namespace (must be a valid UUID)
+ * @param UuidInterface | string $ns The namespace (must be a valid UUID)
* @param string $name The name to use for creating a UUID
*
- * @return UuidInterface A UuidInterface instance that represents a
- * version 3 UUID
+ * @return UuidInterface A UuidInterface instance that represents a version 3 UUID
*
- * @psalm-suppress ImpureMethodCall we know that the factory being replaced can lead to massive
- * havoc across all consumers: that should never happen, and
- * is generally to be discouraged. Until the factory is kept
- * un-replaced, this method is effectively pure.
- *
- * @psalm-pure note: changing the internal factory is an edge case not covered by purity invariants,
- * but under constant factory setups, this method operates in functionally pure manners
+ * @pure
*/
public static function uuid3($ns, string $name): UuidInterface
{
+ /** @phpstan-ignore possiblyImpure.methodCall */
return self::getFactory()->uuid3($ns, $name);
}
/**
* Returns a version 4 (random) UUID
*
- * @return UuidInterface A UuidInterface instance that represents a
- * version 4 UUID
+ * @return UuidInterface A UuidInterface instance that represents a version 4 UUID
*/
public static function uuid4(): UuidInterface
{
@@ -620,40 +647,29 @@ class Uuid implements UuidInterface
}
/**
- * Returns a version 5 (name-based) UUID based on the SHA-1 hash of a
- * namespace ID and a name
+ * Returns a version 5 (name-based) UUID based on the SHA-1 hash of a namespace ID and a name
*
- * @param string|UuidInterface $ns The namespace (must be a valid UUID)
+ * @param UuidInterface | string $ns The namespace (must be a valid UUID)
* @param string $name The name to use for creating a UUID
*
- * @return UuidInterface A UuidInterface instance that represents a
- * version 5 UUID
+ * @return UuidInterface A UuidInterface instance that represents a version 5 UUID
*
- * @psalm-pure note: changing the internal factory is an edge case not covered by purity invariants,
- * but under constant factory setups, this method operates in functionally pure manners
- *
- * @psalm-suppress ImpureMethodCall we know that the factory being replaced can lead to massive
- * havoc across all consumers: that should never happen, and
- * is generally to be discouraged. Until the factory is kept
- * un-replaced, this method is effectively pure.
+ * @pure
*/
public static function uuid5($ns, string $name): UuidInterface
{
+ /** @phpstan-ignore possiblyImpure.methodCall */
return self::getFactory()->uuid5($ns, $name);
}
/**
- * Returns a version 6 (ordered-time) UUID from a host ID, sequence number,
- * and the current time
+ * Returns a version 6 (reordered Gregorian time) UUID from a host ID, sequence number, and the current time
*
- * @param Hexadecimal|null $node A 48-bit number representing the hardware
- * address
- * @param int $clockSeq A 14-bit number used to help avoid duplicates that
- * could arise when the clock is set backwards in time or if the node ID
- * changes
+ * @param Hexadecimal | null $node A 48-bit number representing the hardware address
+ * @param int | null $clockSeq A 14-bit number used to help avoid duplicates that could arise when the clock is set
+ * backwards in time or if the node ID changes
*
- * @return UuidInterface A UuidInterface instance that represents a
- * version 6 UUID
+ * @return UuidInterface A UuidInterface instance that represents a version 6 UUID
*/
public static function uuid6(
?Hexadecimal $node = null,
@@ -661,4 +677,54 @@ class Uuid implements UuidInterface
): UuidInterface {
return self::getFactory()->uuid6($node, $clockSeq);
}
+
+ /**
+ * Returns a version 7 (Unix Epoch time) UUID
+ *
+ * @param DateTimeInterface | null $dateTime An optional date/time from which to create the version 7 UUID. If not
+ * provided, the UUID is generated using the current date/time.
+ *
+ * @return UuidInterface A UuidInterface instance that represents a version 7 UUID
+ */
+ public static function uuid7(?DateTimeInterface $dateTime = null): UuidInterface
+ {
+ $factory = self::getFactory();
+
+ if (method_exists($factory, 'uuid7')) {
+ /** @var UuidInterface */
+ return $factory->uuid7($dateTime);
+ }
+
+ throw new UnsupportedOperationException('The provided factory does not support the uuid7() method');
+ }
+
+ /**
+ * Returns a version 8 (custom format) UUID
+ *
+ * The bytes provided may contain any value according to your application's needs. Be aware, however, that other
+ * applications may not understand the semantics of the value.
+ *
+ * @param string $bytes A 16-byte octet string. This is an open blob of data that you may fill with 128 bits of
+ * information. Be aware, however, bits 48 through 51 will be replaced with the UUID version field, and bits 64
+ * and 65 will be replaced with the UUID variant. You MUST NOT rely on these bits for your application needs.
+ *
+ * @return UuidInterface A UuidInterface instance that represents a version 8 UUID
+ *
+ * @pure
+ */
+ public static function uuid8(string $bytes): UuidInterface
+ {
+ /** @phpstan-ignore possiblyImpure.methodCall */
+ $factory = self::getFactory();
+
+ if (method_exists($factory, 'uuid8')) {
+ /**
+ * @var UuidInterface
+ * @phpstan-ignore possiblyImpure.methodCall
+ */
+ return $factory->uuid8($bytes);
+ }
+
+ throw new UnsupportedOperationException('The provided factory does not support the uuid8() method');
+ }
}
diff --git a/vendor/ramsey/uuid/src/UuidFactory.php b/vendor/ramsey/uuid/src/UuidFactory.php
index 6f2cea0..c7607a1 100644
--- a/vendor/ramsey/uuid/src/UuidFactory.php
+++ b/vendor/ramsey/uuid/src/UuidFactory.php
@@ -24,6 +24,7 @@ use Ramsey\Uuid\Generator\DefaultTimeGenerator;
use Ramsey\Uuid\Generator\NameGeneratorInterface;
use Ramsey\Uuid\Generator\RandomGeneratorInterface;
use Ramsey\Uuid\Generator\TimeGeneratorInterface;
+use Ramsey\Uuid\Generator\UnixTimeGenerator;
use Ramsey\Uuid\Lazy\LazyUuidFromString;
use Ramsey\Uuid\Provider\NodeProviderInterface;
use Ramsey\Uuid\Provider\Time\FixedTimeProvider;
@@ -45,61 +46,25 @@ use const STR_PAD_LEFT;
class UuidFactory implements UuidFactoryInterface
{
+ private CodecInterface $codec;
+ private DceSecurityGeneratorInterface $dceSecurityGenerator;
+ private NameGeneratorInterface $nameGenerator;
+ private NodeProviderInterface $nodeProvider;
+ private NumberConverterInterface $numberConverter;
+ private RandomGeneratorInterface $randomGenerator;
+ private TimeConverterInterface $timeConverter;
+ private TimeGeneratorInterface $timeGenerator;
+ private TimeGeneratorInterface $unixTimeGenerator;
+ private UuidBuilderInterface $uuidBuilder;
+ private ValidatorInterface $validator;
+
/**
- * @var CodecInterface
+ * @var bool whether the feature set was provided from outside, or we can operate under "default" assumptions
*/
- private $codec;
+ private bool $isDefaultFeatureSet;
/**
- * @var DceSecurityGeneratorInterface
- */
- private $dceSecurityGenerator;
-
- /**
- * @var NameGeneratorInterface
- */
- private $nameGenerator;
-
- /**
- * @var NodeProviderInterface
- */
- private $nodeProvider;
-
- /**
- * @var NumberConverterInterface
- */
- private $numberConverter;
-
- /**
- * @var RandomGeneratorInterface
- */
- private $randomGenerator;
-
- /**
- * @var TimeConverterInterface
- */
- private $timeConverter;
-
- /**
- * @var TimeGeneratorInterface
- */
- private $timeGenerator;
-
- /**
- * @var UuidBuilderInterface
- */
- private $uuidBuilder;
-
- /**
- * @var ValidatorInterface
- */
- private $validator;
-
- /** @var bool whether the feature set was provided from outside, or we can operate under "default" assumptions */
- private $isDefaultFeatureSet;
-
- /**
- * @param FeatureSet $features A set of available features in the current environment
+ * @param FeatureSet | null $features A set of available features in the current environment
*/
public function __construct(?FeatureSet $features = null)
{
@@ -117,6 +82,7 @@ class UuidFactory implements UuidFactoryInterface
$this->timeGenerator = $features->getTimeGenerator();
$this->uuidBuilder = $features->getBuilder();
$this->validator = $features->getValidator();
+ $this->unixTimeGenerator = $features->getUnixTimeGenerator();
}
/**
@@ -150,8 +116,7 @@ class UuidFactory implements UuidFactoryInterface
/**
* Sets the name generator to use for this factory
*
- * @param NameGeneratorInterface $nameGenerator A generator to generate
- * binary data, based on a namespace and name
+ * @param NameGeneratorInterface $nameGenerator A generator to generate binary data, based on a namespace and name
*/
public function setNameGenerator(NameGeneratorInterface $nameGenerator): void
{
@@ -187,8 +152,7 @@ class UuidFactory implements UuidFactoryInterface
/**
* Sets the time generator to use for this factory
*
- * @param TimeGeneratorInterface $generator A generator to generate binary
- * data, based on the time
+ * @param TimeGeneratorInterface $generator A generator to generate binary data, based on the time
*/
public function setTimeGenerator(TimeGeneratorInterface $generator): void
{
@@ -208,8 +172,8 @@ class UuidFactory implements UuidFactoryInterface
/**
* Sets the DCE Security generator to use for this factory
*
- * @param DceSecurityGeneratorInterface $generator A generator to generate
- * binary data, based on a local domain and local identifier
+ * @param DceSecurityGeneratorInterface $generator A generator to generate binary data, based on a local domain and
+ * local identifier
*/
public function setDceSecurityGenerator(DceSecurityGeneratorInterface $generator): void
{
@@ -229,8 +193,7 @@ class UuidFactory implements UuidFactoryInterface
/**
* Sets the random generator to use for this factory
*
- * @param RandomGeneratorInterface $generator A generator to generate binary
- * data, based on some random input
+ * @param RandomGeneratorInterface $generator A generator to generate binary data, based on some random input
*/
public function setRandomGenerator(RandomGeneratorInterface $generator): void
{
@@ -242,8 +205,8 @@ class UuidFactory implements UuidFactoryInterface
/**
* Sets the number converter to use for this factory
*
- * @param NumberConverterInterface $converter A converter to use for working
- * with large integers (i.e. integers greater than PHP_INT_MAX)
+ * @param NumberConverterInterface $converter A converter to use for working with large integers (i.e., integers
+ * greater than PHP_INT_MAX)
*/
public function setNumberConverter(NumberConverterInterface $converter): void
{
@@ -263,8 +226,7 @@ class UuidFactory implements UuidFactoryInterface
/**
* Sets the UUID builder to use for this factory
*
- * @param UuidBuilderInterface $builder A builder for constructing instances
- * of UuidInterface
+ * @param UuidBuilderInterface $builder A builder for constructing instances of UuidInterface
*/
public function setUuidBuilder(UuidBuilderInterface $builder): void
{
@@ -273,9 +235,6 @@ class UuidFactory implements UuidFactoryInterface
$this->uuidBuilder = $builder;
}
- /**
- * @psalm-mutation-free
- */
public function getValidator(): ValidatorInterface
{
return $this->validator;
@@ -284,8 +243,7 @@ class UuidFactory implements UuidFactoryInterface
/**
* Sets the validator to use for this factory
*
- * @param ValidatorInterface $validator A validator to use for validating
- * whether a string is a valid UUID
+ * @param ValidatorInterface $validator A validator to use for validating whether a string is a valid UUID
*/
public function setValidator(ValidatorInterface $validator): void
{
@@ -295,7 +253,7 @@ class UuidFactory implements UuidFactoryInterface
}
/**
- * @psalm-pure
+ * @pure
*/
public function fromBytes(string $bytes): UuidInterface
{
@@ -303,7 +261,7 @@ class UuidFactory implements UuidFactoryInterface
}
/**
- * @psalm-pure
+ * @pure
*/
public function fromString(string $uuid): UuidInterface
{
@@ -313,7 +271,7 @@ class UuidFactory implements UuidFactoryInterface
}
/**
- * @psalm-pure
+ * @pure
*/
public function fromInteger(string $integer): UuidInterface
{
@@ -326,23 +284,21 @@ class UuidFactory implements UuidFactoryInterface
public function fromDateTime(
DateTimeInterface $dateTime,
?Hexadecimal $node = null,
- ?int $clockSeq = null
+ ?int $clockSeq = null,
): UuidInterface {
- $timeProvider = new FixedTimeProvider(
- new Time($dateTime->format('U'), $dateTime->format('u'))
- );
+ $timeProvider = new FixedTimeProvider(new Time($dateTime->format('U'), $dateTime->format('u')));
+ $timeGenerator = new DefaultTimeGenerator($this->nodeProvider, $this->timeConverter, $timeProvider);
+ $bytes = $timeGenerator->generate($node?->toString(), $clockSeq);
- $timeGenerator = new DefaultTimeGenerator(
- $this->nodeProvider,
- $this->timeConverter,
- $timeProvider
- );
+ return $this->uuidFromBytesAndVersion($bytes, Uuid::UUID_TYPE_TIME);
+ }
- $nodeHex = $node ? $node->toString() : null;
-
- $bytes = $timeGenerator->generate($nodeHex, $clockSeq);
-
- return $this->uuidFromBytesAndVersion($bytes, 1);
+ /**
+ * @pure
+ */
+ public function fromHexadecimal(Hexadecimal $hex): UuidInterface
+ {
+ return $this->codec->decode($hex->__toString());
}
/**
@@ -352,81 +308,108 @@ class UuidFactory implements UuidFactoryInterface
{
$bytes = $this->timeGenerator->generate($node, $clockSeq);
- return $this->uuidFromBytesAndVersion($bytes, 1);
+ return $this->uuidFromBytesAndVersion($bytes, Uuid::UUID_TYPE_TIME);
}
public function uuid2(
int $localDomain,
?IntegerObject $localIdentifier = null,
?Hexadecimal $node = null,
- ?int $clockSeq = null
+ ?int $clockSeq = null,
): UuidInterface {
- $bytes = $this->dceSecurityGenerator->generate(
- $localDomain,
- $localIdentifier,
- $node,
- $clockSeq
- );
+ $bytes = $this->dceSecurityGenerator->generate($localDomain, $localIdentifier, $node, $clockSeq);
- return $this->uuidFromBytesAndVersion($bytes, 2);
+ return $this->uuidFromBytesAndVersion($bytes, Uuid::UUID_TYPE_DCE_SECURITY);
}
/**
* @inheritDoc
- * @psalm-pure
+ * @pure
*/
public function uuid3($ns, string $name): UuidInterface
{
- return $this->uuidFromNsAndName($ns, $name, 3, 'md5');
+ return $this->uuidFromNsAndName($ns, $name, Uuid::UUID_TYPE_HASH_MD5, 'md5');
}
public function uuid4(): UuidInterface
{
$bytes = $this->randomGenerator->generate(16);
- return $this->uuidFromBytesAndVersion($bytes, 4);
+ return $this->uuidFromBytesAndVersion($bytes, Uuid::UUID_TYPE_RANDOM);
}
/**
* @inheritDoc
- * @psalm-pure
+ * @pure
*/
public function uuid5($ns, string $name): UuidInterface
{
- return $this->uuidFromNsAndName($ns, $name, 5, 'sha1');
+ return $this->uuidFromNsAndName($ns, $name, Uuid::UUID_TYPE_HASH_SHA1, 'sha1');
}
public function uuid6(?Hexadecimal $node = null, ?int $clockSeq = null): UuidInterface
{
- $nodeHex = $node ? $node->toString() : null;
- $bytes = $this->timeGenerator->generate($nodeHex, $clockSeq);
+ $bytes = $this->timeGenerator->generate($node?->toString(), $clockSeq);
// Rearrange the bytes, according to the UUID version 6 specification.
$v6 = $bytes[6] . $bytes[7] . $bytes[4] . $bytes[5]
. $bytes[0] . $bytes[1] . $bytes[2] . $bytes[3];
$v6 = bin2hex($v6);
- // Drop the first four bits, while adding an empty four bits for the
- // version field. This allows us to reconstruct the correct time from
- // the bytes of this UUID.
+ // Drop the first four bits, while adding an empty four bits for the version field. This allows us to
+ // reconstruct the correct time from the bytes of this UUID.
$v6Bytes = hex2bin(substr($v6, 1, 12) . '0' . substr($v6, -3));
$v6Bytes .= substr($bytes, 8);
- return $this->uuidFromBytesAndVersion($v6Bytes, 6);
+ return $this->uuidFromBytesAndVersion($v6Bytes, Uuid::UUID_TYPE_REORDERED_TIME);
+ }
+
+ /**
+ * Returns a version 7 (Unix Epoch time) UUID
+ *
+ * @param DateTimeInterface | null $dateTime An optional date/time from which to create the version 7 UUID. If not
+ * provided, the UUID is generated using the current date/time.
+ *
+ * @return UuidInterface A UuidInterface instance that represents a version 7 UUID
+ */
+ public function uuid7(?DateTimeInterface $dateTime = null): UuidInterface
+ {
+ assert($this->unixTimeGenerator instanceof UnixTimeGenerator);
+ $bytes = $this->unixTimeGenerator->generate(null, null, $dateTime);
+
+ return $this->uuidFromBytesAndVersion($bytes, Uuid::UUID_TYPE_UNIX_TIME);
+ }
+
+ /**
+ * Returns a version 8 (custom format) UUID
+ *
+ * The bytes provided may contain any value according to your application's needs. Be aware, however, that other
+ * applications may not understand the semantics of the value.
+ *
+ * @param string $bytes A 16-byte octet string. This is an open blob of data that you may fill with 128 bits of
+ * information. Be aware, however, bits 48 through 51 will be replaced with the UUID version field, and bits 64
+ * and 65 will be replaced with the UUID variant. You MUST NOT rely on these bits for your application needs.
+ *
+ * @return UuidInterface A UuidInterface instance that represents a version 8 UUID
+ *
+ * @pure
+ */
+ public function uuid8(string $bytes): UuidInterface
+ {
+ /** @phpstan-ignore possiblyImpure.methodCall */
+ return $this->uuidFromBytesAndVersion($bytes, Uuid::UUID_TYPE_CUSTOM);
}
/**
* Returns a Uuid created from the provided byte string
*
- * Uses the configured builder and codec and the provided byte string to
- * construct a Uuid object.
+ * Uses the configured builder and codec and the provided byte string to construct a Uuid object.
*
* @param string $bytes The byte string from which to construct a UUID
*
- * @return UuidInterface An instance of UuidInterface, created from the
- * provided bytes
+ * @return UuidInterface An instance of UuidInterface, created from the provided bytes
*
- * @psalm-pure
+ * @pure
*/
public function uuid(string $bytes): UuidInterface
{
@@ -436,49 +419,49 @@ class UuidFactory implements UuidFactoryInterface
/**
* Returns a version 3 or 5 namespaced Uuid
*
- * @param string|UuidInterface $ns The namespace (must be a valid UUID)
+ * @param UuidInterface | string $ns The namespace (must be a valid UUID)
* @param string $name The name to hash together with the namespace
* @param int $version The version of UUID to create (3 or 5)
- * @param string $hashAlgorithm The hashing algorithm to use when hashing
- * together the namespace and name
+ * @param string $hashAlgorithm The hashing algorithm to use when hashing together the namespace and name
*
- * @return UuidInterface An instance of UuidInterface, created by hashing
- * together the provided namespace and name
+ * @return UuidInterface An instance of UuidInterface, created by hashing together the provided namespace and name
*
- * @psalm-pure
+ * @pure
*/
- private function uuidFromNsAndName($ns, string $name, int $version, string $hashAlgorithm): UuidInterface
- {
+ private function uuidFromNsAndName(
+ UuidInterface | string $ns,
+ string $name,
+ int $version,
+ string $hashAlgorithm,
+ ): UuidInterface {
if (!($ns instanceof UuidInterface)) {
$ns = $this->fromString($ns);
}
$bytes = $this->nameGenerator->generate($ns, $name, $hashAlgorithm);
+ /** @phpstan-ignore possiblyImpure.methodCall */
return $this->uuidFromBytesAndVersion(substr($bytes, 0, 16), $version);
}
/**
- * Returns an RFC 4122 variant Uuid, created from the provided bytes and version
+ * Returns a Uuid created from the provided bytes and version
*
* @param string $bytes The byte string to convert to a UUID
- * @param int $version The RFC 4122 version to apply to the UUID
+ * @param int $version The version to apply to the UUID
*
- * @return UuidInterface An instance of UuidInterface, created from the
- * byte string and version
- *
- * @psalm-pure
+ * @return UuidInterface An instance of UuidInterface, created from the byte string and version
*/
private function uuidFromBytesAndVersion(string $bytes, int $version): UuidInterface
{
- /** @var array $unpackedTime */
+ /** @var int[] $unpackedTime */
$unpackedTime = unpack('n*', substr($bytes, 6, 2));
- $timeHi = (int) $unpackedTime[1];
+ $timeHi = $unpackedTime[1];
$timeHiAndVersion = pack('n*', BinaryUtils::applyVersion($timeHi, $version));
- /** @var array $unpackedClockSeq */
+ /** @var int[] $unpackedClockSeq */
$unpackedClockSeq = unpack('n*', substr($bytes, 8, 2));
- $clockSeqHi = (int) $unpackedClockSeq[1];
+ $clockSeqHi = $unpackedClockSeq[1];
$clockSeqHiAndReserved = pack('n*', BinaryUtils::applyVariant($clockSeqHi));
$bytes = substr_replace($bytes, $timeHiAndVersion, 6, 2);
diff --git a/vendor/ramsey/uuid/src/UuidFactoryInterface.php b/vendor/ramsey/uuid/src/UuidFactoryInterface.php
index 468cc63..5a83a79 100644
--- a/vendor/ramsey/uuid/src/UuidFactoryInterface.php
+++ b/vendor/ramsey/uuid/src/UuidFactoryInterface.php
@@ -20,163 +20,136 @@ use Ramsey\Uuid\Type\Integer as IntegerObject;
use Ramsey\Uuid\Validator\ValidatorInterface;
/**
- * UuidFactoryInterface defines common functionality all `UuidFactory` instances
- * must implement
+ * UuidFactoryInterface defines the common functionality all `UuidFactory` instances must implement
*/
interface UuidFactoryInterface
{
- /**
- * Returns the validator to use for the factory
- *
- * @psalm-mutation-free
- */
- public function getValidator(): ValidatorInterface;
-
- /**
- * Returns a version 1 (time-based) UUID from a host ID, sequence number,
- * and the current time
- *
- * @param Hexadecimal|int|string|null $node A 48-bit number representing the
- * hardware address; this number may be represented as an integer or a
- * hexadecimal string
- * @param int|null $clockSeq A 14-bit number used to help avoid duplicates
- * that could arise when the clock is set backwards in time or if the
- * node ID changes
- *
- * @return UuidInterface A UuidInterface instance that represents a
- * version 1 UUID
- */
- public function uuid1($node = null, ?int $clockSeq = null): UuidInterface;
-
- /**
- * Returns a version 2 (DCE Security) UUID from a local domain, local
- * identifier, host ID, clock sequence, and the current time
- *
- * @param int $localDomain The local domain to use when generating bytes,
- * according to DCE Security
- * @param IntegerObject|null $localIdentifier The local identifier for the
- * given domain; this may be a UID or GID on POSIX systems, if the local
- * domain is person or group, or it may be a site-defined identifier
- * if the local domain is org
- * @param Hexadecimal|null $node A 48-bit number representing the hardware
- * address
- * @param int|null $clockSeq A 14-bit number used to help avoid duplicates
- * that could arise when the clock is set backwards in time or if the
- * node ID changes
- *
- * @return UuidInterface A UuidInterface instance that represents a
- * version 2 UUID
- */
- public function uuid2(
- int $localDomain,
- ?IntegerObject $localIdentifier = null,
- ?Hexadecimal $node = null,
- ?int $clockSeq = null
- ): UuidInterface;
-
- /**
- * Returns a version 3 (name-based) UUID based on the MD5 hash of a
- * namespace ID and a name
- *
- * @param string|UuidInterface $ns The namespace (must be a valid UUID)
- * @param string $name The name to use for creating a UUID
- *
- * @return UuidInterface A UuidInterface instance that represents a
- * version 3 UUID
- *
- * @psalm-pure
- */
- public function uuid3($ns, string $name): UuidInterface;
-
- /**
- * Returns a version 4 (random) UUID
- *
- * @return UuidInterface A UuidInterface instance that represents a
- * version 4 UUID
- */
- public function uuid4(): UuidInterface;
-
- /**
- * Returns a version 5 (name-based) UUID based on the SHA-1 hash of a
- * namespace ID and a name
- *
- * @param string|UuidInterface $ns The namespace (must be a valid UUID)
- * @param string $name The name to use for creating a UUID
- *
- * @return UuidInterface A UuidInterface instance that represents a
- * version 5 UUID
- *
- * @psalm-pure
- */
- public function uuid5($ns, string $name): UuidInterface;
-
- /**
- * Returns a version 6 (ordered-time) UUID from a host ID, sequence number,
- * and the current time
- *
- * @param Hexadecimal|null $node A 48-bit number representing the hardware
- * address
- * @param int|null $clockSeq A 14-bit number used to help avoid duplicates
- * that could arise when the clock is set backwards in time or if the
- * node ID changes
- *
- * @return UuidInterface A UuidInterface instance that represents a
- * version 6 UUID
- */
- public function uuid6(?Hexadecimal $node = null, ?int $clockSeq = null): UuidInterface;
-
/**
* Creates a UUID from a byte string
*
* @param string $bytes A binary string
*
- * @return UuidInterface A UuidInterface instance created from a binary
- * string representation
+ * @return UuidInterface A UuidInterface instance created from a binary string representation
*
- * @psalm-pure
+ * @pure
*/
public function fromBytes(string $bytes): UuidInterface;
/**
- * Creates a UUID from the string standard representation
+ * Creates a UUID from a DateTimeInterface instance
*
- * @param string $uuid A hexadecimal string
+ * @param DateTimeInterface $dateTime The date and time
+ * @param Hexadecimal | null $node A 48-bit number representing the hardware address
+ * @param int | null $clockSeq A 14-bit number used to help avoid duplicates that could arise when the clock is set
+ * backwards in time or if the node ID changes
*
- * @return UuidInterface A UuidInterface instance created from a hexadecimal
- * string representation
- *
- * @psalm-pure
+ * @return UuidInterface A UuidInterface instance that represents a version 1 UUID created from a DateTimeInterface instance
*/
- public function fromString(string $uuid): UuidInterface;
+ public function fromDateTime(
+ DateTimeInterface $dateTime,
+ ?Hexadecimal $node = null,
+ ?int $clockSeq = null,
+ ): UuidInterface;
/**
* Creates a UUID from a 128-bit integer string
*
* @param string $integer String representation of 128-bit integer
*
- * @return UuidInterface A UuidInterface instance created from the string
- * representation of a 128-bit integer
+ * @return UuidInterface A UuidInterface instance created from the string representation of a 128-bit integer
*
- * @psalm-pure
+ * @pure
*/
public function fromInteger(string $integer): UuidInterface;
/**
- * Creates a UUID from a DateTimeInterface instance
+ * Creates a UUID from the string standard representation
*
- * @param DateTimeInterface $dateTime The date and time
- * @param Hexadecimal|null $node A 48-bit number representing the hardware
- * address
- * @param int|null $clockSeq A 14-bit number used to help avoid duplicates
- * that could arise when the clock is set backwards in time or if the
- * node ID changes
+ * @param string $uuid A hexadecimal string
*
- * @return UuidInterface A UuidInterface instance that represents a
- * version 1 UUID created from a DateTimeInterface instance
+ * @return UuidInterface A UuidInterface instance created from a hexadecimal string representation
+ *
+ * @pure
*/
- public function fromDateTime(
- DateTimeInterface $dateTime,
+ public function fromString(string $uuid): UuidInterface;
+
+ /**
+ * Returns the validator used by the factory
+ */
+ public function getValidator(): ValidatorInterface;
+
+ /**
+ * Returns a version 1 (Gregorian time) UUID from a host ID, sequence number, and the current time
+ *
+ * @param Hexadecimal | int | string | null $node A 48-bit number representing the hardware address; this number may
+ * be represented as an integer or a hexadecimal string
+ * @param int | null $clockSeq A 14-bit number used to help avoid duplicates that could arise when the clock is set
+ * backwards in time or if the node ID changes
+ *
+ * @return UuidInterface A UuidInterface instance that represents a version 1 UUID
+ */
+ public function uuid1($node = null, ?int $clockSeq = null): UuidInterface;
+
+ /**
+ * Returns a version 2 (DCE Security) UUID from a local domain, local identifier, host ID, clock sequence, and the
+ * current time
+ *
+ * @param int $localDomain The local domain to use when generating bytes, according to DCE Security
+ * @param IntegerObject | null $localIdentifier The local identifier for the given domain; this may be a UID or GID
+ * on POSIX systems, if the local domain is a person or group, or it may be a site-defined identifier if the
+ * local domain is org
+ * @param Hexadecimal | null $node A 48-bit number representing the hardware address
+ * @param int | null $clockSeq A 14-bit number used to help avoid duplicates that could arise when the clock is set
+ * backwards in time or if the node ID changes
+ *
+ * @return UuidInterface A UuidInterface instance that represents a version 2 UUID
+ */
+ public function uuid2(
+ int $localDomain,
+ ?IntegerObject $localIdentifier = null,
?Hexadecimal $node = null,
- ?int $clockSeq = null
+ ?int $clockSeq = null,
): UuidInterface;
+
+ /**
+ * Returns a version 3 (name-based) UUID based on the MD5 hash of a namespace ID and a name
+ *
+ * @param UuidInterface | string $ns The namespace (must be a valid UUID)
+ * @param string $name The name to use for creating a UUID
+ *
+ * @return UuidInterface A UuidInterface instance that represents a version 3 UUID
+ *
+ * @pure
+ */
+ public function uuid3($ns, string $name): UuidInterface;
+
+ /**
+ * Returns a version 4 (random) UUID
+ *
+ * @return UuidInterface A UuidInterface instance that represents a version 4 UUID
+ */
+ public function uuid4(): UuidInterface;
+
+ /**
+ * Returns a version 5 (name-based) UUID based on the SHA-1 hash of a namespace ID and a name
+ *
+ * @param UuidInterface | string $ns The namespace (must be a valid UUID)
+ * @param string $name The name to use for creating a UUID
+ *
+ * @return UuidInterface A UuidInterface instance that represents a version 5 UUID
+ *
+ * @pure
+ */
+ public function uuid5($ns, string $name): UuidInterface;
+
+ /**
+ * Returns a version 6 (reordered Gregorian time) UUID from a host ID, sequence number, and the current time
+ *
+ * @param Hexadecimal | null $node A 48-bit number representing the hardware address
+ * @param int | null $clockSeq A 14-bit number used to help avoid duplicates that could arise when the clock is set
+ * backwards in time or if the node ID changes
+ *
+ * @return UuidInterface A UuidInterface instance that represents a version 6 UUID
+ */
+ public function uuid6(?Hexadecimal $node = null, ?int $clockSeq = null): UuidInterface;
}
diff --git a/vendor/ramsey/uuid/src/UuidInterface.php b/vendor/ramsey/uuid/src/UuidInterface.php
index f22eb0f..38525cb 100644
--- a/vendor/ramsey/uuid/src/UuidInterface.php
+++ b/vendor/ramsey/uuid/src/UuidInterface.php
@@ -19,43 +19,38 @@ use Ramsey\Uuid\Fields\FieldsInterface;
use Ramsey\Uuid\Type\Hexadecimal;
use Ramsey\Uuid\Type\Integer as IntegerObject;
use Serializable;
+use Stringable;
/**
- * A UUID is a universally unique identifier adhering to an agreed-upon
- * representation format and standard for generation
+ * A UUID is a universally unique identifier adhering to an agreed-upon representation format and standard for generation
*
- * @psalm-immutable
+ * @immutable
*/
interface UuidInterface extends
DeprecatedUuidInterface,
JsonSerializable,
- Serializable
+ Serializable,
+ Stringable
{
/**
- * Returns -1, 0, or 1 if the UUID is less than, equal to, or greater than
- * the other UUID
+ * Returns -1, 0, or 1 if the UUID is less than, equal to, or greater than the other UUID
*
- * The first of two UUIDs is greater than the second if the most
- * significant field in which the UUIDs differ is greater for the first
- * UUID.
- *
- * * Q. What's the value of being able to sort UUIDs?
- * * A. Use them as keys in a B-Tree or similar mapping.
+ * The first of two UUIDs is greater than the second if the most significant field in which the UUIDs differ is
+ * greater for the first UUID.
*
* @param UuidInterface $other The UUID to compare
*
- * @return int -1, 0, or 1 if the UUID is less than, equal to, or greater than $other
+ * @return int<-1,1> -1, 0, or 1 if the UUID is less than, equal to, or greater than $other
*/
public function compareTo(UuidInterface $other): int;
/**
* Returns true if the UUID is equal to the provided object
*
- * The result is true if and only if the argument is not null, is a UUID
- * object, has the same variant, and contains the same value, bit for bit,
- * as the UUID.
+ * The result is true if and only if the argument is not null, is a UUID object, has the same variant, and contains
+ * the same value, bit-for-bit, as the UUID.
*
- * @param object|null $other An object to test for equality with this UUID
+ * @param object | null $other An object to test for equality with this UUID
*
* @return bool True if the other object is equal to this UUID
*/
@@ -64,7 +59,9 @@ interface UuidInterface extends
/**
* Returns the binary string representation of the UUID
*
- * @psalm-return non-empty-string
+ * @return non-empty-string
+ *
+ * @pure
*/
public function getBytes(): string;
@@ -83,17 +80,31 @@ interface UuidInterface extends
*/
public function getInteger(): IntegerObject;
+ /**
+ * Returns the string standard representation of the UUID as a URN
+ *
+ * @link http://en.wikipedia.org/wiki/Uniform_Resource_Name Uniform Resource Name
+ * @link https://www.rfc-editor.org/rfc/rfc9562.html#section-4 RFC 9562, 4. UUID Format
+ * @link https://www.rfc-editor.org/rfc/rfc9562.html#section-7 RFC 9562, 7. IANA Considerations
+ * @link https://www.rfc-editor.org/rfc/rfc4122.html#section-3 RFC 4122, 3. Namespace Registration Template
+ */
+ public function getUrn(): string;
+
/**
* Returns the string standard representation of the UUID
*
- * @psalm-return non-empty-string
+ * @return non-empty-string
+ *
+ * @pure
*/
public function toString(): string;
/**
* Casts the UUID to the string standard representation
*
- * @psalm-return non-empty-string
+ * @return non-empty-string
+ *
+ * @pure
*/
public function __toString(): string;
}
diff --git a/vendor/ramsey/uuid/src/Validator/GenericValidator.php b/vendor/ramsey/uuid/src/Validator/GenericValidator.php
index fd60955..6d60647 100644
--- a/vendor/ramsey/uuid/src/Validator/GenericValidator.php
+++ b/vendor/ramsey/uuid/src/Validator/GenericValidator.php
@@ -22,7 +22,7 @@ use function str_replace;
/**
* GenericValidator validates strings as UUIDs of any variant
*
- * @psalm-immutable
+ * @immutable
*/
final class GenericValidator implements ValidatorInterface
{
@@ -32,9 +32,7 @@ final class GenericValidator implements ValidatorInterface
private const VALID_PATTERN = '\A[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}\z';
/**
- * @psalm-return non-empty-string
- * @psalm-suppress MoreSpecificReturnType we know that the retrieved `string` is never empty
- * @psalm-suppress LessSpecificReturnStatement we know that the retrieved `string` is never empty
+ * @return non-empty-string
*/
public function getPattern(): string
{
@@ -43,8 +41,10 @@ final class GenericValidator implements ValidatorInterface
public function validate(string $uuid): bool
{
+ /** @phpstan-ignore possiblyImpure.functionCall */
$uuid = str_replace(['urn:', 'uuid:', 'URN:', 'UUID:', '{', '}'], '', $uuid);
+ /** @phpstan-ignore possiblyImpure.functionCall */
return $uuid === Uuid::NIL || preg_match('/' . self::VALID_PATTERN . '/Dms', $uuid);
}
}
diff --git a/vendor/ramsey/uuid/src/Validator/ValidatorInterface.php b/vendor/ramsey/uuid/src/Validator/ValidatorInterface.php
index 3d4bd6f..95dc8eb 100644
--- a/vendor/ramsey/uuid/src/Validator/ValidatorInterface.php
+++ b/vendor/ramsey/uuid/src/Validator/ValidatorInterface.php
@@ -17,16 +17,14 @@ namespace Ramsey\Uuid\Validator;
/**
* A validator validates a string as a proper UUID
*
- * @psalm-immutable
+ * @immutable
*/
interface ValidatorInterface
{
/**
* Returns the regular expression pattern used by this validator
*
- * @return string The regular expression pattern this validator uses
- *
- * @psalm-return non-empty-string
+ * @return non-empty-string The regular expression pattern this validator uses
*/
public function getPattern(): string;
@@ -36,6 +34,8 @@ interface ValidatorInterface
* @param string $uuid The string to validate as a UUID
*
* @return bool True if the string is a valid UUID, false otherwise
+ *
+ * @pure
*/
public function validate(string $uuid): bool;
}
diff --git a/vendor/ramsey/uuid/src/functions.php b/vendor/ramsey/uuid/src/functions.php
index f5df148..854c5c5 100644
--- a/vendor/ramsey/uuid/src/functions.php
+++ b/vendor/ramsey/uuid/src/functions.php
@@ -15,19 +15,17 @@ declare(strict_types=1);
namespace Ramsey\Uuid;
+use DateTimeInterface;
use Ramsey\Uuid\Type\Hexadecimal;
use Ramsey\Uuid\Type\Integer as IntegerObject;
/**
- * Returns a version 1 (time-based) UUID from a host ID, sequence number,
- * and the current time
+ * Returns a version 1 (Gregorian time) UUID from a host ID, sequence number, and the current time
*
- * @param Hexadecimal|int|string|null $node A 48-bit number representing the
- * hardware address; this number may be represented as an integer or a
- * hexadecimal string
- * @param int $clockSeq A 14-bit number used to help avoid duplicates that
- * could arise when the clock is set backwards in time or if the node ID
- * changes
+ * @param Hexadecimal | int | string | null $node A 48-bit number representing the hardware address; this number may be
+ * represented as an integer or a hexadecimal string
+ * @param int | null $clockSeq A 14-bit number used to help avoid duplicates that could arise when the clock is set
+ * backwards in time or if the node ID changes
*
* @return non-empty-string Version 1 UUID as a string
*/
@@ -37,20 +35,15 @@ function v1($node = null, ?int $clockSeq = null): string
}
/**
- * Returns a version 2 (DCE Security) UUID from a local domain, local
- * identifier, host ID, clock sequence, and the current time
+ * Returns a version 2 (DCE Security) UUID from a local domain, local identifier, host ID, clock sequence, and the current time
*
- * @param int $localDomain The local domain to use when generating bytes,
- * according to DCE Security
- * @param IntegerObject|null $localIdentifier The local identifier for the
- * given domain; this may be a UID or GID on POSIX systems, if the local
- * domain is person or group, or it may be a site-defined identifier
- * if the local domain is org
- * @param Hexadecimal|null $node A 48-bit number representing the hardware
- * address
- * @param int|null $clockSeq A 14-bit number used to help avoid duplicates
- * that could arise when the clock is set backwards in time or if the
- * node ID changes
+ * @param int $localDomain The local domain to use when generating bytes, according to DCE Security
+ * @param IntegerObject | null $localIdentifier The local identifier for the given domain; this may be a UID or GID on
+ * POSIX systems, if the local domain is a person or group, or it may be a site-defined identifier if the local
+ * domain is org
+ * @param Hexadecimal | null $node A 48-bit number representing the hardware address
+ * @param int | null $clockSeq A 14-bit number used to help avoid duplicates that could arise when the clock is set
+ * backwards in time or if the node ID changes
*
* @return non-empty-string Version 2 UUID as a string
*/
@@ -58,21 +51,19 @@ function v2(
int $localDomain,
?IntegerObject $localIdentifier = null,
?Hexadecimal $node = null,
- ?int $clockSeq = null
+ ?int $clockSeq = null,
): string {
return Uuid::uuid2($localDomain, $localIdentifier, $node, $clockSeq)->toString();
}
/**
- * Returns a version 3 (name-based) UUID based on the MD5 hash of a
- * namespace ID and a name
+ * Returns a version 3 (name-based) UUID based on the MD5 hash of a namespace ID and a name
*
- * @param string|UuidInterface $ns The namespace (must be a valid UUID)
+ * @param UuidInterface | string $ns The namespace (must be a valid UUID)
*
* @return non-empty-string Version 3 UUID as a string
*
- * @psalm-pure note: changing the internal factory is an edge case not covered by purity invariants,
- * but under constant factory setups, this method operates in functionally pure manners
+ * @pure
*/
function v3($ns, string $name): string
{
@@ -90,15 +81,13 @@ function v4(): string
}
/**
- * Returns a version 5 (name-based) UUID based on the SHA-1 hash of a
- * namespace ID and a name
+ * Returns a version 5 (name-based) UUID based on the SHA-1 hash of a namespace ID and a name
*
- * @param string|UuidInterface $ns The namespace (must be a valid UUID)
+ * @param UuidInterface | string $ns The namespace (must be a valid UUID)
*
* @return non-empty-string Version 5 UUID as a string
*
- * @psalm-pure note: changing the internal factory is an edge case not covered by purity invariants,
- * but under constant factory setups, this method operates in functionally pure manners
+ * @pure
*/
function v5($ns, string $name): string
{
@@ -106,14 +95,11 @@ function v5($ns, string $name): string
}
/**
- * Returns a version 6 (ordered-time) UUID from a host ID, sequence number,
- * and the current time
+ * Returns a version 6 (reordered Gregorian time) UUID from a host ID, sequence number, and the current time
*
- * @param Hexadecimal|null $node A 48-bit number representing the hardware
- * address
- * @param int $clockSeq A 14-bit number used to help avoid duplicates that
- * could arise when the clock is set backwards in time or if the node ID
- * changes
+ * @param Hexadecimal | null $node A 48-bit number representing the hardware address
+ * @param int | null $clockSeq A 14-bit number used to help avoid duplicates that could arise when the clock is set
+ * backwards in time or if the node ID changes
*
* @return non-empty-string Version 6 UUID as a string
*/
@@ -121,3 +107,35 @@ function v6(?Hexadecimal $node = null, ?int $clockSeq = null): string
{
return Uuid::uuid6($node, $clockSeq)->toString();
}
+
+/**
+ * Returns a version 7 (Unix Epoch time) UUID
+ *
+ * @param DateTimeInterface|null $dateTime An optional date/time from which to create the version 7 UUID. If not
+ * provided, the UUID is generated using the current date/time.
+ *
+ * @return non-empty-string Version 7 UUID as a string
+ */
+function v7(?DateTimeInterface $dateTime = null): string
+{
+ return Uuid::uuid7($dateTime)->toString();
+}
+
+/**
+ * Returns a version 8 (custom format) UUID
+ *
+ * The bytes provided may contain any value according to your application's needs. Be aware, however, that other
+ * applications may not understand the semantics of the value.
+ *
+ * @param string $bytes A 16-byte octet string. This is an open blob of data that you may fill with 128 bits of
+ * information. Be aware, however, bits 48 through 51 will be replaced with the UUID version field, and bits 64 and
+ * 65 will be replaced with the UUID variant. You MUST NOT rely on these bits for your application needs.
+ *
+ * @return non-empty-string Version 8 UUID as a string
+ *
+ * @pure
+ */
+function v8(string $bytes): string
+{
+ return Uuid::uuid8($bytes)->toString();
+}
diff --git a/vendor/symfony/polyfill-ctype/Ctype.php b/vendor/symfony/polyfill-ctype/Ctype.php
deleted file mode 100644
index ba75a2c..0000000
--- a/vendor/symfony/polyfill-ctype/Ctype.php
+++ /dev/null
@@ -1,232 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Polyfill\Ctype;
-
-/**
- * Ctype implementation through regex.
- *
- * @internal
- *
- * @author Gert de Pagter
- */
-final class Ctype
-{
- /**
- * Returns TRUE if every character in text is either a letter or a digit, FALSE otherwise.
- *
- * @see https://php.net/ctype-alnum
- *
- * @param mixed $text
- *
- * @return bool
- */
- public static function ctype_alnum($text)
- {
- $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__);
-
- return \is_string($text) && '' !== $text && !preg_match('/[^A-Za-z0-9]/', $text);
- }
-
- /**
- * Returns TRUE if every character in text is a letter, FALSE otherwise.
- *
- * @see https://php.net/ctype-alpha
- *
- * @param mixed $text
- *
- * @return bool
- */
- public static function ctype_alpha($text)
- {
- $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__);
-
- return \is_string($text) && '' !== $text && !preg_match('/[^A-Za-z]/', $text);
- }
-
- /**
- * Returns TRUE if every character in text is a control character from the current locale, FALSE otherwise.
- *
- * @see https://php.net/ctype-cntrl
- *
- * @param mixed $text
- *
- * @return bool
- */
- public static function ctype_cntrl($text)
- {
- $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__);
-
- return \is_string($text) && '' !== $text && !preg_match('/[^\x00-\x1f\x7f]/', $text);
- }
-
- /**
- * Returns TRUE if every character in the string text is a decimal digit, FALSE otherwise.
- *
- * @see https://php.net/ctype-digit
- *
- * @param mixed $text
- *
- * @return bool
- */
- public static function ctype_digit($text)
- {
- $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__);
-
- return \is_string($text) && '' !== $text && !preg_match('/[^0-9]/', $text);
- }
-
- /**
- * Returns TRUE if every character in text is printable and actually creates visible output (no white space), FALSE otherwise.
- *
- * @see https://php.net/ctype-graph
- *
- * @param mixed $text
- *
- * @return bool
- */
- public static function ctype_graph($text)
- {
- $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__);
-
- return \is_string($text) && '' !== $text && !preg_match('/[^!-~]/', $text);
- }
-
- /**
- * Returns TRUE if every character in text is a lowercase letter.
- *
- * @see https://php.net/ctype-lower
- *
- * @param mixed $text
- *
- * @return bool
- */
- public static function ctype_lower($text)
- {
- $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__);
-
- return \is_string($text) && '' !== $text && !preg_match('/[^a-z]/', $text);
- }
-
- /**
- * Returns TRUE if every character in text will actually create output (including blanks). Returns FALSE if text contains control characters or characters that do not have any output or control function at all.
- *
- * @see https://php.net/ctype-print
- *
- * @param mixed $text
- *
- * @return bool
- */
- public static function ctype_print($text)
- {
- $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__);
-
- return \is_string($text) && '' !== $text && !preg_match('/[^ -~]/', $text);
- }
-
- /**
- * Returns TRUE if every character in text is printable, but neither letter, digit or blank, FALSE otherwise.
- *
- * @see https://php.net/ctype-punct
- *
- * @param mixed $text
- *
- * @return bool
- */
- public static function ctype_punct($text)
- {
- $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__);
-
- return \is_string($text) && '' !== $text && !preg_match('/[^!-\/\:-@\[-`\{-~]/', $text);
- }
-
- /**
- * Returns TRUE if every character in text creates some sort of white space, FALSE otherwise. Besides the blank character this also includes tab, vertical tab, line feed, carriage return and form feed characters.
- *
- * @see https://php.net/ctype-space
- *
- * @param mixed $text
- *
- * @return bool
- */
- public static function ctype_space($text)
- {
- $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__);
-
- return \is_string($text) && '' !== $text && !preg_match('/[^\s]/', $text);
- }
-
- /**
- * Returns TRUE if every character in text is an uppercase letter.
- *
- * @see https://php.net/ctype-upper
- *
- * @param mixed $text
- *
- * @return bool
- */
- public static function ctype_upper($text)
- {
- $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__);
-
- return \is_string($text) && '' !== $text && !preg_match('/[^A-Z]/', $text);
- }
-
- /**
- * Returns TRUE if every character in text is a hexadecimal 'digit', that is a decimal digit or a character from [A-Fa-f] , FALSE otherwise.
- *
- * @see https://php.net/ctype-xdigit
- *
- * @param mixed $text
- *
- * @return bool
- */
- public static function ctype_xdigit($text)
- {
- $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__);
-
- return \is_string($text) && '' !== $text && !preg_match('/[^A-Fa-f0-9]/', $text);
- }
-
- /**
- * Converts integers to their char versions according to normal ctype behaviour, if needed.
- *
- * If an integer between -128 and 255 inclusive is provided,
- * it is interpreted as the ASCII value of a single character
- * (negative values have 256 added in order to allow characters in the Extended ASCII range).
- * Any other integer is interpreted as a string containing the decimal digits of the integer.
- *
- * @param mixed $int
- * @param string $function
- *
- * @return mixed
- */
- private static function convert_int_to_char_for_ctype($int, $function)
- {
- if (!\is_int($int)) {
- return $int;
- }
-
- if ($int < -128 || $int > 255) {
- return (string) $int;
- }
-
- if (\PHP_VERSION_ID >= 80100) {
- @trigger_error($function.'(): Argument of type int will be interpreted as string in the future', \E_USER_DEPRECATED);
- }
-
- if ($int < 0) {
- $int += 256;
- }
-
- return \chr($int);
- }
-}
diff --git a/vendor/symfony/polyfill-ctype/LICENSE b/vendor/symfony/polyfill-ctype/LICENSE
deleted file mode 100644
index 7536cae..0000000
--- a/vendor/symfony/polyfill-ctype/LICENSE
+++ /dev/null
@@ -1,19 +0,0 @@
-Copyright (c) 2018-present Fabien Potencier
-
-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.
diff --git a/vendor/symfony/polyfill-ctype/bootstrap.php b/vendor/symfony/polyfill-ctype/bootstrap.php
deleted file mode 100644
index d54524b..0000000
--- a/vendor/symfony/polyfill-ctype/bootstrap.php
+++ /dev/null
@@ -1,50 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-use Symfony\Polyfill\Ctype as p;
-
-if (\PHP_VERSION_ID >= 80000) {
- return require __DIR__.'/bootstrap80.php';
-}
-
-if (!function_exists('ctype_alnum')) {
- function ctype_alnum($text) { return p\Ctype::ctype_alnum($text); }
-}
-if (!function_exists('ctype_alpha')) {
- function ctype_alpha($text) { return p\Ctype::ctype_alpha($text); }
-}
-if (!function_exists('ctype_cntrl')) {
- function ctype_cntrl($text) { return p\Ctype::ctype_cntrl($text); }
-}
-if (!function_exists('ctype_digit')) {
- function ctype_digit($text) { return p\Ctype::ctype_digit($text); }
-}
-if (!function_exists('ctype_graph')) {
- function ctype_graph($text) { return p\Ctype::ctype_graph($text); }
-}
-if (!function_exists('ctype_lower')) {
- function ctype_lower($text) { return p\Ctype::ctype_lower($text); }
-}
-if (!function_exists('ctype_print')) {
- function ctype_print($text) { return p\Ctype::ctype_print($text); }
-}
-if (!function_exists('ctype_punct')) {
- function ctype_punct($text) { return p\Ctype::ctype_punct($text); }
-}
-if (!function_exists('ctype_space')) {
- function ctype_space($text) { return p\Ctype::ctype_space($text); }
-}
-if (!function_exists('ctype_upper')) {
- function ctype_upper($text) { return p\Ctype::ctype_upper($text); }
-}
-if (!function_exists('ctype_xdigit')) {
- function ctype_xdigit($text) { return p\Ctype::ctype_xdigit($text); }
-}
diff --git a/vendor/symfony/polyfill-ctype/bootstrap80.php b/vendor/symfony/polyfill-ctype/bootstrap80.php
deleted file mode 100644
index ab2f861..0000000
--- a/vendor/symfony/polyfill-ctype/bootstrap80.php
+++ /dev/null
@@ -1,46 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-use Symfony\Polyfill\Ctype as p;
-
-if (!function_exists('ctype_alnum')) {
- function ctype_alnum(mixed $text): bool { return p\Ctype::ctype_alnum($text); }
-}
-if (!function_exists('ctype_alpha')) {
- function ctype_alpha(mixed $text): bool { return p\Ctype::ctype_alpha($text); }
-}
-if (!function_exists('ctype_cntrl')) {
- function ctype_cntrl(mixed $text): bool { return p\Ctype::ctype_cntrl($text); }
-}
-if (!function_exists('ctype_digit')) {
- function ctype_digit(mixed $text): bool { return p\Ctype::ctype_digit($text); }
-}
-if (!function_exists('ctype_graph')) {
- function ctype_graph(mixed $text): bool { return p\Ctype::ctype_graph($text); }
-}
-if (!function_exists('ctype_lower')) {
- function ctype_lower(mixed $text): bool { return p\Ctype::ctype_lower($text); }
-}
-if (!function_exists('ctype_print')) {
- function ctype_print(mixed $text): bool { return p\Ctype::ctype_print($text); }
-}
-if (!function_exists('ctype_punct')) {
- function ctype_punct(mixed $text): bool { return p\Ctype::ctype_punct($text); }
-}
-if (!function_exists('ctype_space')) {
- function ctype_space(mixed $text): bool { return p\Ctype::ctype_space($text); }
-}
-if (!function_exists('ctype_upper')) {
- function ctype_upper(mixed $text): bool { return p\Ctype::ctype_upper($text); }
-}
-if (!function_exists('ctype_xdigit')) {
- function ctype_xdigit(mixed $text): bool { return p\Ctype::ctype_xdigit($text); }
-}
diff --git a/vendor/symfony/polyfill-ctype/composer.json b/vendor/symfony/polyfill-ctype/composer.json
deleted file mode 100644
index 131ca7a..0000000
--- a/vendor/symfony/polyfill-ctype/composer.json
+++ /dev/null
@@ -1,38 +0,0 @@
-{
- "name": "symfony/polyfill-ctype",
- "type": "library",
- "description": "Symfony polyfill for ctype functions",
- "keywords": ["polyfill", "compatibility", "portable", "ctype"],
- "homepage": "https://symfony.com",
- "license": "MIT",
- "authors": [
- {
- "name": "Gert de Pagter",
- "email": "BackEndTea@gmail.com"
- },
- {
- "name": "Symfony Community",
- "homepage": "https://symfony.com/contributors"
- }
- ],
- "require": {
- "php": ">=7.2"
- },
- "provide": {
- "ext-ctype": "*"
- },
- "autoload": {
- "psr-4": { "Symfony\\Polyfill\\Ctype\\": "" },
- "files": [ "bootstrap.php" ]
- },
- "suggest": {
- "ext-ctype": "For best performance"
- },
- "minimum-stability": "dev",
- "extra": {
- "thanks": {
- "name": "symfony/polyfill",
- "url": "https://github.com/symfony/polyfill"
- }
- }
-}
diff --git a/vendor/symfony/polyfill-php80/Php80.php b/vendor/symfony/polyfill-php80/Php80.php
deleted file mode 100644
index 362dd1a..0000000
--- a/vendor/symfony/polyfill-php80/Php80.php
+++ /dev/null
@@ -1,115 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Polyfill\Php80;
-
-/**
- * @author Ion Bazan
- * @author Nico Oelgart
- * @author Nicolas Grekas
- *
- * @internal
- */
-final class Php80
-{
- public static function fdiv(float $dividend, float $divisor): float
- {
- return @($dividend / $divisor);
- }
-
- public static function get_debug_type($value): string
- {
- switch (true) {
- case null === $value: return 'null';
- case \is_bool($value): return 'bool';
- case \is_string($value): return 'string';
- case \is_array($value): return 'array';
- case \is_int($value): return 'int';
- case \is_float($value): return 'float';
- case \is_object($value): break;
- case $value instanceof \__PHP_Incomplete_Class: return '__PHP_Incomplete_Class';
- default:
- if (null === $type = @get_resource_type($value)) {
- return 'unknown';
- }
-
- if ('Unknown' === $type) {
- $type = 'closed';
- }
-
- return "resource ($type)";
- }
-
- $class = \get_class($value);
-
- if (false === strpos($class, '@')) {
- return $class;
- }
-
- return (get_parent_class($class) ?: key(class_implements($class)) ?: 'class').'@anonymous';
- }
-
- public static function get_resource_id($res): int
- {
- if (!\is_resource($res) && null === @get_resource_type($res)) {
- throw new \TypeError(sprintf('Argument 1 passed to get_resource_id() must be of the type resource, %s given', get_debug_type($res)));
- }
-
- return (int) $res;
- }
-
- public static function preg_last_error_msg(): string
- {
- switch (preg_last_error()) {
- case \PREG_INTERNAL_ERROR:
- return 'Internal error';
- case \PREG_BAD_UTF8_ERROR:
- return 'Malformed UTF-8 characters, possibly incorrectly encoded';
- case \PREG_BAD_UTF8_OFFSET_ERROR:
- return 'The offset did not correspond to the beginning of a valid UTF-8 code point';
- case \PREG_BACKTRACK_LIMIT_ERROR:
- return 'Backtrack limit exhausted';
- case \PREG_RECURSION_LIMIT_ERROR:
- return 'Recursion limit exhausted';
- case \PREG_JIT_STACKLIMIT_ERROR:
- return 'JIT stack limit exhausted';
- case \PREG_NO_ERROR:
- return 'No error';
- default:
- return 'Unknown error';
- }
- }
-
- public static function str_contains(string $haystack, string $needle): bool
- {
- return '' === $needle || false !== strpos($haystack, $needle);
- }
-
- public static function str_starts_with(string $haystack, string $needle): bool
- {
- return 0 === strncmp($haystack, $needle, \strlen($needle));
- }
-
- public static function str_ends_with(string $haystack, string $needle): bool
- {
- if ('' === $needle || $needle === $haystack) {
- return true;
- }
-
- if ('' === $haystack) {
- return false;
- }
-
- $needleLength = \strlen($needle);
-
- return $needleLength <= \strlen($haystack) && 0 === substr_compare($haystack, $needle, -$needleLength);
- }
-}
diff --git a/vendor/symfony/polyfill-php80/PhpToken.php b/vendor/symfony/polyfill-php80/PhpToken.php
deleted file mode 100644
index cd78c4c..0000000
--- a/vendor/symfony/polyfill-php80/PhpToken.php
+++ /dev/null
@@ -1,106 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Polyfill\Php80;
-
-/**
- * @author Fedonyuk Anton
- *
- * @internal
- */
-class PhpToken implements \Stringable
-{
- /**
- * @var int
- */
- public $id;
-
- /**
- * @var string
- */
- public $text;
-
- /**
- * @var -1|positive-int
- */
- public $line;
-
- /**
- * @var int
- */
- public $pos;
-
- /**
- * @param -1|positive-int $line
- */
- public function __construct(int $id, string $text, int $line = -1, int $position = -1)
- {
- $this->id = $id;
- $this->text = $text;
- $this->line = $line;
- $this->pos = $position;
- }
-
- public function getTokenName(): ?string
- {
- if ('UNKNOWN' === $name = token_name($this->id)) {
- $name = \strlen($this->text) > 1 || \ord($this->text) < 32 ? null : $this->text;
- }
-
- return $name;
- }
-
- /**
- * @param int|string|array $kind
- */
- public function is($kind): bool
- {
- foreach ((array) $kind as $value) {
- if (\in_array($value, [$this->id, $this->text], true)) {
- return true;
- }
- }
-
- return false;
- }
-
- public function isIgnorable(): bool
- {
- return \in_array($this->id, [\T_WHITESPACE, \T_COMMENT, \T_DOC_COMMENT, \T_OPEN_TAG], true);
- }
-
- public function __toString(): string
- {
- return (string) $this->text;
- }
-
- /**
- * @return list
- */
- public static function tokenize(string $code, int $flags = 0): array
- {
- $line = 1;
- $position = 0;
- $tokens = token_get_all($code, $flags);
- foreach ($tokens as $index => $token) {
- if (\is_string($token)) {
- $id = \ord($token);
- $text = $token;
- } else {
- [$id, $text, $line] = $token;
- }
- $tokens[$index] = new static($id, $text, $line, $position);
- $position += \strlen($text);
- }
-
- return $tokens;
- }
-}
diff --git a/vendor/symfony/polyfill-php80/Resources/stubs/Attribute.php b/vendor/symfony/polyfill-php80/Resources/stubs/Attribute.php
deleted file mode 100644
index 2b95542..0000000
--- a/vendor/symfony/polyfill-php80/Resources/stubs/Attribute.php
+++ /dev/null
@@ -1,31 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-#[Attribute(Attribute::TARGET_CLASS)]
-final class Attribute
-{
- public const TARGET_CLASS = 1;
- public const TARGET_FUNCTION = 2;
- public const TARGET_METHOD = 4;
- public const TARGET_PROPERTY = 8;
- public const TARGET_CLASS_CONSTANT = 16;
- public const TARGET_PARAMETER = 32;
- public const TARGET_ALL = 63;
- public const IS_REPEATABLE = 64;
-
- /** @var int */
- public $flags;
-
- public function __construct(int $flags = self::TARGET_ALL)
- {
- $this->flags = $flags;
- }
-}
diff --git a/vendor/symfony/polyfill-php80/Resources/stubs/PhpToken.php b/vendor/symfony/polyfill-php80/Resources/stubs/PhpToken.php
deleted file mode 100644
index bd1212f..0000000
--- a/vendor/symfony/polyfill-php80/Resources/stubs/PhpToken.php
+++ /dev/null
@@ -1,16 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-if (\PHP_VERSION_ID < 80000 && extension_loaded('tokenizer')) {
- class PhpToken extends Symfony\Polyfill\Php80\PhpToken
- {
- }
-}
diff --git a/vendor/symfony/polyfill-php80/Resources/stubs/Stringable.php b/vendor/symfony/polyfill-php80/Resources/stubs/Stringable.php
deleted file mode 100644
index 7c62d75..0000000
--- a/vendor/symfony/polyfill-php80/Resources/stubs/Stringable.php
+++ /dev/null
@@ -1,20 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-if (\PHP_VERSION_ID < 80000) {
- interface Stringable
- {
- /**
- * @return string
- */
- public function __toString();
- }
-}
diff --git a/vendor/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php b/vendor/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php
deleted file mode 100644
index 01c6c6c..0000000
--- a/vendor/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php
+++ /dev/null
@@ -1,16 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-if (\PHP_VERSION_ID < 80000) {
- class UnhandledMatchError extends Error
- {
- }
-}
diff --git a/vendor/symfony/polyfill-php80/Resources/stubs/ValueError.php b/vendor/symfony/polyfill-php80/Resources/stubs/ValueError.php
deleted file mode 100644
index 783dbc2..0000000
--- a/vendor/symfony/polyfill-php80/Resources/stubs/ValueError.php
+++ /dev/null
@@ -1,16 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-if (\PHP_VERSION_ID < 80000) {
- class ValueError extends Error
- {
- }
-}
diff --git a/vendor/symfony/polyfill-php80/bootstrap.php b/vendor/symfony/polyfill-php80/bootstrap.php
deleted file mode 100644
index e5f7dbc..0000000
--- a/vendor/symfony/polyfill-php80/bootstrap.php
+++ /dev/null
@@ -1,42 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-use Symfony\Polyfill\Php80 as p;
-
-if (\PHP_VERSION_ID >= 80000) {
- return;
-}
-
-if (!defined('FILTER_VALIDATE_BOOL') && defined('FILTER_VALIDATE_BOOLEAN')) {
- define('FILTER_VALIDATE_BOOL', \FILTER_VALIDATE_BOOLEAN);
-}
-
-if (!function_exists('fdiv')) {
- function fdiv(float $num1, float $num2): float { return p\Php80::fdiv($num1, $num2); }
-}
-if (!function_exists('preg_last_error_msg')) {
- function preg_last_error_msg(): string { return p\Php80::preg_last_error_msg(); }
-}
-if (!function_exists('str_contains')) {
- function str_contains(?string $haystack, ?string $needle): bool { return p\Php80::str_contains($haystack ?? '', $needle ?? ''); }
-}
-if (!function_exists('str_starts_with')) {
- function str_starts_with(?string $haystack, ?string $needle): bool { return p\Php80::str_starts_with($haystack ?? '', $needle ?? ''); }
-}
-if (!function_exists('str_ends_with')) {
- function str_ends_with(?string $haystack, ?string $needle): bool { return p\Php80::str_ends_with($haystack ?? '', $needle ?? ''); }
-}
-if (!function_exists('get_debug_type')) {
- function get_debug_type($value): string { return p\Php80::get_debug_type($value); }
-}
-if (!function_exists('get_resource_id')) {
- function get_resource_id($resource): int { return p\Php80::get_resource_id($resource); }
-}
diff --git a/vendor/symfony/polyfill-php80/LICENSE b/vendor/symfony/polyfill-php84/LICENSE
similarity index 95%
rename from vendor/symfony/polyfill-php80/LICENSE
rename to vendor/symfony/polyfill-php84/LICENSE
index 0ed3a24..e374a5c 100644
--- a/vendor/symfony/polyfill-php80/LICENSE
+++ b/vendor/symfony/polyfill-php84/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2020-present Fabien Potencier
+Copyright (c) 2024-present Fabien Potencier
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/vendor/symfony/polyfill-php84/Php84.php b/vendor/symfony/polyfill-php84/Php84.php
new file mode 100644
index 0000000..1eea63a
--- /dev/null
+++ b/vendor/symfony/polyfill-php84/Php84.php
@@ -0,0 +1,217 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Polyfill\Php84;
+
+/**
+ * @author Ayesh Karunaratne
+ * @author Pierre Ambroise
+ *
+ * @internal
+ */
+final class Php84
+{
+ public static function mb_ucfirst(string $string, ?string $encoding = null): string
+ {
+ if (null === $encoding) {
+ $encoding = mb_internal_encoding();
+ }
+
+ try {
+ $validEncoding = @mb_check_encoding('', $encoding);
+ } catch (\ValueError $e) {
+ throw new \ValueError(sprintf('mb_ucfirst(): Argument #2 ($encoding) must be a valid encoding, "%s" given', $encoding));
+ }
+
+ // BC for PHP 7.3 and lower
+ if (!$validEncoding) {
+ throw new \ValueError(sprintf('mb_ucfirst(): Argument #2 ($encoding) must be a valid encoding, "%s" given', $encoding));
+ }
+
+ $firstChar = mb_substr($string, 0, 1, $encoding);
+ $firstChar = mb_convert_case($firstChar, \MB_CASE_TITLE, $encoding);
+
+ return $firstChar.mb_substr($string, 1, null, $encoding);
+ }
+
+ public static function mb_lcfirst(string $string, ?string $encoding = null): string
+ {
+ if (null === $encoding) {
+ $encoding = mb_internal_encoding();
+ }
+
+ try {
+ $validEncoding = @mb_check_encoding('', $encoding);
+ } catch (\ValueError $e) {
+ throw new \ValueError(sprintf('mb_lcfirst(): Argument #2 ($encoding) must be a valid encoding, "%s" given', $encoding));
+ }
+
+ // BC for PHP 7.3 and lower
+ if (!$validEncoding) {
+ throw new \ValueError(sprintf('mb_lcfirst(): Argument #2 ($encoding) must be a valid encoding, "%s" given', $encoding));
+ }
+
+ $firstChar = mb_substr($string, 0, 1, $encoding);
+ $firstChar = mb_convert_case($firstChar, \MB_CASE_LOWER, $encoding);
+
+ return $firstChar.mb_substr($string, 1, null, $encoding);
+ }
+
+ public static function array_find(array $array, callable $callback)
+ {
+ foreach ($array as $key => $value) {
+ if ($callback($value, $key)) {
+ return $value;
+ }
+ }
+
+ return null;
+ }
+
+ public static function array_find_key(array $array, callable $callback)
+ {
+ foreach ($array as $key => $value) {
+ if ($callback($value, $key)) {
+ return $key;
+ }
+ }
+
+ return null;
+ }
+
+ public static function array_any(array $array, callable $callback): bool
+ {
+ foreach ($array as $key => $value) {
+ if ($callback($value, $key)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public static function array_all(array $array, callable $callback): bool
+ {
+ foreach ($array as $key => $value) {
+ if (!$callback($value, $key)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public static function fpow(float $num, float $exponent): float
+ {
+ return $num ** $exponent;
+ }
+
+ public static function mb_trim(string $string, ?string $characters = null, ?string $encoding = null): string
+ {
+ return self::mb_internal_trim('{^[%s]+|[%1$s]+$}Du', $string, $characters, $encoding, __FUNCTION__);
+ }
+
+ public static function mb_ltrim(string $string, ?string $characters = null, ?string $encoding = null): string
+ {
+ return self::mb_internal_trim('{^[%s]+}Du', $string, $characters, $encoding, __FUNCTION__);
+ }
+
+ public static function mb_rtrim(string $string, ?string $characters = null, ?string $encoding = null): string
+ {
+ return self::mb_internal_trim('{[%s]+$}Du', $string, $characters, $encoding, __FUNCTION__);
+ }
+
+ private static function mb_internal_trim(string $regex, string $string, ?string $characters, ?string $encoding, string $function): string
+ {
+ if (null === $encoding) {
+ $encoding = mb_internal_encoding();
+ }
+
+ try {
+ $validEncoding = @mb_check_encoding('', $encoding);
+ } catch (\ValueError $e) {
+ throw new \ValueError(sprintf('%s(): Argument #3 ($encoding) must be a valid encoding, "%s" given', $function, $encoding));
+ }
+
+ // BC for PHP 7.3 and lower
+ if (!$validEncoding) {
+ throw new \ValueError(sprintf('%s(): Argument #3 ($encoding) must be a valid encoding, "%s" given', $function, $encoding));
+ }
+
+ if ('' === $characters) {
+ return null === $encoding ? $string : mb_convert_encoding($string, $encoding);
+ }
+
+ if ('UTF-8' === $encoding || \in_array(strtolower($encoding), ['utf-8', 'utf8'], true)) {
+ $encoding = 'UTF-8';
+ }
+
+ $string = mb_convert_encoding($string, 'UTF-8', $encoding);
+
+ if (null !== $characters) {
+ $characters = mb_convert_encoding($characters, 'UTF-8', $encoding);
+ }
+
+ if (null === $characters) {
+ $characters = "\\0 \f\n\r\t\v\u{00A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{2028}\u{2029}\u{202F}\u{205F}\u{3000}\u{0085}\u{180E}";
+ } else {
+ $characters = preg_quote($characters);
+ }
+
+ $string = preg_replace(sprintf($regex, $characters), '', $string);
+
+ if ('UTF-8' === $encoding) {
+ return $string;
+ }
+
+ return mb_convert_encoding($string, $encoding, 'UTF-8');
+ }
+
+ public static function grapheme_str_split(string $string, int $length)
+ {
+ if (0 > $length || 1073741823 < $length) {
+ throw new \ValueError('grapheme_str_split(): Argument #2 ($length) must be greater than 0 and less than or equal to 1073741823.');
+ }
+
+ if ('' === $string) {
+ return [];
+ }
+
+ $regex = ((float) \PCRE_VERSION < 10 ? (float) \PCRE_VERSION >= 8.32 : (float) \PCRE_VERSION >= 10.39)
+ ? '\X'
+ : '(?:\r\n|(?:[ -~\x{200C}\x{200D}]|[ᆨ-ᇹ]+|[ᄀ-ᅟ]*(?:[가개갸걔거게겨계고과괘괴교구궈궤귀규그긔기까깨꺄꺠꺼께껴꼐꼬꽈꽤꾀꾜꾸꿔꿰뀌뀨끄끠끼나내냐냬너네녀녜노놔놰뇌뇨누눠눼뉘뉴느늬니다대댜댸더데뎌뎨도돠돼되됴두둬뒈뒤듀드듸디따때땨떄떠떼뗘뗴또똬뙈뙤뚀뚜뚸뛔뛰뜌뜨띄띠라래랴럐러레려례로롸뢔뢰료루뤄뤠뤼류르릐리마매먀먜머메며몌모뫄뫠뫼묘무뭐뭬뮈뮤므믜미바배뱌뱨버베벼볘보봐봬뵈뵤부붜붸뷔뷰브븨비빠빼뺘뺴뻐뻬뼈뼤뽀뽜뽸뾔뾰뿌뿨쀄쀠쀼쁘쁴삐사새샤섀서세셔셰소솨쇄쇠쇼수숴쉐쉬슈스싀시싸쌔쌰썌써쎄쎠쎼쏘쏴쐐쐬쑈쑤쒀쒜쒸쓔쓰씌씨아애야얘어에여예오와왜외요우워웨위유으의이자재쟈쟤저제져졔조좌좨죄죠주줘줴쥐쥬즈즤지짜째쨔쨰쩌쩨쪄쪠쪼쫘쫴쬐쬬쭈쭤쮀쮜쮸쯔쯰찌차채챠챼처체쳐쳬초촤쵀최쵸추춰췌취츄츠츼치카캐캬컈커케켜켸코콰쾌쾨쿄쿠쿼퀘퀴큐크킈키타태탸턔터테텨톄토톼퇘퇴툐투퉈퉤튀튜트틔티파패퍄퍠퍼페펴폐포퐈퐤푀표푸풔풰퓌퓨프픠피하해햐햬허헤혀혜호화홰회효후훠훼휘휴흐희히]?[ᅠ-ᆢ]+|[가-힣])[ᆨ-ᇹ]*|[ᄀ-ᅟ]+|[^\p{Cc}\p{Cf}\p{Zl}\p{Zp}])[\p{Mn}\p{Me}\x{09BE}\x{09D7}\x{0B3E}\x{0B57}\x{0BBE}\x{0BD7}\x{0CC2}\x{0CD5}\x{0CD6}\x{0D3E}\x{0D57}\x{0DCF}\x{0DDF}\x{200C}\x{200D}\x{1D165}\x{1D16E}-\x{1D172}]*|[\p{Cc}\p{Cf}\p{Zl}\p{Zp}])';
+
+ if (!preg_match_all('/'. $regex .'/u', $string, $matches)) {
+ return false;
+ }
+
+ if (1 === $length) {
+ return $matches[0];
+ }
+
+ $chunks = array_chunk($matches[0], $length);
+ foreach ($chunks as &$chunk) {
+ $chunk = implode('', $chunk);
+ }
+
+ return $chunks;
+ }
+
+ public static function bcdivmod(string $num1, string $num2, ?int $scale = null): ?array
+ {
+ if (null === $quot = \bcdiv($num1, $num2, 0)) {
+ return null;
+ }
+ $scale = $scale ?? (\PHP_VERSION_ID >= 70300 ? \bcscale() : (ini_get('bcmath.scale') ?: 0));
+
+ return [$quot, \bcmod($num1, $num2, $scale)];
+ }
+}
diff --git a/vendor/symfony/polyfill-php84/Resources/stubs/Deprecated.php b/vendor/symfony/polyfill-php84/Resources/stubs/Deprecated.php
new file mode 100644
index 0000000..f3e6a4f
--- /dev/null
+++ b/vendor/symfony/polyfill-php84/Resources/stubs/Deprecated.php
@@ -0,0 +1,25 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+if (\PHP_VERSION_ID < 80400) {
+ #[Attribute(Attribute::TARGET_METHOD | Attribute::TARGET_FUNCTION | Attribute::TARGET_CLASS_CONSTANT)]
+ final class Deprecated
+ {
+ public readonly ?string $message;
+ public readonly ?string $since;
+
+ public function __construct(?string $message = null, ?string $since = null)
+ {
+ $this->message = $message;
+ $this->since = $since;
+ }
+ }
+}
diff --git a/vendor/symfony/polyfill-php84/Resources/stubs/ReflectionConstant.php b/vendor/symfony/polyfill-php84/Resources/stubs/ReflectionConstant.php
new file mode 100644
index 0000000..f4c8448
--- /dev/null
+++ b/vendor/symfony/polyfill-php84/Resources/stubs/ReflectionConstant.php
@@ -0,0 +1,158 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+if (\PHP_VERSION_ID < 80400) {
+ /**
+ * @author Daniel Scherzer
+ */
+ final class ReflectionConstant
+ {
+ /**
+ * @var string
+ *
+ * @readonly
+ */
+ public $name;
+
+ private $value;
+ private $deprecated;
+
+ private static $persistentConstants = [];
+
+ public function __construct(string $name)
+ {
+ if (!defined($name) || false !== strpos($name, '::')) {
+ throw new ReflectionException("Constant \"$name\" does not exist");
+ }
+
+ $this->name = ltrim($name, '\\');
+ $deprecated = false;
+ $eh = set_error_handler(static function ($type, $msg, $file, $line) use ($name, &$deprecated, &$eh) {
+ if (\E_DEPRECATED === $type && "Constant $name is deprecated" === $msg) {
+ return $deprecated = true;
+ }
+
+ return $eh && $eh($type, $msg, $file, $line);
+ });
+
+ try {
+ $this->value = constant($name);
+ $this->deprecated = $deprecated;
+ } finally {
+ restore_error_handler();
+ }
+ }
+
+ public function getName(): string
+ {
+ return $this->name;
+ }
+
+ public function getValue()
+ {
+ return $this->value;
+ }
+
+ public function getNamespaceName(): string
+ {
+ if (false === $slashPos = strrpos($this->name, '\\')) {
+ return '';
+ }
+
+ return substr($this->name, 0, $slashPos);
+ }
+
+ public function getShortName(): string
+ {
+ if (false === $slashPos = strrpos($this->name, '\\')) {
+ return $this->name;
+ }
+
+ return substr($this->name, $slashPos + 1);
+ }
+
+ public function isDeprecated(): bool
+ {
+ return $this->deprecated;
+ }
+
+ public function __toString(): string
+ {
+ // A constant is persistent if provided by PHP itself rather than
+ // being defined by users. If we got here, we know that it *is*
+ // defined, so we just need to figure out if it is defined by the
+ // user or not
+ if (!self::$persistentConstants) {
+ $persistentConstants = get_defined_constants(true);
+ unset($persistentConstants['user']);
+ foreach ($persistentConstants as $constants) {
+ self::$persistentConstants += $constants;
+ }
+ }
+ $persistent = array_key_exists($this->name, self::$persistentConstants);
+
+ // Can't match the inclusion of `no_file_cache` but the rest is
+ // possible to match
+ $result = 'Constant [ ';
+ if ($persistent || $this->deprecated) {
+ $result .= '<';
+ if ($persistent) {
+ $result .= 'persistent';
+ if ($this->deprecated) {
+ $result .= ', ';
+ }
+ }
+ if ($this->deprecated) {
+ $result .= 'deprecated';
+ }
+ $result .= '> ';
+ }
+ // Cannot just use gettype() to match zend_zval_type_name()
+ if (is_object($this->value)) {
+ $result .= \PHP_VERSION_ID >= 80000 ? get_debug_type($this->value) : gettype($this->value);
+ } elseif (is_bool($this->value)) {
+ $result .= 'bool';
+ } elseif (is_int($this->value)) {
+ $result .= 'int';
+ } elseif (is_float($this->value)) {
+ $result .= 'float';
+ } elseif (null === $this->value) {
+ $result .= 'null';
+ } else {
+ $result .= gettype($this->value);
+ }
+ $result .= ' ';
+ $result .= $this->name;
+ $result .= ' ] { ';
+ if (is_array($this->value)) {
+ $result .= 'Array';
+ } else {
+ // This will throw an exception if the value is an object that
+ // cannot be converted to string; that is expected and matches
+ // the behavior of zval_get_string_func()
+ $result .= (string) $this->value;
+ }
+ $result .= " }\n";
+
+ return $result;
+ }
+
+ public function __sleep(): array
+ {
+ throw new Exception("Serialization of 'ReflectionConstant' is not allowed");
+ }
+
+ public function __wakeup(): void
+ {
+ throw new Exception("Unserialization of 'ReflectionConstant' is not allowed");
+ }
+ }
+}
diff --git a/vendor/symfony/polyfill-php84/bootstrap.php b/vendor/symfony/polyfill-php84/bootstrap.php
new file mode 100644
index 0000000..4bd1c17
--- /dev/null
+++ b/vendor/symfony/polyfill-php84/bootstrap.php
@@ -0,0 +1,82 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+use Symfony\Polyfill\Php84 as p;
+
+if (\PHP_VERSION_ID >= 80400) {
+ return;
+}
+
+if (defined('CURL_VERSION_HTTP3') || PHP_VERSION_ID < 80200 && function_exists('curl_version') && curl_version()['version'] >= 0x074200) { // libcurl >= 7.66.0
+ if (!defined('CURL_HTTP_VERSION_3')) {
+ define('CURL_HTTP_VERSION_3', 30);
+ }
+
+ if (!defined('CURL_HTTP_VERSION_3ONLY') && defined('CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256')) { // libcurl >= 7.80.0 (7.88 would be better but is slow to check)
+ define('CURL_HTTP_VERSION_3ONLY', 31);
+ }
+}
+
+if (!function_exists('array_find')) {
+ function array_find(array $array, callable $callback) { return p\Php84::array_find($array, $callback); }
+}
+
+if (!function_exists('array_find_key')) {
+ function array_find_key(array $array, callable $callback) { return p\Php84::array_find_key($array, $callback); }
+}
+
+if (!function_exists('array_any')) {
+ function array_any(array $array, callable $callback): bool { return p\Php84::array_any($array, $callback); }
+}
+
+if (!function_exists('array_all')) {
+ function array_all(array $array, callable $callback): bool { return p\Php84::array_all($array, $callback); }
+}
+
+if (!function_exists('fpow')) {
+ function fpow(float $num, float $exponent): float { return p\Php84::fpow($num, $exponent); }
+}
+
+if (extension_loaded('mbstring')) {
+ if (!function_exists('mb_ucfirst')) {
+ function mb_ucfirst(string $string, ?string $encoding = null): string { return p\Php84::mb_ucfirst($string, $encoding); }
+ }
+
+ if (!function_exists('mb_lcfirst')) {
+ function mb_lcfirst(string $string, ?string $encoding = null): string { return p\Php84::mb_lcfirst($string, $encoding); }
+ }
+
+ if (!function_exists('mb_trim')) {
+ function mb_trim(string $string, ?string $characters = null, ?string $encoding = null): string { return p\Php84::mb_trim($string, $characters, $encoding); }
+ }
+
+ if (!function_exists('mb_ltrim')) {
+ function mb_ltrim(string $string, ?string $characters = null, ?string $encoding = null): string { return p\Php84::mb_ltrim($string, $characters, $encoding); }
+ }
+
+ if (!function_exists('mb_rtrim')) {
+ function mb_rtrim(string $string, ?string $characters = null, ?string $encoding = null): string { return p\Php84::mb_rtrim($string, $characters, $encoding); }
+ }
+}
+
+if (extension_loaded('bcmath')) {
+ if (!function_exists('bcdivmod')) {
+ function bcdivmod(string $num1, string $num2, ?int $scale = null): ?array { return p\Php84::bcdivmod($num1, $num2, $scale); }
+ }
+}
+
+if (\PHP_VERSION_ID >= 80200) {
+ return require __DIR__.'/bootstrap82.php';
+}
+
+if (extension_loaded('intl') && !function_exists('grapheme_str_split')) {
+ function grapheme_str_split(string $string, int $length = 1) { return p\Php84::grapheme_str_split($string, $length); }
+}
diff --git a/vendor/symfony/polyfill-php84/bootstrap82.php b/vendor/symfony/polyfill-php84/bootstrap82.php
new file mode 100644
index 0000000..216ad02
--- /dev/null
+++ b/vendor/symfony/polyfill-php84/bootstrap82.php
@@ -0,0 +1,20 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+use Symfony\Polyfill\Php84 as p;
+
+if (\PHP_VERSION_ID >= 80400) {
+ return;
+}
+
+if (extension_loaded('intl') && !function_exists('grapheme_str_split')) {
+ function grapheme_str_split(string $string, int $length = 1): array|false { return p\Php84::grapheme_str_split($string, $length); }
+}
diff --git a/vendor/symfony/polyfill-php80/composer.json b/vendor/symfony/polyfill-php84/composer.json
similarity index 74%
rename from vendor/symfony/polyfill-php80/composer.json
rename to vendor/symfony/polyfill-php84/composer.json
index a503b03..8bbc281 100644
--- a/vendor/symfony/polyfill-php80/composer.json
+++ b/vendor/symfony/polyfill-php84/composer.json
@@ -1,15 +1,11 @@
{
- "name": "symfony/polyfill-php80",
+ "name": "symfony/polyfill-php84",
"type": "library",
- "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions",
+ "description": "Symfony polyfill backporting some PHP 8.4+ features to lower PHP versions",
"keywords": ["polyfill", "shim", "compatibility", "portable"],
"homepage": "https://symfony.com",
"license": "MIT",
"authors": [
- {
- "name": "Ion Bazan",
- "email": "ion.bazan@gmail.com"
- },
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
@@ -23,7 +19,7 @@
"php": ">=7.2"
},
"autoload": {
- "psr-4": { "Symfony\\Polyfill\\Php80\\": "" },
+ "psr-4": { "Symfony\\Polyfill\\Php84\\": "" },
"files": [ "bootstrap.php" ],
"classmap": [ "Resources/stubs" ]
},