From 873d3b4591362153225575871dfe8eadc80d451a Mon Sep 17 00:00:00 2001 From: Marc Beinder Date: Mon, 24 Nov 2025 10:35:11 -0600 Subject: [PATCH 01/10] Remove Deprecated Rules from Rector --- src/Support/Internal/Rector/Rector.php | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/Support/Internal/Rector/Rector.php b/src/Support/Internal/Rector/Rector.php index 8209497..798fd13 100644 --- a/src/Support/Internal/Rector/Rector.php +++ b/src/Support/Internal/Rector/Rector.php @@ -16,8 +16,6 @@ use Rector\CodeQuality\Rector\Catch_\ThrowWithPreviousExceptionRector; use Rector\CodeQuality\Rector\Class_\CompleteDynamicPropertiesRector; use Rector\CodeQuality\Rector\Class_\InlineConstructorDefaultToPropertyRector; -use Rector\CodeQuality\Rector\Class_\StaticToSelfStaticMethodCallOnFinalClassRector; -use Rector\CodeQuality\Rector\ClassConstFetch\ConvertStaticPrivateConstantToSelfRector; use Rector\CodeQuality\Rector\ClassMethod\ExplicitReturnNullRector; use Rector\CodeQuality\Rector\ClassMethod\InlineArrayReturnAssignRector; use Rector\CodeQuality\Rector\ClassMethod\LocallyCalledStaticMethodToNonStaticRector; @@ -164,11 +162,7 @@ use Rector\Privatization\Rector\MethodCall\PrivatizeLocalGetterToPropertyRector; use Rector\Privatization\Rector\Property\PrivatizeFinalClassPropertyRector; use Rector\Renaming\Rector\FuncCall\RenameFunctionRector; -use Rector\Strict\Rector\BooleanNot\BooleanInBooleanNotRuleFixerRector; use Rector\Strict\Rector\Empty_\DisallowedEmptyRuleFixerRector; -use Rector\Strict\Rector\If_\BooleanInIfConditionRuleFixerRector; -use Rector\Strict\Rector\Ternary\BooleanInTernaryOperatorRuleFixerRector; -use Rector\Strict\Rector\Ternary\DisallowedShortTernaryRuleFixerRector; use Rector\Symfony\CodeQuality\Rector\ClassMethod\ResponseReturnTypeControllerActionRector; use Rector\Transform\Rector\FuncCall\FuncCallToConstFetchRector; use Rector\TypeDeclaration\Rector\ArrowFunction\AddArrowFunctionReturnTypeRector; @@ -179,7 +173,6 @@ use Rector\TypeDeclaration\Rector\Class_\PropertyTypeFromStrictSetterGetterRector; use Rector\TypeDeclaration\Rector\Class_\ReturnTypeFromStrictTernaryRector; use Rector\TypeDeclaration\Rector\Class_\TypedPropertyFromCreateMockAssignRector; -use Rector\TypeDeclaration\Rector\Class_\TypedPropertyFromJMSSerializerAttributeTypeRector; use Rector\TypeDeclaration\Rector\ClassMethod\AddMethodCallBasedStrictParamTypeRector; use Rector\TypeDeclaration\Rector\ClassMethod\AddParamTypeBasedOnPHPUnitDataProviderRector; use Rector\TypeDeclaration\Rector\ClassMethod\AddParamTypeFromPropertyTypeRector; @@ -237,14 +230,12 @@ public static function rules(array $rules = []): array ReplaceMultipleBooleanNotRector::class, SimplifyDeMorganBinaryRector::class, ThrowWithPreviousExceptionRector::class, - ConvertStaticPrivateConstantToSelfRector::class, ExplicitReturnNullRector::class, InlineArrayReturnAssignRector::class, LocallyCalledStaticMethodToNonStaticRector::class, OptionalParametersAfterRequiredRector::class, CompleteDynamicPropertiesRector::class, InlineConstructorDefaultToPropertyRector::class, - StaticToSelfStaticMethodCallOnFinalClassRector::class, JoinStringConcatRector::class, SimplifyEmptyCheckOnEmptyArrayRector::class, InlineIfToExplicitIfRector::class, @@ -378,9 +369,6 @@ public static function rules(array $rules = []): array PrivatizeFinalClassPropertyRector::class, RenameFunctionRector::class, DisallowedEmptyRuleFixerRector::class, - BooleanInIfConditionRuleFixerRector::class, - BooleanInTernaryOperatorRuleFixerRector::class, - DisallowedShortTernaryRuleFixerRector::class, ResponseReturnTypeControllerActionRector::class, FuncCallToConstFetchRector::class, AddArrowFunctionReturnTypeRector::class, @@ -420,7 +408,6 @@ public static function rules(array $rules = []): array PropertyTypeFromStrictSetterGetterRector::class, ReturnTypeFromStrictTernaryRector::class, TypedPropertyFromCreateMockAssignRector::class, - TypedPropertyFromJMSSerializerAttributeTypeRector::class, AddClosureNeverReturnTypeRector::class, AddClosureVoidReturnTypeWhereNoReturnRector::class, ClosureReturnTypeRector::class, @@ -449,7 +436,6 @@ public static function skip(array $rules = []): array SeparateMultiUseImportsRector::class, RemoveExtraParametersRector::class, NewlineAfterStatementRector::class, - BooleanInBooleanNotRuleFixerRector::class, ], $rules); } } From 8c058c72eaa3e53e32d78905f58f6a9d97570b25 Mon Sep 17 00:00:00 2001 From: Marc Beinder Date: Mon, 24 Nov 2025 10:52:26 -0600 Subject: [PATCH 02/10] Create Assert Class --- .idea/php.xml | 20 +- .idea/stdlib.iml | 6 - composer.json | 10 +- composer.lock | 401 ++++++++++---------- phpstan.neon | 4 +- src/Exceptions/AssertionFailedException.php | 18 + src/Objects/Filesystem/Directory.php | 8 +- src/Objects/Serializers/JsonSerializer.php | 6 +- src/Objects/Support/Assert.php | 61 +++ src/Objects/Support/Traits/Assertable.php | 36 ++ src/Objects/Support/Traits/HasEnumValue.php | 1 + 11 files changed, 342 insertions(+), 229 deletions(-) create mode 100644 src/Exceptions/AssertionFailedException.php create mode 100644 src/Objects/Support/Assert.php create mode 100644 src/Objects/Support/Traits/Assertable.php diff --git a/.idea/php.xml b/.idea/php.xml index 4da245d..f7cbecb 100644 --- a/.idea/php.xml +++ b/.idea/php.xml @@ -18,13 +18,10 @@ - - - @@ -83,31 +80,24 @@ - - - - - - - @@ -116,6 +106,16 @@ + + + + + + + + + + diff --git a/.idea/stdlib.iml b/.idea/stdlib.iml index 101fa13..5e6660a 100644 --- a/.idea/stdlib.iml +++ b/.idea/stdlib.iml @@ -24,7 +24,6 @@ - @@ -72,11 +71,6 @@ - - - - - diff --git a/composer.json b/composer.json index 8c36b64..93380a1 100644 --- a/composer.json +++ b/composer.json @@ -23,12 +23,12 @@ }, "require-dev": { "mockery/mockery": "^1.6", - "pestphp/pest": "^2.34 || ^3.0 || ^4.0", + "pestphp/pest": "^4", "phpstan/extension-installer": "^1.3", - "phpstan/phpstan": "^1.10", - "rector/rector": "^1.0", - "tightenco/duster": "^2.7 || ^3.0", - "tomasvotruba/cognitive-complexity": "^0.2.3" + "phpstan/phpstan": "^2", + "rector/rector": "^2", + "tightenco/duster": "^3", + "tomasvotruba/cognitive-complexity": "^1" }, "autoload": { "psr-4": { diff --git a/composer.lock b/composer.lock index 03312bf..abd673b 100644 --- a/composer.lock +++ b/composer.lock @@ -4,20 +4,20 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "d87f8ae3c632cd96db23f6304d6f50c7", + "content-hash": "5e755e57c6d94b86a69152b6f4fe6939", "packages": [ { "name": "brick/math", - "version": "0.14.0", + "version": "0.14.1", "source": { "type": "git", "url": "https://github.com/brick/math.git", - "reference": "113a8ee2656b882d4c3164fa31aa6e12cbb7aaa2" + "reference": "f05858549e5f9d7bb45875a75583240a38a281d0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/brick/math/zipball/113a8ee2656b882d4c3164fa31aa6e12cbb7aaa2", - "reference": "113a8ee2656b882d4c3164fa31aa6e12cbb7aaa2", + "url": "https://api.github.com/repos/brick/math/zipball/f05858549e5f9d7bb45875a75583240a38a281d0", + "reference": "f05858549e5f9d7bb45875a75583240a38a281d0", "shasum": "" }, "require": { @@ -56,7 +56,7 @@ ], "support": { "issues": "https://github.com/brick/math/issues", - "source": "https://github.com/brick/math/tree/0.14.0" + "source": "https://github.com/brick/math/tree/0.14.1" }, "funding": [ { @@ -64,7 +64,7 @@ "type": "github" } ], - "time": "2025-08-29T12:40:03+00:00" + "time": "2025-11-24T14:40:29+00:00" }, { "name": "carbonphp/carbon-doctrine-types", @@ -137,16 +137,16 @@ }, { "name": "composer/ca-bundle", - "version": "1.5.8", + "version": "1.5.9", "source": { "type": "git", "url": "https://github.com/composer/ca-bundle.git", - "reference": "719026bb30813accb68271fee7e39552a58e9f65" + "reference": "1905981ee626e6f852448b7aaa978f8666c5bc54" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/ca-bundle/zipball/719026bb30813accb68271fee7e39552a58e9f65", - "reference": "719026bb30813accb68271fee7e39552a58e9f65", + "url": "https://api.github.com/repos/composer/ca-bundle/zipball/1905981ee626e6f852448b7aaa978f8666c5bc54", + "reference": "1905981ee626e6f852448b7aaa978f8666c5bc54", "shasum": "" }, "require": { @@ -193,7 +193,7 @@ "support": { "irc": "irc://irc.freenode.org/composer", "issues": "https://github.com/composer/ca-bundle/issues", - "source": "https://github.com/composer/ca-bundle/tree/1.5.8" + "source": "https://github.com/composer/ca-bundle/tree/1.5.9" }, "funding": [ { @@ -205,26 +205,26 @@ "type": "github" } ], - "time": "2025-08-20T18:49:47+00:00" + "time": "2025-11-06T11:46:17+00:00" }, { "name": "composer/class-map-generator", - "version": "1.6.2", + "version": "1.7.0", "source": { "type": "git", "url": "https://github.com/composer/class-map-generator.git", - "reference": "ba9f089655d4cdd64e762a6044f411ccdaec0076" + "reference": "2373419b7709815ed323ebf18c3c72d03ff4a8a6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/class-map-generator/zipball/ba9f089655d4cdd64e762a6044f411ccdaec0076", - "reference": "ba9f089655d4cdd64e762a6044f411ccdaec0076", + "url": "https://api.github.com/repos/composer/class-map-generator/zipball/2373419b7709815ed323ebf18c3c72d03ff4a8a6", + "reference": "2373419b7709815ed323ebf18c3c72d03ff4a8a6", "shasum": "" }, "require": { "composer/pcre": "^2.1 || ^3.1", "php": "^7.2 || ^8.0", - "symfony/finder": "^4.4 || ^5.3 || ^6 || ^7" + "symfony/finder": "^4.4 || ^5.3 || ^6 || ^7 || ^8" }, "require-dev": { "phpstan/phpstan": "^1.12 || ^2", @@ -232,7 +232,7 @@ "phpstan/phpstan-phpunit": "^1 || ^2", "phpstan/phpstan-strict-rules": "^1.1 || ^2", "phpunit/phpunit": "^8", - "symfony/filesystem": "^5.4 || ^6" + "symfony/filesystem": "^5.4 || ^6 || ^7 || ^8" }, "type": "library", "extra": { @@ -262,7 +262,7 @@ ], "support": { "issues": "https://github.com/composer/class-map-generator/issues", - "source": "https://github.com/composer/class-map-generator/tree/1.6.2" + "source": "https://github.com/composer/class-map-generator/tree/1.7.0" }, "funding": [ { @@ -274,30 +274,31 @@ "type": "github" } ], - "time": "2025-08-20T18:52:43+00:00" + "time": "2025-11-19T10:41:15+00:00" }, { "name": "composer/composer", - "version": "2.8.12", + "version": "2.9.2", "source": { "type": "git", "url": "https://github.com/composer/composer.git", - "reference": "3e38919bc9a2c3c026f2151b5e56d04084ce8f0b" + "reference": "8d5358f147c63a3a681b002076deff8c90e0b19d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/composer/zipball/3e38919bc9a2c3c026f2151b5e56d04084ce8f0b", - "reference": "3e38919bc9a2c3c026f2151b5e56d04084ce8f0b", + "url": "https://api.github.com/repos/composer/composer/zipball/8d5358f147c63a3a681b002076deff8c90e0b19d", + "reference": "8d5358f147c63a3a681b002076deff8c90e0b19d", "shasum": "" }, "require": { "composer/ca-bundle": "^1.5", "composer/class-map-generator": "^1.4.0", "composer/metadata-minifier": "^1.0", - "composer/pcre": "^2.2 || ^3.2", + "composer/pcre": "^2.3 || ^3.3", "composer/semver": "^3.3", "composer/spdx-licenses": "^1.5.7", "composer/xdebug-handler": "^2.0.2 || ^3.0.3", + "ext-json": "*", "justinrainbow/json-schema": "^6.5.1", "php": "^7.2.5 || ^8.0", "psr/log": "^1.0 || ^2.0 || ^3.0", @@ -305,13 +306,14 @@ "seld/jsonlint": "^1.4", "seld/phar-utils": "^1.2", "seld/signal-handler": "^2.0", - "symfony/console": "^5.4.47 || ^6.4.25 || ^7.1.10", - "symfony/filesystem": "^5.4.45 || ^6.4.24 || ^7.1.10", - "symfony/finder": "^5.4.45 || ^6.4.24 || ^7.1.10", + "symfony/console": "^5.4.47 || ^6.4.25 || ^7.1.10 || ^8.0", + "symfony/filesystem": "^5.4.45 || ^6.4.24 || ^7.1.10 || ^8.0", + "symfony/finder": "^5.4.45 || ^6.4.24 || ^7.1.10 || ^8.0", "symfony/polyfill-php73": "^1.24", "symfony/polyfill-php80": "^1.24", "symfony/polyfill-php81": "^1.24", - "symfony/process": "^5.4.47 || ^6.4.25 || ^7.1.10" + "symfony/polyfill-php84": "^1.30", + "symfony/process": "^5.4.47 || ^6.4.25 || ^7.1.10 || ^8.0" }, "require-dev": { "phpstan/phpstan": "^1.11.8", @@ -319,12 +321,13 @@ "phpstan/phpstan-phpunit": "^1.4.0", "phpstan/phpstan-strict-rules": "^1.6.0", "phpstan/phpstan-symfony": "^1.4.0", - "symfony/phpunit-bridge": "^6.4.25 || ^7.3.3" + "symfony/phpunit-bridge": "^6.4.25 || ^7.3.3 || ^8.0" }, "suggest": { - "ext-openssl": "Enabling the openssl extension allows you to access https URLs for repositories and packages", - "ext-zip": "Enabling the zip extension allows you to unzip archives", - "ext-zlib": "Allow gzip compression of HTTP requests" + "ext-curl": "Provides HTTP support (will fallback to PHP streams if missing)", + "ext-openssl": "Enables access to repositories and packages over HTTPS", + "ext-zip": "Allows direct extraction of ZIP archives (unzip/7z binaries will be used instead if available)", + "ext-zlib": "Enables gzip for HTTP requests" }, "bin": [ "bin/composer" @@ -337,7 +340,7 @@ ] }, "branch-alias": { - "dev-main": "2.8-dev" + "dev-main": "2.9-dev" } }, "autoload": { @@ -372,7 +375,7 @@ "irc": "ircs://irc.libera.chat:6697/composer", "issues": "https://github.com/composer/composer/issues", "security": "https://github.com/composer/composer/security/policy", - "source": "https://github.com/composer/composer/tree/2.8.12" + "source": "https://github.com/composer/composer/tree/2.9.2" }, "funding": [ { @@ -384,7 +387,7 @@ "type": "github" } ], - "time": "2025-09-19T11:41:59+00:00" + "time": "2025-11-19T20:57:25+00:00" }, { "name": "composer/metadata-minifier", @@ -849,7 +852,7 @@ }, { "name": "illuminate/collections", - "version": "v12.38.0", + "version": "v12.39.0", "source": { "type": "git", "url": "https://github.com/illuminate/collections.git", @@ -908,7 +911,7 @@ }, { "name": "illuminate/conditionable", - "version": "v12.38.0", + "version": "v12.39.0", "source": { "type": "git", "url": "https://github.com/illuminate/conditionable.git", @@ -954,7 +957,7 @@ }, { "name": "illuminate/contracts", - "version": "v12.38.0", + "version": "v12.39.0", "source": { "type": "git", "url": "https://github.com/illuminate/contracts.git", @@ -1002,7 +1005,7 @@ }, { "name": "illuminate/macroable", - "version": "v12.38.0", + "version": "v12.39.0", "source": { "type": "git", "url": "https://github.com/illuminate/macroable.git", @@ -1048,16 +1051,16 @@ }, { "name": "illuminate/support", - "version": "v12.37.0", + "version": "v12.39.0", "source": { "type": "git", "url": "https://github.com/illuminate/support.git", - "reference": "480df979c8ffe700d6adb6e6e64abe04b32e02e3" + "reference": "d9780f626aa79d6b7b9c18f0d886340a29c66659" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/support/zipball/480df979c8ffe700d6adb6e6e64abe04b32e02e3", - "reference": "480df979c8ffe700d6adb6e6e64abe04b32e02e3", + "url": "https://api.github.com/repos/illuminate/support/zipball/d9780f626aa79d6b7b9c18f0d886340a29c66659", + "reference": "d9780f626aa79d6b7b9c18f0d886340a29c66659", "shasum": "" }, "require": { @@ -1123,20 +1126,20 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2025-10-31T16:20:10+00:00" + "time": "2025-11-16T14:43:22+00:00" }, { "name": "justinrainbow/json-schema", - "version": "6.5.2", + "version": "6.6.1", "source": { "type": "git", "url": "https://github.com/jsonrainbow/json-schema.git", - "reference": "ac0d369c09653cf7af561f6d91a705bc617a87b8" + "reference": "fd8e5c6b1badb998844ad34ce0abcd71a0aeb396" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/jsonrainbow/json-schema/zipball/ac0d369c09653cf7af561f6d91a705bc617a87b8", - "reference": "ac0d369c09653cf7af561f6d91a705bc617a87b8", + "url": "https://api.github.com/repos/jsonrainbow/json-schema/zipball/fd8e5c6b1badb998844ad34ce0abcd71a0aeb396", + "reference": "fd8e5c6b1badb998844ad34ce0abcd71a0aeb396", "shasum": "" }, "require": { @@ -1196,9 +1199,9 @@ ], "support": { "issues": "https://github.com/jsonrainbow/json-schema/issues", - "source": "https://github.com/jsonrainbow/json-schema/tree/6.5.2" + "source": "https://github.com/jsonrainbow/json-schema/tree/6.6.1" }, - "time": "2025-09-09T09:42:27+00:00" + "time": "2025-11-07T18:30:29+00:00" }, { "name": "marc-mabe/php-enum", @@ -2056,16 +2059,16 @@ }, { "name": "symfony/console", - "version": "v7.3.4", + "version": "v7.3.6", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "2b9c5fafbac0399a20a2e82429e2bd735dcfb7db" + "reference": "c28ad91448f86c5f6d9d2c70f0cf68bf135f252a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/2b9c5fafbac0399a20a2e82429e2bd735dcfb7db", - "reference": "2b9c5fafbac0399a20a2e82429e2bd735dcfb7db", + "url": "https://api.github.com/repos/symfony/console/zipball/c28ad91448f86c5f6d9d2c70f0cf68bf135f252a", + "reference": "c28ad91448f86c5f6d9d2c70f0cf68bf135f252a", "shasum": "" }, "require": { @@ -2130,7 +2133,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.3.4" + "source": "https://github.com/symfony/console/tree/v7.3.6" }, "funding": [ { @@ -2150,7 +2153,7 @@ "type": "tidelift" } ], - "time": "2025-09-22T15:31:00+00:00" + "time": "2025-11-04T01:21:42+00:00" }, { "name": "symfony/deprecation-contracts", @@ -2221,16 +2224,16 @@ }, { "name": "symfony/filesystem", - "version": "v7.3.2", + "version": "v7.3.6", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "edcbb768a186b5c3f25d0643159a787d3e63b7fd" + "reference": "e9bcfd7837928ab656276fe00464092cc9e1826a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/edcbb768a186b5c3f25d0643159a787d3e63b7fd", - "reference": "edcbb768a186b5c3f25d0643159a787d3e63b7fd", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/e9bcfd7837928ab656276fe00464092cc9e1826a", + "reference": "e9bcfd7837928ab656276fe00464092cc9e1826a", "shasum": "" }, "require": { @@ -2267,7 +2270,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v7.3.2" + "source": "https://github.com/symfony/filesystem/tree/v7.3.6" }, "funding": [ { @@ -2287,20 +2290,20 @@ "type": "tidelift" } ], - "time": "2025-07-07T08:17:47+00:00" + "time": "2025-11-05T09:52:27+00:00" }, { "name": "symfony/finder", - "version": "v7.3.2", + "version": "v7.3.5", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "2a6614966ba1074fa93dae0bc804227422df4dfe" + "reference": "9f696d2f1e340484b4683f7853b273abff94421f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/2a6614966ba1074fa93dae0bc804227422df4dfe", - "reference": "2a6614966ba1074fa93dae0bc804227422df4dfe", + "url": "https://api.github.com/repos/symfony/finder/zipball/9f696d2f1e340484b4683f7853b273abff94421f", + "reference": "9f696d2f1e340484b4683f7853b273abff94421f", "shasum": "" }, "require": { @@ -2335,7 +2338,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v7.3.2" + "source": "https://github.com/symfony/finder/tree/v7.3.5" }, "funding": [ { @@ -2355,7 +2358,7 @@ "type": "tidelift" } ], - "time": "2025-07-15T13:41:35+00:00" + "time": "2025-10-15T18:45:57+00:00" }, { "name": "symfony/polyfill-ctype", @@ -3323,23 +3326,23 @@ }, { "name": "symfony/property-info", - "version": "v7.3.1", + "version": "v7.3.5", "source": { "type": "git", "url": "https://github.com/symfony/property-info.git", - "reference": "90586acbf2a6dd13bee4f09f09111c8bd4773970" + "reference": "0b346ed259dc5da43535caf243005fe7d4b0f051" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/property-info/zipball/90586acbf2a6dd13bee4f09f09111c8bd4773970", - "reference": "90586acbf2a6dd13bee4f09f09111c8bd4773970", + "url": "https://api.github.com/repos/symfony/property-info/zipball/0b346ed259dc5da43535caf243005fe7d4b0f051", + "reference": "0b346ed259dc5da43535caf243005fe7d4b0f051", "shasum": "" }, "require": { "php": ">=8.2", "symfony/deprecation-contracts": "^2.5|^3", "symfony/string": "^6.4|^7.0", - "symfony/type-info": "~7.2.8|^7.3.1" + "symfony/type-info": "^7.3.5" }, "conflict": { "phpdocumentor/reflection-docblock": "<5.2", @@ -3389,7 +3392,7 @@ "validator" ], "support": { - "source": "https://github.com/symfony/property-info/tree/v7.3.1" + "source": "https://github.com/symfony/property-info/tree/v7.3.5" }, "funding": [ { @@ -3400,12 +3403,16 @@ "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": "2025-06-27T19:55:54+00:00" + "time": "2025-10-05T22:12:41+00:00" }, { "name": "symfony/serializer", @@ -3512,16 +3519,16 @@ }, { "name": "symfony/service-contracts", - "version": "v3.6.0", + "version": "v3.6.1", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4" + "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f021b05a130d35510bd6b25fe9053c2a8a15d5d4", - "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/45112560a3ba2d715666a509a0bc9521d10b6c43", + "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43", "shasum": "" }, "require": { @@ -3575,7 +3582,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.6.0" + "source": "https://github.com/symfony/service-contracts/tree/v3.6.1" }, "funding": [ { @@ -3586,12 +3593,16 @@ "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": "2025-04-25T09:37:31+00:00" + "time": "2025-07-15T11:30:57+00:00" }, { "name": "symfony/string", @@ -3867,16 +3878,16 @@ }, { "name": "symfony/type-info", - "version": "v7.3.3", + "version": "v7.3.5", "source": { "type": "git", "url": "https://github.com/symfony/type-info.git", - "reference": "aa64b58ed04517d4d730202dd035895743c23273" + "reference": "8b36f41421160db56914f897b57eaa6a830758b3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/type-info/zipball/aa64b58ed04517d4d730202dd035895743c23273", - "reference": "aa64b58ed04517d4d730202dd035895743c23273", + "url": "https://api.github.com/repos/symfony/type-info/zipball/8b36f41421160db56914f897b57eaa6a830758b3", + "reference": "8b36f41421160db56914f897b57eaa6a830758b3", "shasum": "" }, "require": { @@ -3926,7 +3937,7 @@ "type" ], "support": { - "source": "https://github.com/symfony/type-info/tree/v7.3.3" + "source": "https://github.com/symfony/type-info/tree/v7.3.5" }, "funding": [ { @@ -3946,7 +3957,7 @@ "type": "tidelift" } ], - "time": "2025-08-28T09:38:04+00:00" + "time": "2025-10-16T12:30:12+00:00" }, { "name": "voku/portable-ascii", @@ -4026,16 +4037,16 @@ "packages-dev": [ { "name": "brianium/paratest", - "version": "v7.14.1", + "version": "v7.14.2", "source": { "type": "git", "url": "https://github.com/paratestphp/paratest.git", - "reference": "e1a93c38a94f4808faf75552e835666d3a6f8bb2" + "reference": "de06de1ae1203b11976c6ca01d6a9081c8b33d45" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/paratestphp/paratest/zipball/e1a93c38a94f4808faf75552e835666d3a6f8bb2", - "reference": "e1a93c38a94f4808faf75552e835666d3a6f8bb2", + "url": "https://api.github.com/repos/paratestphp/paratest/zipball/de06de1ae1203b11976c6ca01d6a9081c8b33d45", + "reference": "de06de1ae1203b11976c6ca01d6a9081c8b33d45", "shasum": "" }, "require": { @@ -4049,7 +4060,7 @@ "phpunit/php-code-coverage": "^12.4.0", "phpunit/php-file-iterator": "^6", "phpunit/php-timer": "^8", - "phpunit/phpunit": "^12.4.0", + "phpunit/phpunit": "^12.4.1", "sebastian/environment": "^8.0.3", "symfony/console": "^6.4.20 || ^7.3.4", "symfony/process": "^6.4.20 || ^7.3.4" @@ -4059,7 +4070,7 @@ "ext-pcntl": "*", "ext-pcov": "*", "ext-posix": "*", - "phpstan/phpstan": "^2.1.30", + "phpstan/phpstan": "^2.1.31", "phpstan/phpstan-deprecation-rules": "^2.0.3", "phpstan/phpstan-phpunit": "^2.0.7", "phpstan/phpstan-strict-rules": "^2.0.7", @@ -4103,7 +4114,7 @@ ], "support": { "issues": "https://github.com/paratestphp/paratest/issues", - "source": "https://github.com/paratestphp/paratest/tree/v7.14.1" + "source": "https://github.com/paratestphp/paratest/tree/v7.14.2" }, "funding": [ { @@ -4115,7 +4126,7 @@ "type": "paypal" } ], - "time": "2025-10-06T08:26:52+00:00" + "time": "2025-10-24T07:20:53+00:00" }, { "name": "doctrine/deprecations", @@ -4553,16 +4564,16 @@ }, { "name": "nikic/php-parser", - "version": "v5.6.1", + "version": "v5.6.2", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2" + "reference": "3a454ca033b9e06b63282ce19562e892747449bb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2", - "reference": "f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/3a454ca033b9e06b63282ce19562e892747449bb", + "reference": "3a454ca033b9e06b63282ce19562e892747449bb", "shasum": "" }, "require": { @@ -4605,22 +4616,22 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.6.1" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.6.2" }, - "time": "2025-08-13T20:13:15+00:00" + "time": "2025-10-21T19:32:17+00:00" }, { "name": "nunomaduro/collision", - "version": "v8.8.2", + "version": "v8.8.3", "source": { "type": "git", "url": "https://github.com/nunomaduro/collision.git", - "reference": "60207965f9b7b7a4ce15a0f75d57f9dadb105bdb" + "reference": "1dc9e88d105699d0fee8bb18890f41b274f6b4c4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nunomaduro/collision/zipball/60207965f9b7b7a4ce15a0f75d57f9dadb105bdb", - "reference": "60207965f9b7b7a4ce15a0f75d57f9dadb105bdb", + "url": "https://api.github.com/repos/nunomaduro/collision/zipball/1dc9e88d105699d0fee8bb18890f41b274f6b4c4", + "reference": "1dc9e88d105699d0fee8bb18890f41b274f6b4c4", "shasum": "" }, "require": { @@ -4642,7 +4653,7 @@ "laravel/sanctum": "^4.1.1", "laravel/tinker": "^2.10.1", "orchestra/testbench-core": "^9.12.0 || ^10.4", - "pestphp/pest": "^3.8.2", + "pestphp/pest": "^3.8.2 || ^4.0.0", "sebastian/environment": "^7.2.1 || ^8.0" }, "type": "library", @@ -4706,35 +4717,35 @@ "type": "patreon" } ], - "time": "2025-06-25T02:12:12+00:00" + "time": "2025-11-20T02:55:25+00:00" }, { "name": "nunomaduro/termwind", - "version": "v2.3.1", + "version": "v2.3.3", "source": { "type": "git", "url": "https://github.com/nunomaduro/termwind.git", - "reference": "dfa08f390e509967a15c22493dc0bac5733d9123" + "reference": "6fb2a640ff502caace8e05fd7be3b503a7e1c017" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nunomaduro/termwind/zipball/dfa08f390e509967a15c22493dc0bac5733d9123", - "reference": "dfa08f390e509967a15c22493dc0bac5733d9123", + "url": "https://api.github.com/repos/nunomaduro/termwind/zipball/6fb2a640ff502caace8e05fd7be3b503a7e1c017", + "reference": "6fb2a640ff502caace8e05fd7be3b503a7e1c017", "shasum": "" }, "require": { "ext-mbstring": "*", "php": "^8.2", - "symfony/console": "^7.2.6" + "symfony/console": "^7.3.6" }, "require-dev": { - "illuminate/console": "^11.44.7", - "laravel/pint": "^1.22.0", + "illuminate/console": "^11.46.1", + "laravel/pint": "^1.25.1", "mockery/mockery": "^1.6.12", - "pestphp/pest": "^2.36.0 || ^3.8.2", - "phpstan/phpstan": "^1.12.25", + "pestphp/pest": "^2.36.0 || ^3.8.4 || ^4.1.3", + "phpstan/phpstan": "^1.12.32", "phpstan/phpstan-strict-rules": "^1.6.2", - "symfony/var-dumper": "^7.2.6", + "symfony/var-dumper": "^7.3.5", "thecodingmachine/phpstan-strict-rules": "^1.0.0" }, "type": "library", @@ -4777,7 +4788,7 @@ ], "support": { "issues": "https://github.com/nunomaduro/termwind/issues", - "source": "https://github.com/nunomaduro/termwind/tree/v2.3.1" + "source": "https://github.com/nunomaduro/termwind/tree/v2.3.3" }, "funding": [ { @@ -4793,20 +4804,20 @@ "type": "github" } ], - "time": "2025-05-08T08:14:37+00:00" + "time": "2025-11-20T02:34:59+00:00" }, { "name": "pestphp/pest", - "version": "v4.1.2", + "version": "v4.1.4", "source": { "type": "git", "url": "https://github.com/pestphp/pest.git", - "reference": "08b09f2e98fc6830050c0237968b233768642d46" + "reference": "1a39826935b730b0bcad805013d4b2607b83fe3f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pestphp/pest/zipball/08b09f2e98fc6830050c0237968b233768642d46", - "reference": "08b09f2e98fc6830050c0237968b233768642d46", + "url": "https://api.github.com/repos/pestphp/pest/zipball/1a39826935b730b0bcad805013d4b2607b83fe3f", + "reference": "1a39826935b730b0bcad805013d4b2607b83fe3f", "shasum": "" }, "require": { @@ -4818,12 +4829,12 @@ "pestphp/pest-plugin-mutate": "^4.0.1", "pestphp/pest-plugin-profanity": "^4.1.0", "php": "^8.3.0", - "phpunit/phpunit": "^12.4.0", + "phpunit/phpunit": "^12.4.1", "symfony/process": "^7.3.4" }, "conflict": { "filp/whoops": "<2.18.3", - "phpunit/phpunit": ">12.4.0", + "phpunit/phpunit": ">12.4.1", "sebastian/exporter": "<7.0.0", "webmozart/assert": "<1.11.0" }, @@ -4897,7 +4908,7 @@ ], "support": { "issues": "https://github.com/pestphp/pest/issues", - "source": "https://github.com/pestphp/pest/tree/v4.1.2" + "source": "https://github.com/pestphp/pest/tree/v4.1.4" }, "funding": [ { @@ -4909,7 +4920,7 @@ "type": "github" } ], - "time": "2025-10-05T19:09:49+00:00" + "time": "2025-11-20T02:59:27+00:00" }, { "name": "pestphp/pest-plugin", @@ -5129,16 +5140,16 @@ }, { "name": "pestphp/pest-plugin-profanity", - "version": "v4.1.0", + "version": "v4.2.0", "source": { "type": "git", "url": "https://github.com/pestphp/pest-plugin-profanity.git", - "reference": "e279c844b6868da92052be27b5202c2ad7216e80" + "reference": "c37e5e2c7136ee4eae12082e7952332bc1c6600a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pestphp/pest-plugin-profanity/zipball/e279c844b6868da92052be27b5202c2ad7216e80", - "reference": "e279c844b6868da92052be27b5202c2ad7216e80", + "url": "https://api.github.com/repos/pestphp/pest-plugin-profanity/zipball/c37e5e2c7136ee4eae12082e7952332bc1c6600a", + "reference": "c37e5e2c7136ee4eae12082e7952332bc1c6600a", "shasum": "" }, "require": { @@ -5179,9 +5190,9 @@ "unit" ], "support": { - "source": "https://github.com/pestphp/pest-plugin-profanity/tree/v4.1.0" + "source": "https://github.com/pestphp/pest-plugin-profanity/tree/v4.2.0" }, - "time": "2025-09-10T06:17:03+00:00" + "time": "2025-10-28T23:14:11+00:00" }, { "name": "phar-io/manifest", @@ -5356,16 +5367,16 @@ }, { "name": "phpdocumentor/reflection-docblock", - "version": "5.6.3", + "version": "5.6.4", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "94f8051919d1b0369a6bcc7931d679a511c03fe9" + "reference": "90a04bcbf03784066f16038e87e23a0a83cee3c2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/94f8051919d1b0369a6bcc7931d679a511c03fe9", - "reference": "94f8051919d1b0369a6bcc7931d679a511c03fe9", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/90a04bcbf03784066f16038e87e23a0a83cee3c2", + "reference": "90a04bcbf03784066f16038e87e23a0a83cee3c2", "shasum": "" }, "require": { @@ -5414,22 +5425,22 @@ "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", "support": { "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", - "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.6.3" + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.6.4" }, - "time": "2025-08-01T19:43:32+00:00" + "time": "2025-11-17T21:13:10+00:00" }, { "name": "phpdocumentor/type-resolver", - "version": "1.10.0", + "version": "1.11.1", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "679e3ce485b99e84c775d28e2e96fade9a7fb50a" + "reference": "f626740b38009078de0dc8b2b9dc4e7f749c6eba" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/679e3ce485b99e84c775d28e2e96fade9a7fb50a", - "reference": "679e3ce485b99e84c775d28e2e96fade9a7fb50a", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/f626740b38009078de0dc8b2b9dc4e7f749c6eba", + "reference": "f626740b38009078de0dc8b2b9dc4e7f749c6eba", "shasum": "" }, "require": { @@ -5472,9 +5483,9 @@ "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", "support": { "issues": "https://github.com/phpDocumentor/TypeResolver/issues", - "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.10.0" + "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.11.1" }, - "time": "2024-11-09T15:12:26+00:00" + "time": "2025-11-21T11:31:57+00:00" }, { "name": "phpstan/extension-installer", @@ -5573,20 +5584,15 @@ }, { "name": "phpstan/phpstan", - "version": "1.12.28", - "source": { - "type": "git", - "url": "https://github.com/phpstan/phpstan.git", - "reference": "fcf8b71aeab4e1a1131d1783cef97b23a51b87a9" - }, + "version": "2.1.32", "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/fcf8b71aeab4e1a1131d1783cef97b23a51b87a9", - "reference": "fcf8b71aeab4e1a1131d1783cef97b23a51b87a9", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/e126cad1e30a99b137b8ed75a85a676450ebb227", + "reference": "e126cad1e30a99b137b8ed75a85a676450ebb227", "shasum": "" }, "require": { - "php": "^7.2|^8.0" + "php": "^7.4|^8.0" }, "conflict": { "phpstan/phpstan-shim": "*" @@ -5627,7 +5633,7 @@ "type": "github" } ], - "time": "2025-07-17T17:15:39+00:00" + "time": "2025-11-11T15:18:17+00:00" }, { "name": "phpunit/php-code-coverage", @@ -5965,16 +5971,16 @@ }, { "name": "phpunit/phpunit", - "version": "12.4.0", + "version": "12.4.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "f62aab5794e36ccd26860db2d1bbf89ac19028d9" + "reference": "fc5413a2e6d240d2f6d9317bdf7f0a24e73de194" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/f62aab5794e36ccd26860db2d1bbf89ac19028d9", - "reference": "f62aab5794e36ccd26860db2d1bbf89ac19028d9", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/fc5413a2e6d240d2f6d9317bdf7f0a24e73de194", + "reference": "fc5413a2e6d240d2f6d9317bdf7f0a24e73de194", "shasum": "" }, "require": { @@ -6042,7 +6048,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/12.4.0" + "source": "https://github.com/sebastianbergmann/phpunit/tree/12.4.1" }, "funding": [ { @@ -6066,25 +6072,25 @@ "type": "tidelift" } ], - "time": "2025-10-03T04:28:03+00:00" + "time": "2025-10-09T14:08:29+00:00" }, { "name": "rector/rector", - "version": "1.2.10", + "version": "2.2.8", "source": { "type": "git", "url": "https://github.com/rectorphp/rector.git", - "reference": "40f9cf38c05296bd32f444121336a521a293fa61" + "reference": "303aa811649ccd1d32e51e62d5c85949d01b5f1b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/rectorphp/rector/zipball/40f9cf38c05296bd32f444121336a521a293fa61", - "reference": "40f9cf38c05296bd32f444121336a521a293fa61", + "url": "https://api.github.com/repos/rectorphp/rector/zipball/303aa811649ccd1d32e51e62d5c85949d01b5f1b", + "reference": "303aa811649ccd1d32e51e62d5c85949d01b5f1b", "shasum": "" }, "require": { - "php": "^7.2|^8.0", - "phpstan/phpstan": "^1.12.5" + "php": "^7.4|^8.0", + "phpstan/phpstan": "^2.1.32" }, "conflict": { "rector/rector-doctrine": "*", @@ -6109,6 +6115,7 @@ "MIT" ], "description": "Instant Upgrade and Automated Refactoring of any PHP code", + "homepage": "https://getrector.com/", "keywords": [ "automation", "dev", @@ -6117,7 +6124,7 @@ ], "support": { "issues": "https://github.com/rectorphp/rector/issues", - "source": "https://github.com/rectorphp/rector/tree/1.2.10" + "source": "https://github.com/rectorphp/rector/tree/2.2.8" }, "funding": [ { @@ -6125,7 +6132,7 @@ "type": "github" } ], - "time": "2024-11-08T13:59:10+00:00" + "time": "2025-11-12T18:38:00+00:00" }, { "name": "sebastian/cli-parser", @@ -7137,16 +7144,16 @@ }, { "name": "theseer/tokenizer", - "version": "1.2.3", + "version": "1.3.1", "source": { "type": "git", "url": "https://github.com/theseer/tokenizer.git", - "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" + "reference": "b7489ce515e168639d17feec34b8847c326b0b3c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", - "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/b7489ce515e168639d17feec34b8847c326b0b3c", + "reference": "b7489ce515e168639d17feec34b8847c326b0b3c", "shasum": "" }, "require": { @@ -7175,7 +7182,7 @@ "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", "support": { "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/1.2.3" + "source": "https://github.com/theseer/tokenizer/tree/1.3.1" }, "funding": [ { @@ -7183,7 +7190,7 @@ "type": "github" } ], - "time": "2024-03-03T12:36:25+00:00" + "time": "2025-11-17T20:03:58+00:00" }, { "name": "tightenco/duster", @@ -7255,21 +7262,21 @@ }, { "name": "tomasvotruba/cognitive-complexity", - "version": "0.2.3", + "version": "1.0.0", "source": { "type": "git", "url": "https://github.com/TomasVotruba/cognitive-complexity.git", - "reference": "02cde7462c6d0ae76b74d71b6e69a29e710cffb2" + "reference": "974586fbc31b448ec04cf7877767bbb775671c3f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/TomasVotruba/cognitive-complexity/zipball/02cde7462c6d0ae76b74d71b6e69a29e710cffb2", - "reference": "02cde7462c6d0ae76b74d71b6e69a29e710cffb2", + "url": "https://api.github.com/repos/TomasVotruba/cognitive-complexity/zipball/974586fbc31b448ec04cf7877767bbb775671c3f", + "reference": "974586fbc31b448ec04cf7877767bbb775671c3f", "shasum": "" }, "require": { - "php": "^7.2 || ^8.0", - "phpstan/phpstan": "^1.10" + "php": "^7.4 || ^8.0", + "phpstan/phpstan": "^2" }, "type": "phpstan-extension", "extra": { @@ -7291,7 +7298,7 @@ "description": "PHPStan rules to measure cognitive complexity of your classes and methods", "support": { "issues": "https://github.com/TomasVotruba/cognitive-complexity/issues", - "source": "https://github.com/TomasVotruba/cognitive-complexity/tree/0.2.3" + "source": "https://github.com/TomasVotruba/cognitive-complexity/tree/1.0.0" }, "funding": [ { @@ -7303,32 +7310,32 @@ "type": "github" } ], - "time": "2024-01-03T13:13:16+00:00" + "time": "2024-12-13T10:28:54+00:00" }, { "name": "webmozart/assert", - "version": "1.11.0", + "version": "1.12.1", "source": { "type": "git", "url": "https://github.com/webmozarts/assert.git", - "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991" + "reference": "9be6926d8b485f55b9229203f962b51ed377ba68" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991", - "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/9be6926d8b485f55b9229203f962b51ed377ba68", + "reference": "9be6926d8b485f55b9229203f962b51ed377ba68", "shasum": "" }, "require": { "ext-ctype": "*", + "ext-date": "*", + "ext-filter": "*", "php": "^7.2 || ^8.0" }, - "conflict": { - "phpstan/phpstan": "<0.12.20", - "vimeo/psalm": "<4.6.1 || 4.6.2" - }, - "require-dev": { - "phpunit/phpunit": "^8.5.13" + "suggest": { + "ext-intl": "", + "ext-simplexml": "", + "ext-spl": "" }, "type": "library", "extra": { @@ -7359,9 +7366,9 @@ ], "support": { "issues": "https://github.com/webmozarts/assert/issues", - "source": "https://github.com/webmozarts/assert/tree/1.11.0" + "source": "https://github.com/webmozarts/assert/tree/1.12.1" }, - "time": "2022-06-03T18:03:27+00:00" + "time": "2025-10-29T15:56:20+00:00" } ], "aliases": [], diff --git a/phpstan.neon b/phpstan.neon index 753f713..c8da40c 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,6 +1,3 @@ -#includes: -# - phpstan-baseline.neon - parameters: level: 8 paths: @@ -11,6 +8,7 @@ parameters: ignoreErrors: - identifier: missingType.generics - identifier: missingType.iterableValue + - identifier: trait.unused - '#PHPDoc tag .+ #' cognitive_complexity: class: 50 diff --git a/src/Exceptions/AssertionFailedException.php b/src/Exceptions/AssertionFailedException.php new file mode 100644 index 0000000..473013c --- /dev/null +++ b/src/Exceptions/AssertionFailedException.php @@ -0,0 +1,18 @@ +newInstance(); $mapper = $direction === self::MAPPER_DIRECTION_OUTPUT - ? ($mapNameInstance->output ?? $mapNameInstance->input) + ? $mapNameInstance->output : $mapNameInstance->input; - if ($mapper !== null) { - return self::getMapperResult($mapper, $propertyName); - } + return self::getMapperResult($mapper, $propertyName); } return null; diff --git a/src/Objects/Support/Assert.php b/src/Objects/Support/Assert.php new file mode 100644 index 0000000..1c7d3d9 --- /dev/null +++ b/src/Objects/Support/Assert.php @@ -0,0 +1,61 @@ + Date: Mon, 24 Nov 2025 16:53:40 +0000 Subject: [PATCH 03/10] Rectifying --- src/Objects/Support/Traits/Macroable.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Objects/Support/Traits/Macroable.php b/src/Objects/Support/Traits/Macroable.php index 14bdd96..dbd83d5 100644 --- a/src/Objects/Support/Traits/Macroable.php +++ b/src/Objects/Support/Traits/Macroable.php @@ -89,12 +89,10 @@ protected function deferToEloquentInstance(string $method, array $parameters): m /** * @param string $method - * @param array $parameters * @return mixed - * * @throws ReflectionException */ - public static function __callStatic($method, $parameters) + public static function __callStatic($method, array $parameters) { // Check if a macro exists for the method if (static::hasMacro($method)) { From aae03ce39f9cc4551236da3b7d26a38b791844c6 Mon Sep 17 00:00:00 2001 From: EncoreBot Date: Mon, 24 Nov 2025 16:53:40 +0000 Subject: [PATCH 04/10] Ignore Rector Commit in Git Blame --- .git-blame-ignore-revs | 1 + 1 file changed, 1 insertion(+) diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index 6336d8e..b3d5e3c 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -53,3 +53,4 @@ c400a3c655b1157b8ff30f5c2ead30563fad972a 9ceb35f77a0bfefe8bf4b51d5026399f12ad79b0 8614c245e767ac74c2ca65697553b70bf54394ad e7d3e86c6e045f09131ec7cdb3e2cf0887e7eb21 +7350f8fc64aa43ff050446bd64157a28f73e21d4 From bb927a60f808d44d10b6ffbd796982a3e5022c44 Mon Sep 17 00:00:00 2001 From: EncoreBot Date: Mon, 24 Nov 2025 16:53:58 +0000 Subject: [PATCH 05/10] Dusting --- src/Exceptions/AssertionFailedException.php | 1 + src/Objects/Serializers/JsonSerializer.php | 1 + src/Objects/Support/Traits/Assertable.php | 1 + src/Objects/Support/Traits/Macroable.php | 1 + 4 files changed, 4 insertions(+) diff --git a/src/Exceptions/AssertionFailedException.php b/src/Exceptions/AssertionFailedException.php index 473013c..d99ecfd 100644 --- a/src/Exceptions/AssertionFailedException.php +++ b/src/Exceptions/AssertionFailedException.php @@ -1,4 +1,5 @@ output : $mapNameInstance->input; + return self::getMapperResult($mapper, $propertyName); } diff --git a/src/Objects/Support/Traits/Assertable.php b/src/Objects/Support/Traits/Assertable.php index b2e4474..1e46c43 100644 --- a/src/Objects/Support/Traits/Assertable.php +++ b/src/Objects/Support/Traits/Assertable.php @@ -1,4 +1,5 @@ Date: Mon, 24 Nov 2025 16:53:58 +0000 Subject: [PATCH 06/10] Ignore Duster Commit in Git Blame --- .git-blame-ignore-revs | 1 + 1 file changed, 1 insertion(+) diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index b3d5e3c..29f988f 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -54,3 +54,4 @@ c400a3c655b1157b8ff30f5c2ead30563fad972a 8614c245e767ac74c2ca65697553b70bf54394ad e7d3e86c6e045f09131ec7cdb3e2cf0887e7eb21 7350f8fc64aa43ff050446bd64157a28f73e21d4 +bb927a60f808d44d10b6ffbd796982a3e5022c44 From 17f5724edec2a2ad56e49510d3dc26fb57694293 Mon Sep 17 00:00:00 2001 From: Marc Beinder Date: Mon, 24 Nov 2025 17:37:14 -0600 Subject: [PATCH 07/10] Update default error code in AssertionFailedException constructor --- src/Exceptions/AssertionFailedException.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Exceptions/AssertionFailedException.php b/src/Exceptions/AssertionFailedException.php index d99ecfd..1af2e80 100644 --- a/src/Exceptions/AssertionFailedException.php +++ b/src/Exceptions/AssertionFailedException.php @@ -12,7 +12,7 @@ class AssertionFailedException extends BaseException { - public function __construct(string $message = "Assertion Failed", int $code = ExitCode::SUCCESS, ?Throwable $previous = null) + public function __construct(string $message = "Assertion Failed", int $code = ExitCode::GENERAL_ERROR, ?Throwable $previous = null) { parent::__construct($message, $code, $previous); } From 25a09cff3f440ee695a06ab6134b2d20d95bb901 Mon Sep 17 00:00:00 2001 From: Marc Beinder Date: Mon, 24 Nov 2025 17:38:48 -0600 Subject: [PATCH 08/10] Improve error messages in AssertionFailedException for boolean and null assertions --- src/Objects/Support/Assert.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Objects/Support/Assert.php b/src/Objects/Support/Assert.php index 1c7d3d9..498ecc2 100644 --- a/src/Objects/Support/Assert.php +++ b/src/Objects/Support/Assert.php @@ -17,11 +17,11 @@ class Assert public static function true(mixed $value): void { if (!is_bool($value)) { - throw new AssertionFailedException; + throw new AssertionFailedException("Failed to assert true: value is not a boolean."); } if (!$value) { - throw new AssertionFailedException("Failed to assert true"); + throw new AssertionFailedException("Failed to assert true."); } } @@ -31,11 +31,11 @@ public static function true(mixed $value): void public static function false(mixed $value): void { if (!is_bool($value)) { - throw new AssertionFailedException; + throw new AssertionFailedException("Failed to assert false: value is not a boolean."); } if ($value) { - throw new AssertionFailedException("Failed to assert false"); + throw new AssertionFailedException("Failed to assert false."); } } @@ -45,7 +45,7 @@ public static function false(mixed $value): void public static function notNull(mixed $value): void { if (is_null($value)) { - throw new AssertionFailedException("Failed to assert not null"); + throw new AssertionFailedException("Failed to assert not null."); } } @@ -55,7 +55,7 @@ public static function notNull(mixed $value): void public static function string(mixed $value): void { if (!is_string($value)) { - throw new AssertionFailedException("Failed to assert string"); + throw new AssertionFailedException("Failed to assert string."); } } } \ No newline at end of file From bc230587f3446b85b9888f6ee5b5ae8316eabfe9 Mon Sep 17 00:00:00 2001 From: Marc Beinder Date: Mon, 24 Nov 2025 17:49:43 -0600 Subject: [PATCH 09/10] Add section on Assertions to README with overview of runtime assertion utilities --- docs/README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/README.md b/docs/README.md index 8638c82..95a4344 100644 --- a/docs/README.md +++ b/docs/README.md @@ -59,6 +59,12 @@ Date and time utilities with type-safe operations: - **DayOfWeek** - Type-safe day representation with flexible conversion - **Month** - Month enumeration with navigation capabilities +### [Assertions](./assertions.md) + +Runtime assertion utilities for verifying programming assumptions: + +- **Assert** - Precondition, postcondition, and invariant verification with static analysis integration + ### [Core Objects and Utilities](./core-objects.md) Foundational classes providing system-wide functionality: From f037f178a0909dc9a63c7c7d3babe97ac0378d23 Mon Sep 17 00:00:00 2001 From: Marc Beinder Date: Mon, 24 Nov 2025 17:50:07 -0600 Subject: [PATCH 10/10] Add documentation for Assert class and its runtime assertion utilities --- docs/assertions.md | 272 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 272 insertions(+) create mode 100644 docs/assertions.md diff --git a/docs/assertions.md b/docs/assertions.md new file mode 100644 index 0000000..de9a935 --- /dev/null +++ b/docs/assertions.md @@ -0,0 +1,272 @@ +# Assertions + +The `Assert` class provides runtime assertion utilities for verifying preconditions, postconditions, and invariants in your code. Unlike validation, assertions verify assumptions that **must** be true for the program to continue safely. + +## Purpose + +Runtime verification of programming assumptions with static analysis integration. When assertions fail, they indicate bugs that should be fixed rather than conditions that should be handled gracefully. + +## Key Methods + +### Boolean Assertions + +- `true(mixed $value)` - Asserts that a value is boolean true +- `false(mixed $value)` - Asserts that a value is boolean false + +### Null Assertions + +- `notNull(mixed $value)` - Asserts that a value is not null + +### Type Assertions + +- `string(mixed $value)` - Asserts that a value is a string + +## Usage Scenarios + +### Precondition Verification + +Verify function inputs meet required assumptions: + +```php +public function processUser(?User $user): void +{ + Assert::notNull($user); + // $user is guaranteed non-null here + $user->doSomething(); +} +``` + +### Type Narrowing with Static Analysis + +Use assertions to help static analysis tools understand type guarantees: + +```php +function handleValue(mixed $value): void +{ + Assert::string($value); + // PHPStan now knows $value is string + echo strtoupper($value); +} +``` + +### Postcondition Verification + +Verify function outputs meet expected conditions: + +```php +public function findUser(int $id): User +{ + $user = $this->repository->find($id); + Assert::notNull($user); + return $user; +} +``` + +### Invariant Checking + +Verify state consistency during complex operations: + +```php +public function transfer(Account $from, Account $to, int $amount): void +{ + $totalBefore = $from->balance + $to->balance; + + $from->withdraw($amount); + $to->deposit($amount); + + $totalAfter = $from->balance + $to->balance; + Assert::true($totalBefore === $totalAfter); +} +``` + +## When to Use Assertions + +### Use Assertions For: + +- **Programming errors** - Violations of assumed contracts or invariants +- **Developer mistakes** - Incorrect API usage or invalid state +- **Type narrowing** - Helping static analysis understand guarantees +- **Defensive programming** - Fail fast when assumptions are violated +- **Development debugging** - Catching bugs early in development + +### Don't Use Assertions For: + +- **User input validation** - Use validation classes instead +- **Expected error conditions** - Use proper error handling +- **Business logic validation** - Use domain-specific validation +- **Recoverable errors** - Use exceptions meant to be caught +- **Production-only checks** - Assertions should be permanent + +## Exception Handling + +### Should You Catch Assertion Exceptions? + +**Generally, no.** Assertion failures indicate programming errors that should halt execution: + +```php +// DON'T catch assertion failures +try { + Assert::notNull($user); + $user->doSomething(); +} catch (AssertionFailedException $e) { + // This masks a bug that should be fixed +} +``` + +When an assertion fails, the program should crash with a clear error message indicating what assumption was violated. This helps developers identify and fix bugs quickly. + +### Exception Details + +- Throws: `AssertionFailedException` +- Exit code: `ExitCode::GENERAL_ERROR` +- Message: Descriptive text indicating which assertion failed + +### When Catching Is Acceptable + +Only catch assertion exceptions in specific scenarios: + +- **Testing** - Verify that assertions work correctly +- **Framework-level error handling** - Global exception handlers that log and report +- **Development tools** - IDE integrations or debugging utilities + +```php +// Acceptable in tests +test('throws when value is null', function () { + expect(fn() => Assert::notNull(null)) + ->toThrow(AssertionFailedException::class); +}); +``` + +## Static Analysis Integration + +All assertion methods include PHPStan annotations for type narrowing: + +- `@phpstan-assert true $value` - Narrows to boolean true +- `@phpstan-assert false $value` - Narrows to boolean false +- `@phpstan-assert !null $value` - Narrows to non-null +- `@phpstan-assert string $value` - Narrows to string type + +This enables static analysis tools to understand the guarantees provided by assertions: + +```php +function example(mixed $value): void +{ + Assert::string($value); + // No PHPStan error: $value is known to be string + echo strtoupper($value); +} +``` + +## Assertions vs Validation + +### Assertions + +- Verify **programming assumptions** +- Should **never** fail in correct code +- Indicate **bugs** when they fail +- **Not** meant to be caught +- Used for **development** and **debugging** + +### Validation + +- Verify **user input** or **external data** +- **Expected** to fail sometimes +- Indicate **invalid input** when they fail +- **Meant** to be caught and handled +- Used for **business logic** and **security** + +## Best Practices + +### Write Clear Assertion Messages + +Boolean assertions check the type first and provide specific error messages: + +```php +Assert::true($value); +// "Failed to assert true: value is not a boolean." +// or "Failed to assert true." +``` + +### Fail Fast + +Place assertions early in functions to catch violations immediately: + +```php +public function process(mixed $data): void +{ + Assert::string($data); // Fail fast + // Rest of function knows $data is string +} +``` + +### Use Appropriate Assertion Types + +Choose the most specific assertion for your needs: + +```php +// Good: Specific assertion +Assert::string($value); + +// Bad: Too generic +Assert::true(is_string($value)); +``` + +### Don't Assert Expected Conditions + +Only assert conditions that indicate bugs: + +```php +// Bad: User input validation should not use assertions +Assert::true($email !== ''); + +// Good: Use proper validation +if ($email === '') { + throw new ValidationException('Email is required'); +} +``` + +## Performance Considerations + +- Assertions execute on every call in all environments +- No performance overhead for assertion checking +- Failed assertions halt execution immediately +- Consider the cost of complex assertion conditions + +## Common Patterns + +### Guard Clauses with Assertions + +```php +public function updateUser(?User $user): void +{ + Assert::notNull($user); + // Guaranteed non-null, continue safely + $user->update(['last_seen' => now()]); +} +``` + +### Type-Safe Conversions + +```php +public function formatName(mixed $name): string +{ + Assert::string($name); + return Str::title($name); +} +``` + +### Invariant Maintenance + +```php +public function setBalance(int $balance): void +{ + $this->balance = $balance; + Assert::true($this->balance >= 0); +} +``` + +## Related Components + +- `AssertionFailedException` - Exception thrown on assertion failures +- `ExitCode` - Provides exit code constants including `GENERAL_ERROR` +- PHPStan - Static analysis tool that understands assertion annotations \ No newline at end of file