Update composer dependencies
authorTim Düsterhus <duesterhus@woltlab.com>
Mon, 21 Aug 2023 12:50:19 +0000 (14:50 +0200)
committerTim Düsterhus <duesterhus@woltlab.com>
Mon, 21 Aug 2023 12:50:50 +0000 (14:50 +0200)
102 files changed:
wcfsetup/install/files/lib/system/api/composer.json
wcfsetup/install/files/lib/system/api/composer.lock
wcfsetup/install/files/lib/system/api/composer/autoload_classmap.php
wcfsetup/install/files/lib/system/api/composer/autoload_static.php
wcfsetup/install/files/lib/system/api/composer/installed.json
wcfsetup/install/files/lib/system/api/composer/installed.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/composer.json
wcfsetup/install/files/lib/system/api/cuyz/valinor/qa/PHPStan/Extension/TreeMapperPHPStanExtension.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Cache/Compiled/CompiledPhpFileCache.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Cache/FileWatchingCache.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Cache/Warmup/RecursiveCacheWarmupService.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Definition/ClassDefinition.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Definition/FunctionDefinition.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Definition/FunctionsContainer.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Definition/MethodDefinition.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Definition/NativeAttributes.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Definition/ParameterDefinition.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Definition/PropertyDefinition.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Definition/Repository/Cache/CacheClassDefinitionRepository.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Definition/Repository/Cache/CacheFunctionDefinitionRepository.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Definition/Repository/Cache/Compiler/AttributesCompiler.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Definition/Repository/Cache/Compiler/ParameterDefinitionCompiler.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Definition/Repository/Cache/Compiler/PropertyDefinitionCompiler.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Definition/Repository/Cache/Compiler/TypeCompiler.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Definition/Repository/Reflection/ReflectionParameterDefinitionBuilder.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Definition/Repository/Reflection/ReflectionPropertyDefinitionBuilder.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Definition/Repository/Reflection/ReflectionTypeResolver.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Library/Container.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Library/Settings.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Mapper/Object/DateTimeFormatConstructor.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Mapper/Object/DynamicConstructor.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Mapper/Object/Exception/InvalidConstructorReturnType.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Mapper/Object/Factory/CacheObjectBuilderFactory.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Mapper/Object/Factory/CollisionObjectBuilderFactory.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Mapper/Object/Factory/ConstructorObjectBuilderFactory.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Mapper/Object/Factory/DateTimeObjectBuilderFactory.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Mapper/Object/Factory/StrictTypesObjectBuilderFactory.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Mapper/Object/MethodObjectBuilder.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Mapper/Object/NativeConstructorObjectBuilder.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Mapper/Object/ReflectionObjectBuilder.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Mapper/Source/Exception/InvalidJson.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Mapper/Source/JsonSource.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Mapper/Source/Source.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Mapper/Tree/Builder/ArrayNodeBuilder.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Mapper/Tree/Builder/CasterNodeBuilder.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Mapper/Tree/Builder/CasterProxyNodeBuilder.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Mapper/Tree/Builder/InterfaceNodeBuilder.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Mapper/Tree/Builder/IterableNodeBuilder.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Mapper/Tree/Builder/ListNodeBuilder.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Mapper/Tree/Builder/NativeClassNodeBuilder.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Mapper/Tree/Builder/ObjectNodeBuilder.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Mapper/Tree/Builder/RootNodeBuilder.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Mapper/Tree/Builder/ScalarNodeBuilder.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Mapper/Tree/Builder/ShapedArrayNodeBuilder.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Mapper/Tree/Builder/StrictNodeBuilder.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Mapper/Tree/Builder/UnionNodeBuilder.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Mapper/Tree/Builder/ValueAlteringNodeBuilder.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Mapper/Tree/Message/ErrorMessage.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Mapper/Tree/Message/Formatter/LocaleMessageFormatter.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Mapper/Tree/Message/Formatter/MessageMapFormatter.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Mapper/Tree/Message/MessageBuilder.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Mapper/TypeTreeMapper.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/MapperBuilder.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Type/ClassType.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Type/Parser/CachedParser.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Type/Parser/Exception/InvalidType.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Type/Parser/Exception/Template/InvalidTemplate.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Type/Parser/Factory/LexingTypeParserFactory.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Type/Parser/Factory/Specifications/AliasSpecification.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Type/Parser/Factory/Specifications/ClassContextSpecification.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Type/Parser/Factory/Specifications/TypeAliasAssignerSpecification.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Type/Parser/Lexer/AdvancedClassLexer.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Type/Parser/Lexer/AliasLexer.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Type/Parser/Lexer/Token/AdvancedClassNameToken.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Type/Parser/Lexer/Token/ArrayToken.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Type/Parser/Lexer/Token/CaseFinder.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Type/Parser/Lexer/Token/EnumNameToken.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Type/Parser/Lexer/Token/FloatValueToken.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Type/Parser/Lexer/Token/IntegerValueToken.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Type/Parser/Lexer/Token/ListToken.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Type/Parser/Lexer/Token/NativeToken.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Type/Parser/Lexer/Token/QuoteToken.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Type/Parser/Lexer/Token/TypeToken.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Type/Parser/Lexer/Token/UnknownSymbolToken.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Type/Parser/Lexer/TypeAliasLexer.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Type/Parser/LexingParser.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Type/Types/BooleanValueType.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Type/Types/FloatValueType.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Type/Types/IntegerValueType.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Type/Types/InterfaceType.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Type/Types/ShapedArrayElement.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Type/Types/StringValueType.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Type/Types/UnresolvableType.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Utility/String/StringCutter.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Utility/String/StringFormatter.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Utility/String/StringFormatterError.php
wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Utility/ValueDumper.php
wcfsetup/install/files/lib/system/api/dragonmantank/cron-expression/CHANGELOG.md
wcfsetup/install/files/lib/system/api/dragonmantank/cron-expression/README.md
wcfsetup/install/files/lib/system/api/dragonmantank/cron-expression/phpstan.neon [deleted file]
wcfsetup/install/files/lib/system/api/dragonmantank/cron-expression/src/Cron/CronExpression.php
wcfsetup/install/files/lib/system/api/dragonmantank/cron-expression/src/Cron/MinutesField.php

index 0554681b257d740300b9a1eb6ab23ce3c55e60c0..c3c3af3549dbf4fa3286223dca4e2f24f0493406 100644 (file)
@@ -10,8 +10,8 @@
         }
     },
     "require": {
-        "cuyz/valinor": "^1.4.0",
-        "dragonmantank/cron-expression": "^3.3.2",
+        "cuyz/valinor": "^1.5.0",
+        "dragonmantank/cron-expression": "^3.3.3",
         "erusev/parsedown": "^1.7.4",
         "ezyang/htmlpurifier": "^4.16",
         "guzzlehttp/guzzle": "^7.7.0",
index 3a8385d04b358c4aa95c239e48a003441e8163ae..c75674ce37c6bbc768172de299fc3896aad5c907 100644 (file)
@@ -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": "d94553c231572f020140e0c1ed535635",
+    "content-hash": "19268d8275d6b8c74c4fc8303d9cb0f2",
     "packages": [
         {
             "name": "cuyz/valinor",
-            "version": "1.4.0",
+            "version": "1.5.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/CuyZ/Valinor.git",
-                "reference": "229098184cf5877ec01305461cdcb8a73379bf5b"
+                "reference": "668cd3f0f95c57d75981a31d63b5b1422606bc7e"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/CuyZ/Valinor/zipball/229098184cf5877ec01305461cdcb8a73379bf5b",
-                "reference": "229098184cf5877ec01305461cdcb8a73379bf5b",
+                "url": "https://api.github.com/repos/CuyZ/Valinor/zipball/668cd3f0f95c57d75981a31d63b5b1422606bc7e",
+                "reference": "668cd3f0f95c57d75981a31d63b5b1422606bc7e",
                 "shasum": ""
             },
             "require": {
@@ -69,7 +69,7 @@
             ],
             "support": {
                 "issues": "https://github.com/CuyZ/Valinor/issues",
-                "source": "https://github.com/CuyZ/Valinor/tree/1.4.0"
+                "source": "https://github.com/CuyZ/Valinor/tree/1.5.0"
             },
             "funding": [
                 {
                     "type": "github"
                 }
             ],
-            "time": "2023-04-17T11:25:01+00:00"
+            "time": "2023-08-07T18:29:08+00:00"
         },
         {
             "name": "dragonmantank/cron-expression",
-            "version": "v3.3.2",
+            "version": "v3.3.3",
             "source": {
                 "type": "git",
                 "url": "https://github.com/dragonmantank/cron-expression.git",
-                "reference": "782ca5968ab8b954773518e9e49a6f892a34b2a8"
+                "reference": "adfb1f505deb6384dc8b39804c5065dd3c8c8c0a"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/782ca5968ab8b954773518e9e49a6f892a34b2a8",
-                "reference": "782ca5968ab8b954773518e9e49a6f892a34b2a8",
+                "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/adfb1f505deb6384dc8b39804c5065dd3c8c8c0a",
+                "reference": "adfb1f505deb6384dc8b39804c5065dd3c8c8c0a",
                 "shasum": ""
             },
             "require": {
             ],
             "support": {
                 "issues": "https://github.com/dragonmantank/cron-expression/issues",
-                "source": "https://github.com/dragonmantank/cron-expression/tree/v3.3.2"
+                "source": "https://github.com/dragonmantank/cron-expression/tree/v3.3.3"
             },
             "funding": [
                 {
                     "type": "github"
                 }
             ],
-            "time": "2022-09-10T18:51:20+00:00"
+            "time": "2023-08-10T19:36:49+00:00"
         },
         {
             "name": "erusev/parsedown",
index 341fb46d746cdbccca9b3c868fb0afe3f225d2e9..dee9c56dcb8910d078c395c1093c3b97e624c662 100644 (file)
@@ -339,6 +339,7 @@ return array(
     'CuyZ\\Valinor\\Utility\\Reflection\\PhpParser' => $vendorDir . '/cuyz/valinor/src/Utility/Reflection/PhpParser.php',
     'CuyZ\\Valinor\\Utility\\Reflection\\Reflection' => $vendorDir . '/cuyz/valinor/src/Utility/Reflection/Reflection.php',
     'CuyZ\\Valinor\\Utility\\Reflection\\TokenParser' => $vendorDir . '/cuyz/valinor/src/Utility/Reflection/TokenParser.php',
+    'CuyZ\\Valinor\\Utility\\String\\StringCutter' => $vendorDir . '/cuyz/valinor/src/Utility/String/StringCutter.php',
     'CuyZ\\Valinor\\Utility\\String\\StringFormatter' => $vendorDir . '/cuyz/valinor/src/Utility/String/StringFormatter.php',
     'CuyZ\\Valinor\\Utility\\String\\StringFormatterError' => $vendorDir . '/cuyz/valinor/src/Utility/String/StringFormatterError.php',
     'CuyZ\\Valinor\\Utility\\TypeHelper' => $vendorDir . '/cuyz/valinor/src/Utility/TypeHelper.php',
index 4bad81d871c85639cc3664d46f563c4987d38b13..e3dd6453c94b0140fee15f21c07145cf731c785a 100644 (file)
@@ -521,6 +521,7 @@ class ComposerStaticInita1f5f7c74275d47a45049a2936db1d0d
         'CuyZ\\Valinor\\Utility\\Reflection\\PhpParser' => __DIR__ . '/..' . '/cuyz/valinor/src/Utility/Reflection/PhpParser.php',
         'CuyZ\\Valinor\\Utility\\Reflection\\Reflection' => __DIR__ . '/..' . '/cuyz/valinor/src/Utility/Reflection/Reflection.php',
         'CuyZ\\Valinor\\Utility\\Reflection\\TokenParser' => __DIR__ . '/..' . '/cuyz/valinor/src/Utility/Reflection/TokenParser.php',
+        'CuyZ\\Valinor\\Utility\\String\\StringCutter' => __DIR__ . '/..' . '/cuyz/valinor/src/Utility/String/StringCutter.php',
         'CuyZ\\Valinor\\Utility\\String\\StringFormatter' => __DIR__ . '/..' . '/cuyz/valinor/src/Utility/String/StringFormatter.php',
         'CuyZ\\Valinor\\Utility\\String\\StringFormatterError' => __DIR__ . '/..' . '/cuyz/valinor/src/Utility/String/StringFormatterError.php',
         'CuyZ\\Valinor\\Utility\\TypeHelper' => __DIR__ . '/..' . '/cuyz/valinor/src/Utility/TypeHelper.php',
index 989b93522e303bc0db93f5038c0baba38df8604c..7c4dc6ad7f6ca790dbcaa0401c7995e93f8e30f6 100644 (file)
@@ -2,17 +2,17 @@
     "packages": [
         {
             "name": "cuyz/valinor",
-            "version": "1.4.0",
-            "version_normalized": "1.4.0.0",
+            "version": "1.5.0",
+            "version_normalized": "1.5.0.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/CuyZ/Valinor.git",
-                "reference": "229098184cf5877ec01305461cdcb8a73379bf5b"
+                "reference": "668cd3f0f95c57d75981a31d63b5b1422606bc7e"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/CuyZ/Valinor/zipball/229098184cf5877ec01305461cdcb8a73379bf5b",
-                "reference": "229098184cf5877ec01305461cdcb8a73379bf5b",
+                "url": "https://api.github.com/repos/CuyZ/Valinor/zipball/668cd3f0f95c57d75981a31d63b5b1422606bc7e",
+                "reference": "668cd3f0f95c57d75981a31d63b5b1422606bc7e",
                 "shasum": ""
             },
             "require": {
@@ -32,7 +32,7 @@
                 "rector/rector": "~0.15.0",
                 "vimeo/psalm": "^5.0"
             },
-            "time": "2023-04-17T11:25:01+00:00",
+            "time": "2023-08-07T18:29:08+00:00",
             "type": "library",
             "installation-source": "dist",
             "autoload": {
@@ -66,7 +66,7 @@
             ],
             "support": {
                 "issues": "https://github.com/CuyZ/Valinor/issues",
-                "source": "https://github.com/CuyZ/Valinor/tree/1.4.0"
+                "source": "https://github.com/CuyZ/Valinor/tree/1.5.0"
             },
             "funding": [
                 {
         },
         {
             "name": "dragonmantank/cron-expression",
-            "version": "v3.3.2",
-            "version_normalized": "3.3.2.0",
+            "version": "v3.3.3",
+            "version_normalized": "3.3.3.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/dragonmantank/cron-expression.git",
-                "reference": "782ca5968ab8b954773518e9e49a6f892a34b2a8"
+                "reference": "adfb1f505deb6384dc8b39804c5065dd3c8c8c0a"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/782ca5968ab8b954773518e9e49a6f892a34b2a8",
-                "reference": "782ca5968ab8b954773518e9e49a6f892a34b2a8",
+                "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/adfb1f505deb6384dc8b39804c5065dd3c8c8c0a",
+                "reference": "adfb1f505deb6384dc8b39804c5065dd3c8c8c0a",
                 "shasum": ""
             },
             "require": {
                 "phpstan/phpstan-webmozart-assert": "^1.0",
                 "phpunit/phpunit": "^7.0|^8.0|^9.0"
             },
-            "time": "2022-09-10T18:51:20+00:00",
+            "time": "2023-08-10T19:36:49+00:00",
             "type": "library",
             "installation-source": "dist",
             "autoload": {
             ],
             "support": {
                 "issues": "https://github.com/dragonmantank/cron-expression/issues",
-                "source": "https://github.com/dragonmantank/cron-expression/tree/v3.3.2"
+                "source": "https://github.com/dragonmantank/cron-expression/tree/v3.3.3"
             },
             "funding": [
                 {
index ffe1d47fd32a3e70e09c0a7a62ddadd2f08611bb..8db1af492843fa7fb0c3c67b9f1ba82d4f11a6ea 100644 (file)
             'dev_requirement' => false,
         ),
         'cuyz/valinor' => array(
-            'pretty_version' => '1.4.0',
-            'version' => '1.4.0.0',
-            'reference' => '229098184cf5877ec01305461cdcb8a73379bf5b',
+            'pretty_version' => '1.5.0',
+            'version' => '1.5.0.0',
+            'reference' => '668cd3f0f95c57d75981a31d63b5b1422606bc7e',
             'type' => 'library',
             'install_path' => __DIR__ . '/../cuyz/valinor',
             'aliases' => array(),
             'dev_requirement' => false,
         ),
         'dragonmantank/cron-expression' => array(
-            'pretty_version' => 'v3.3.2',
-            'version' => '3.3.2.0',
-            'reference' => '782ca5968ab8b954773518e9e49a6f892a34b2a8',
+            'pretty_version' => 'v3.3.3',
+            'version' => '3.3.3.0',
+            'reference' => 'adfb1f505deb6384dc8b39804c5065dd3c8c8c0a',
             'type' => 'library',
             'install_path' => __DIR__ . '/../dragonmantank/cron-expression',
             'aliases' => array(),
         'psr/http-factory-implementation' => array(
             'dev_requirement' => false,
             'provided' => array(
-                0 => '^1.1 || ^2.0',
-                1 => '1.0',
+                0 => '1.0',
+                1 => '^1.1 || ^2.0',
             ),
         ),
         'psr/http-message' => array(
         'psr/http-message-implementation' => array(
             'dev_requirement' => false,
             'provided' => array(
-                0 => '^1.1 || ^2.0',
-                1 => '1.0',
+                0 => '1.0',
+                1 => '^1.1 || ^2.0',
             ),
         ),
         'psr/http-server-handler' => array(
index 6765e71f508e87ec495b5b877b408bcb0717aeb0..2e7a92015ca6f463b6b23dec8e51ba96f3187861 100644 (file)
             "psalm --config=tests/StaticAnalysis/psalm-with-plugin.xml",
             "phpstan --configuration=tests/StaticAnalysis/phpstan-without-extension.neon.dist",
             "phpstan --configuration=tests/StaticAnalysis/phpstan-with-extension.neon.dist",
-            "@putenv PHP_CS_FIXER_IGNORE_ENV=1",
             "php-cs-fixer fix --dry-run",
-            "rector --dry-run"
+            "rector --dry-run",
+            "@check-todo"
+        ],
+        "check-todo": [
+            "! git --no-pager grep --extended-regexp --ignore-case 'todo|fixme' -- ':!composer.json' ':!*/quality-assurance.yml'"
         ],
         "fix": [
             "@putenv XDEBUG_MODE=off",
-            "@putenv PHP_CS_FIXER_IGNORE_ENV=1",
             "php-cs-fixer fix",
             "rector"
         ],
index 18a2a498505959c741ab99cf296d5b11055240a3..ac447d9db4dcc46e75014c9710be149d3a4e5720 100644 (file)
@@ -20,9 +20,7 @@ use PHPStan\Type\UnionType;
 
 final class TreeMapperPHPStanExtension implements DynamicMethodReturnTypeExtension
 {
-    public function __construct(private TypeStringResolver $resolver)
-    {
-    }
+    public function __construct(private TypeStringResolver $resolver) {}
 
     public function getClass(): string
     {
index 97ffa69cb61960ee1d8823701355afb46507ce8f..88cbe1796382a8f5f12ae7417360cfa01c60f457 100644 (file)
@@ -44,8 +44,7 @@ final class CompiledPhpFileCache implements CacheInterface
     public function __construct(
         private string $cacheDir,
         private CacheCompiler $compiler
-    ) {
-    }
+    ) {}
 
     public function has($key): bool
     {
@@ -114,6 +113,10 @@ final class CompiledPhpFileCache implements CacheInterface
 
     public function clear(): bool
     {
+        if (! is_dir($this->cacheDir)) {
+            return true;
+        }
+
         $success = true;
 
         /** @var FilesystemIterator $file */
index d9cf7b076708a0aa97f744c7c7664e09a9cc1b32..770d38c68927104fb864c16197ad64db5bbfa6a6 100644 (file)
@@ -39,8 +39,7 @@ final class FileWatchingCache implements CacheInterface
     public function __construct(
         /** @var CacheInterface<EntryType|TimestampsArray> */
         private CacheInterface $delegate
-    ) {
-    }
+    ) {}
 
     public function has($key): bool
     {
index 4d0af544f42803d92d82998f9b7e6e87a9794c06..f22beca30505392e555d1baee2b7c57f1aa043cf 100644 (file)
@@ -28,8 +28,7 @@ final class RecursiveCacheWarmupService
         private ObjectImplementations $implementations,
         private ClassDefinitionRepository $classDefinitionRepository,
         private ObjectBuilderFactory $objectBuilderFactory
-    ) {
-    }
+    ) {}
 
     public function warmup(string ...$signatures): void
     {
index 1fac82a60f9c66522abb3067759ee965c70bcaad..74b11d49e755f1e0395f604fdb1f885db48a41fe 100644 (file)
@@ -16,8 +16,7 @@ final class ClassDefinition
         private Methods $methods,
         private bool $isFinal,
         private bool $isAbstract,
-    ) {
-    }
+    ) {}
 
     /**
      * @return class-string
index c8eb789065f149a18d3d75b86b8f26262ef70527..77b6ddfb4ab6fafe800d4087d199b6f9d5482eab 100644 (file)
@@ -20,8 +20,7 @@ final class FunctionDefinition
         private bool $isClosure,
         private Parameters $parameters,
         private Type $returnType
-    ) {
-    }
+    ) {}
 
     public function name(): string
     {
index df7c0258af0f43fec59b52099bbcfdcc93714d31..d6269f5b163b7258977f2dce57ca11ac0c16d8d8 100644 (file)
@@ -24,8 +24,7 @@ final class FunctionsContainer implements IteratorAggregate
         private FunctionDefinitionRepository $functionDefinitionRepository,
         /** @var array<callable> */
         private array $callables
-    ) {
-    }
+    ) {}
 
     public function has(string|int $key): bool
     {
index 8d8910be5c28ad43d4a71353c8c4ed39596a8e17..a04e8928d579a01405647bb014571726d618c3d1 100644 (file)
@@ -16,8 +16,7 @@ final class MethodDefinition
         private bool $isStatic,
         private bool $isPublic,
         private Type $returnType
-    ) {
-    }
+    ) {}
 
     public function name(): string
     {
index c3ee736c174e096b617358060e0ad3906872f09e..f4a7b980226aba41bf93ec1262d7f288a3c6cab7 100644 (file)
@@ -20,16 +20,14 @@ final class NativeAttributes implements Attributes
 {
     private AttributesContainer $delegate;
 
-    /** @var array<ReflectionAttribute<object>> */
-    private array $reflectionAttributes;
+    /** @var array<class-string, array<mixed>> */
+    private array $definition = [];
 
     /**
      * @param ReflectionClass<object>|ReflectionProperty|ReflectionMethod|ReflectionFunction|ReflectionParameter $reflection
      */
     public function __construct(ReflectionClass|ReflectionProperty|ReflectionMethod|ReflectionFunction|ReflectionParameter $reflection)
     {
-        $this->reflectionAttributes = $reflection->getAttributes();
-
         $attributes = array_filter(
             array_map(
                 static function (ReflectionAttribute $attribute) {
@@ -45,10 +43,14 @@ final class NativeAttributes implements Attributes
                         return null;
                     }
                 },
-                $this->reflectionAttributes,
+                $reflection->getAttributes(),
             ),
         );
 
+        foreach ($reflection->getAttributes() as $attribute) {
+            $this->definition[$attribute->getName()] = $attribute->getArguments();
+        }
+
         $this->delegate = new AttributesContainer(...$attributes);
     }
 
@@ -73,10 +75,10 @@ final class NativeAttributes implements Attributes
     }
 
     /**
-     * @return array<ReflectionAttribute<object>>
+     * @return array<class-string, array<mixed>>
      */
-    public function reflectionAttributes(): array
+    public function definition(): array
     {
-        return $this->reflectionAttributes;
+        return $this->definition;
     }
 }
index 16f26293325afeeb627d5bd642973013c9b6fe48..6ea27a6c67546be9dc548791b6cb657ccf7ea4b3 100644 (file)
@@ -17,8 +17,7 @@ final class ParameterDefinition
         private bool $isVariadic,
         private mixed $defaultValue,
         private Attributes $attributes
-    ) {
-    }
+    ) {}
 
     public function name(): string
     {
index c6e5a4b7b66b6112e7905be979dd3520e2ee2e16..ac0aaaee1622ca96d1db873ba9df574e65220a75 100644 (file)
@@ -17,8 +17,7 @@ final class PropertyDefinition
         private mixed $defaultValue,
         private bool $isPublic,
         private Attributes $attributes
-    ) {
-    }
+    ) {}
 
     public function name(): string
     {
index 32d489a2d429da88453efe10d220dfeb5cf9a515..e1307d330d74f6ac0e9047229b94f0c93f0c440b 100644 (file)
@@ -16,8 +16,7 @@ final class CacheClassDefinitionRepository implements ClassDefinitionRepository
         private ClassDefinitionRepository $delegate,
         /** @var CacheInterface<ClassDefinition> */
         private CacheInterface $cache
-    ) {
-    }
+    ) {}
 
     public function for(ClassType $type): ClassDefinition
     {
index 8fd31b2f35815e8c50a11d2f76b658de9d9efc39..65dec14647e03215401de14ab3e2feee739e3397 100644 (file)
@@ -16,8 +16,7 @@ final class CacheFunctionDefinitionRepository implements FunctionDefinitionRepos
         private FunctionDefinitionRepository $delegate,
         /** @var CacheInterface<FunctionDefinition> */
         private CacheInterface $cache
-    ) {
-    }
+    ) {}
 
     public function for(callable $function): FunctionDefinition
     {
index 401e10fc01880bb6485932f09adfb4158b421e59..a872f9dd4aa8c6f5d7ffa5838191c798d102e061 100644 (file)
@@ -7,9 +7,7 @@ namespace CuyZ\Valinor\Definition\Repository\Cache\Compiler;
 use CuyZ\Valinor\Definition\Attributes;
 use CuyZ\Valinor\Definition\AttributesContainer;
 use CuyZ\Valinor\Definition\NativeAttributes;
-use ReflectionAttribute;
 
-use function array_map;
 use function count;
 use function implode;
 use function var_export;
@@ -32,31 +30,25 @@ final class AttributesCompiler
             PHP;
     }
 
-    /**
-     * @param ReflectionAttribute<object> $reflectionAttribute
-     */
-    private function compileNativeAttribute(ReflectionAttribute $reflectionAttribute): string
+    private function compileNativeAttributes(NativeAttributes $attributes): string
     {
-        $name = $reflectionAttribute->getName();
-        $arguments = $reflectionAttribute->getArguments();
-
-        /** @infection-ignore-all */
-        if (count($arguments) > 0) {
-            $arguments = serialize($arguments);
-            $arguments = 'unserialize(' . var_export($arguments, true) . ')';
+        $attributes = $attributes->definition();
 
-            return "new $name(...$arguments)";
+        if (count($attributes) === 0) {
+            return '[]';
         }
 
-        return "new $name()";
-    }
+        $attributesListCode = [];
 
-    private function compileNativeAttributes(NativeAttributes $attributes): string
-    {
-        $attributesListCode = array_map(
-            fn (ReflectionAttribute $attribute) => $this->compileNativeAttribute($attribute),
-            $attributes->reflectionAttributes()
-        );
+        foreach ($attributes as $className => $arguments) {
+            if (count($arguments) === 0) {
+                $argumentsCode = '';
+            } else {
+                $argumentsCode = '...unserialize(' . var_export(serialize($arguments), true) . ')';
+            }
+
+            $attributesListCode[] = "new $className($argumentsCode)";
+        }
 
         return '...[' . implode(",\n", $attributesListCode) . ']';
     }
index d39d7f30a9bd497173aa3078f54f4c868dc9b718..be0a590fdd3e24c39d960cf97c25d4bec85241d9 100644 (file)
@@ -6,16 +6,13 @@ namespace CuyZ\Valinor\Definition\Repository\Cache\Compiler;
 
 use CuyZ\Valinor\Definition\ParameterDefinition;
 
-use function is_scalar;
-
 /** @internal */
 final class ParameterDefinitionCompiler
 {
     public function __construct(
         private TypeCompiler $typeCompiler,
         private AttributesCompiler $attributesCompiler
-    ) {
-    }
+    ) {}
 
     public function compile(ParameterDefinition $parameter): string
     {
@@ -42,8 +39,8 @@ final class ParameterDefinitionCompiler
     {
         $defaultValue = $parameter->defaultValue();
 
-        return is_scalar($defaultValue)
-            ? var_export($parameter->defaultValue(), true)
-            : 'unserialize(' . var_export(serialize($defaultValue), true) . ')';
+        return is_object($defaultValue)
+            ? 'unserialize(' . var_export(serialize($defaultValue), true) . ')'
+            : var_export($defaultValue, true);
     }
 }
index 7e4dd7d3b8fb25d57bd256222bc7010f318bffc7..3a6fb9f08766f06e9d6de4ecb2ea3bbc6e992e03 100644 (file)
@@ -12,8 +12,7 @@ final class PropertyDefinitionCompiler
     public function __construct(
         private TypeCompiler $typeCompiler,
         private AttributesCompiler $attributesCompiler
-    ) {
-    }
+    ) {}
 
     public function compile(PropertyDefinition $property): string
     {
index c4f06c3591a4c8579878394f800f8a5183d57b37..a1a75a6df29586963e219681aaccd453a3c7db1e 100644 (file)
@@ -163,7 +163,7 @@ final class TypeCompiler
                 return "new $class($enumName, $pattern, [$cases])";
             case $type instanceof UnresolvableType:
                 $raw = var_export($type->toString(), true);
-                $message = var_export($type->getMessage(), true);
+                $message = var_export($type->message(), true);
 
                 return "new $class($raw, $message)";
             default:
index 4b4122a25b5378caf2b5a52aba7669ebf2fb7714..cc0d212072902c7583fa556ef9f4752ef4d02561 100644 (file)
@@ -13,9 +13,7 @@ use ReflectionParameter;
 /** @internal */
 final class ReflectionParameterDefinitionBuilder
 {
-    public function __construct(private AttributesRepository $attributesFactory)
-    {
-    }
+    public function __construct(private AttributesRepository $attributesFactory) {}
 
     public function for(ReflectionParameter $reflection, ReflectionTypeResolver $typeResolver): ParameterDefinition
     {
index e1909dc30191fc9236608ab14bce0b61f8c3bfb8..802f242c9ddd217a8c2ca481bc5bb11772b3c542 100644 (file)
@@ -15,9 +15,7 @@ use ReflectionProperty;
 /** @internal */
 final class ReflectionPropertyDefinitionBuilder
 {
-    public function __construct(private AttributesRepository $attributesRepository)
-    {
-    }
+    public function __construct(private AttributesRepository $attributesRepository) {}
 
     public function for(ReflectionProperty $reflection, ReflectionTypeResolver $typeResolver): PropertyDefinition
     {
index 3d3b94064a4b93655ea9c734367c9d92956e09bc..ca6a4e1d1e4eabbde9bfd77465a9bdba6bf06508 100644 (file)
@@ -21,8 +21,7 @@ final class ReflectionTypeResolver
     public function __construct(
         private TypeParser $nativeParser,
         private TypeParser $advancedParser
-    ) {
-    }
+    ) {}
 
     public function resolveType(\ReflectionProperty|\ReflectionParameter|\ReflectionFunctionAbstract $reflection): Type
     {
index dfa2f9c2f26a016e5232c687eae0be84890ccde6..3fc9618f3ccfa6e1c07b05cd4c5a177732f80295 100644 (file)
@@ -165,7 +165,7 @@ final class Container
                 $factory = new ReflectionObjectBuilderFactory();
                 $factory = new ConstructorObjectBuilderFactory($factory, $settings->nativeConstructors, $constructors);
                 $factory = new DateTimeZoneObjectBuilderFactory($factory, $this->get(FunctionDefinitionRepository::class));
-                $factory = new DateTimeObjectBuilderFactory($factory, $this->get(FunctionDefinitionRepository::class));
+                $factory = new DateTimeObjectBuilderFactory($factory, $settings->supportedDateFormats, $this->get(FunctionDefinitionRepository::class));
                 $factory = new CollisionObjectBuilderFactory($factory);
 
                 if (! $settings->allowPermissiveTypes) {
index e18ebde2d327aafecd7f250254ae1182d79a816f..143eac2f3f55667806e3d145499bad9e25f51e03 100644 (file)
@@ -13,6 +13,9 @@ use Throwable;
 /** @internal */
 final class Settings
 {
+    /** @var non-empty-array<non-empty-string> */
+    public const DEFAULT_SUPPORTED_DATETIME_FORMATS = [DATE_ATOM, 'U'];
+
     /** @var array<class-string|interface-string, callable> */
     public array $inferredMapping = [];
 
@@ -28,6 +31,9 @@ final class Settings
     /** @var CacheInterface<mixed> */
     public CacheInterface $cache;
 
+    /** @var non-empty-array<non-empty-string> */
+    public array $supportedDateFormats = self::DEFAULT_SUPPORTED_DATETIME_FORMATS;
+
     public bool $enableFlexibleCasting = false;
 
     public bool $allowSuperfluousKeys = false;
index 85bcb0579d7f0a3a56bb388075e12621ee543894..2e2c53f82ce100c96555d391dddfcd1027c84b9b 100644 (file)
@@ -44,7 +44,7 @@ final class DateTimeFormatConstructor
 
     /**
      * @param class-string<DateTime|DateTimeImmutable> $className
-     * @param non-empty-string|positive-int $value
+     * @param non-empty-string|int $value
      */
     #[DynamicConstructor]
     public function __invoke(string $className, string|int $value): DateTimeInterface
index 6e5cc5f44a3e0b54f61bbde54c614dc7a22a4afb..b032c71a0edd00ced452d1015ec1922577e8f22c 100644 (file)
@@ -48,6 +48,4 @@ use CuyZ\Valinor\MapperBuilder;
  * @api
  */
 #[Attribute(Attribute::TARGET_FUNCTION | Attribute::TARGET_METHOD)]
-final class DynamicConstructor
-{
-}
+final class DynamicConstructor {}
index 6498a1b0910d7b66695213a41685b76e409d3d62..136b66e29d2c470ff1b288992c851fe73a9e2dac 100644 (file)
@@ -16,13 +16,11 @@ final class InvalidConstructorReturnType extends LogicException
         $returnType = $function->returnType();
 
         if ($returnType instanceof UnresolvableType) {
-            $message = $returnType->getMessage();
-            $previous = $returnType;
+            $message = $returnType->message();
         } else {
             $message = "Invalid return type `{$returnType->toString()}` for constructor `{$function->signature()}`, it must be a valid class name.";
-            $previous = null;
         }
 
-        parent::__construct($message, 1659446121, $previous);
+        parent::__construct($message, 1659446121);
     }
 }
index 04144ce0e8292bbea1bcba8efe47e451dffbb97d..82f140072b493d08b4edbfc666c843b961809e12 100644 (file)
@@ -15,8 +15,7 @@ final class CacheObjectBuilderFactory implements ObjectBuilderFactory
         private ObjectBuilderFactory $delegate,
         /** @var CacheInterface<list<ObjectBuilder>> */
         private CacheInterface $cache
-    ) {
-    }
+    ) {}
 
     public function for(ClassDefinition $class): array
     {
index c65ecb664b551cb4d201361421d5c8e55fdae438..702a278b07059e8eecac0903f6bfe16a882d248f 100644 (file)
@@ -15,9 +15,7 @@ use function next;
 /** @internal */
 final class CollisionObjectBuilderFactory implements ObjectBuilderFactory
 {
-    public function __construct(private ObjectBuilderFactory $delegate)
-    {
-    }
+    public function __construct(private ObjectBuilderFactory $delegate) {}
 
     public function for(ClassDefinition $class): array
     {
index 2be3a24880ca2c7cc9d2d5b16361c2dbde350ca2..feff612f5c90bc972daa1300689524e7a32d4fc0 100644 (file)
@@ -38,8 +38,7 @@ final class ConstructorObjectBuilderFactory implements ObjectBuilderFactory
         /** @var array<class-string, null> */
         private array $nativeConstructors,
         private FunctionsContainer $constructors
-    ) {
-    }
+    ) {}
 
     public function for(ClassDefinition $class): array
     {
index 282c4c71493c765ae35ece3bf43b0229aaacda9e..f1c80bc20951e8e8bbd3d0df01733afc94b06227 100644 (file)
@@ -7,6 +7,7 @@ namespace CuyZ\Valinor\Mapper\Object\Factory;
 use CuyZ\Valinor\Definition\ClassDefinition;
 use CuyZ\Valinor\Definition\FunctionObject;
 use CuyZ\Valinor\Definition\Repository\FunctionDefinitionRepository;
+use CuyZ\Valinor\Library\Settings;
 use CuyZ\Valinor\Mapper\Object\DateTimeFormatConstructor;
 use CuyZ\Valinor\Mapper\Object\FunctionObjectBuilder;
 use CuyZ\Valinor\Mapper\Object\NativeConstructorObjectBuilder;
@@ -23,9 +24,10 @@ final class DateTimeObjectBuilderFactory implements ObjectBuilderFactory
 {
     public function __construct(
         private ObjectBuilderFactory $delegate,
+        /** @var non-empty-array<non-empty-string> */
+        private array $supportedDateFormats,
         private FunctionDefinitionRepository $functionDefinitionRepository
-    ) {
-    }
+    ) {}
 
     public function for(ClassDefinition $class): array
     {
@@ -40,27 +42,18 @@ final class DateTimeObjectBuilderFactory implements ObjectBuilderFactory
         // Remove `DateTime` & `DateTimeImmutable` native constructors
         $builders = array_filter($builders, fn (ObjectBuilder $builder) => ! $builder instanceof NativeConstructorObjectBuilder);
 
-        $useDefaultBuilder = true;
-
-        foreach ($builders as $builder) {
-            if (count($builder->describeArguments()) === 1) {
-                $useDefaultBuilder = false;
-                // @infection-ignore-all
-                break;
-            }
-        }
+        $buildersWithOneArgument = array_filter($builders, fn (ObjectBuilder $builder) => count($builder->describeArguments()) === 1);
 
-        if ($useDefaultBuilder) {
-            // @infection-ignore-all / Ignore memoization
-            $builders[] = $this->defaultBuilder($class->type());
+        if (count($buildersWithOneArgument) === 0 || $this->supportedDateFormats !== Settings::DEFAULT_SUPPORTED_DATETIME_FORMATS) {
+            $builders[] = $this->internalDateTimeBuilder($class->type());
         }
 
         return $builders;
     }
 
-    private function defaultBuilder(ClassType $type): FunctionObjectBuilder
+    private function internalDateTimeBuilder(ClassType $type): FunctionObjectBuilder
     {
-        $constructor = new DateTimeFormatConstructor(DATE_ATOM, 'U');
+        $constructor = new DateTimeFormatConstructor(...$this->supportedDateFormats);
         $function = new FunctionObject($this->functionDefinitionRepository->for($constructor), $constructor);
 
         return new FunctionObjectBuilder($function, $type);
index cfc8f0793dc7af1f34a8a765730419ee33c1c8e3..372c20934a556012833ba0def5368a39da57f663 100644 (file)
@@ -12,9 +12,7 @@ use CuyZ\Valinor\Utility\TypeHelper;
 /** @internal */
 final class StrictTypesObjectBuilderFactory implements ObjectBuilderFactory
 {
-    public function __construct(private ObjectBuilderFactory $delegate)
-    {
-    }
+    public function __construct(private ObjectBuilderFactory $delegate) {}
 
     public function for(ClassDefinition $class): array
     {
index 3cca1c2eb6ab92e86c275f61018f3fcfb88bbc5c..25f25fd68e95be28e6ad3dc87d57f5207a7c7056 100644 (file)
@@ -17,8 +17,7 @@ final class MethodObjectBuilder implements ObjectBuilder
         private string $className,
         private string $methodName,
         private Parameters $parameters
-    ) {
-    }
+    ) {}
 
     public function describeArguments(): Arguments
     {
index 30eb40aab82da17a9cb9385fd0f2919073fa3c4d..ec7bedd304950aba9321899965ec617aa5dd5af9 100644 (file)
@@ -13,9 +13,7 @@ final class NativeConstructorObjectBuilder implements ObjectBuilder
 {
     private Arguments $arguments;
 
-    public function __construct(private ClassDefinition $class)
-    {
-    }
+    public function __construct(private ClassDefinition $class) {}
 
     public function describeArguments(): Arguments
     {
index 2bac6410dbe8872d459b3c727d10f55ba2980ae9..54447c757df80a43bf4191097cff8e6be13f304b 100644 (file)
@@ -13,9 +13,7 @@ final class ReflectionObjectBuilder implements ObjectBuilder
 {
     private Arguments $arguments;
 
-    public function __construct(private ClassDefinition $class)
-    {
-    }
+    public function __construct(private ClassDefinition $class) {}
 
     public function describeArguments(): Arguments
     {
index ea6c31d5cebd365ae667b58f6d3c06cd01ad1d7e..6c9934fa9a8cc5966b1fc1fc8bbb42acc879e24f 100644 (file)
@@ -4,16 +4,18 @@ declare(strict_types=1);
 
 namespace CuyZ\Valinor\Mapper\Source\Exception;
 
+use JsonException;
 use RuntimeException;
 
 /** @internal */
 final class InvalidJson extends RuntimeException implements InvalidSource
 {
-    public function __construct(private string $source)
+    public function __construct(private string $source, ?JsonException $previous = null)
     {
         parent::__construct(
             'Invalid JSON source.',
-            1566307185
+            1566307185,
+            $previous
         );
     }
 
index c85b9f66f4adee735dbce9948795e5a5bfb3cdb6..e7465b5c5a282cf63326e50ec218c7f74ea4a74b 100644 (file)
@@ -9,11 +9,14 @@ use CuyZ\Valinor\Mapper\Source\Exception\InvalidSource;
 use CuyZ\Valinor\Mapper\Source\Exception\SourceNotIterable;
 use Iterator;
 use IteratorAggregate;
+use JsonException;
 use Traversable;
 
 use function is_iterable;
 use function json_decode;
 
+use const JSON_THROW_ON_ERROR;
+
 /**
  * @api
  *
@@ -29,10 +32,10 @@ final class JsonSource implements IteratorAggregate
      */
     public function __construct(string $jsonSource)
     {
-        $source = json_decode($jsonSource, true);
-
-        if ($source === null) {
-            throw new InvalidJson($jsonSource);
+        try {
+            $source = json_decode($jsonSource, associative: true, flags: JSON_THROW_ON_ERROR);
+        } catch (JsonException $e) {
+            throw new InvalidJson($jsonSource, $e);
         }
 
         if (! is_iterable($source)) {
index f50bf3229fe8d8e1ae83394d13c99ef30909856b..eb71f0f290355bae7c32b4786468a953049eed00 100644 (file)
@@ -21,8 +21,7 @@ final class Source implements IteratorAggregate
     private function __construct(
         /** @var iterable<mixed> */
         private iterable $delegate
-    ) {
-    }
+    ) {}
 
     /**
      * @param iterable<mixed> $data
index 3f0d1901ea0992393680952f7fb79a53332cb619..bcacaca5a6a07b2b360eb6f4e5828cbd7abf7e5c 100644 (file)
@@ -18,9 +18,7 @@ use function is_array;
 /** @internal */
 final class ArrayNodeBuilder implements NodeBuilder
 {
-    public function __construct(private bool $enableFlexibleCasting)
-    {
-    }
+    public function __construct(private bool $enableFlexibleCasting) {}
 
     public function build(Shell $shell, RootNodeBuilder $rootBuilder): TreeNode
     {
index aefbf89ba188188fb895d4ac6e5f9725c64b8096..a00634877dc3c6b5b0860e1722a0417aba2946d1 100644 (file)
@@ -13,8 +13,7 @@ final class CasterNodeBuilder implements NodeBuilder
     public function __construct(
         /** @var array<class-string, NodeBuilder> */
         private array $builders
-    ) {
-    }
+    ) {}
 
     public function build(Shell $shell, RootNodeBuilder $rootBuilder): TreeNode
     {
index 1efe39cfcb86460d35d7a603d517fb331bfa8ca2..db2de428b2dd2689b8ccb0807e42f791378ef4b7 100644 (file)
@@ -9,9 +9,7 @@ use CuyZ\Valinor\Mapper\Tree\Shell;
 /** @internal */
 final class CasterProxyNodeBuilder implements NodeBuilder
 {
-    public function __construct(private NodeBuilder $delegate)
-    {
-    }
+    public function __construct(private NodeBuilder $delegate) {}
 
     public function build(Shell $shell, RootNodeBuilder $rootBuilder): TreeNode
     {
index edc1cae8e96369f92049120a31b243622f556c91..eb6a03c44f456e55ee084aa263af371c07022975 100644 (file)
@@ -27,8 +27,7 @@ final class InterfaceNodeBuilder implements NodeBuilder
         private ObjectBuilderFactory $objectBuilderFactory,
         private ObjectNodeBuilder $objectNodeBuilder,
         private bool $enableFlexibleCasting
-    ) {
-    }
+    ) {}
 
     public function build(Shell $shell, RootNodeBuilder $rootBuilder): TreeNode
     {
index c615c0c62fcfdcebe7ec5a860bb2da04ccd35307..a3580ce0a27703a853ad86d9c6a823ac8e810e34 100644 (file)
@@ -13,9 +13,7 @@ use function iterator_to_array;
 /** @internal */
 final class IterableNodeBuilder implements NodeBuilder
 {
-    public function __construct(private NodeBuilder $delegate)
-    {
-    }
+    public function __construct(private NodeBuilder $delegate) {}
 
     public function build(Shell $shell, RootNodeBuilder $rootBuilder): TreeNode
     {
index 531b1beee4b368cbb152209f33379f797ee3e309..8033c4d8c2449922b6c60ab9d893d9533b8884d2 100644 (file)
@@ -17,9 +17,7 @@ use function is_array;
 /** @internal */
 final class ListNodeBuilder implements NodeBuilder
 {
-    public function __construct(private bool $enableFlexibleCasting)
-    {
-    }
+    public function __construct(private bool $enableFlexibleCasting) {}
 
     public function build(Shell $shell, RootNodeBuilder $rootBuilder): TreeNode
     {
index eae3fac09e88902fbe4daa61b6edfff316c9c843..f129b3d31384138f080b41d8484f35c73b50f768 100644 (file)
@@ -20,8 +20,7 @@ final class NativeClassNodeBuilder implements NodeBuilder
         private ObjectBuilderFactory $objectBuilderFactory,
         private ObjectNodeBuilder $objectNodeBuilder,
         private bool $enableFlexibleCasting,
-    ) {
-    }
+    ) {}
 
     public function build(Shell $shell, RootNodeBuilder $rootBuilder): TreeNode
     {
index 060d854234dbd2c3320519896f9194b7cca9323e..e0965e5b4996517fe9bbee502c283fd8348087fc 100644 (file)
@@ -14,9 +14,7 @@ use function count;
 /** @internal */
 final class ObjectNodeBuilder
 {
-    public function __construct(private bool $allowSuperfluousKeys)
-    {
-    }
+    public function __construct(private bool $allowSuperfluousKeys) {}
 
     public function build(ObjectBuilder $builder, Shell $shell, RootNodeBuilder $rootBuilder): TreeNode
     {
index ed4da9c96660584deb867ac22e9009b475662f27..0afca986e6dc00e15ed97f10b6ee7c37a85a8aaa 100644 (file)
@@ -9,9 +9,7 @@ use CuyZ\Valinor\Mapper\Tree\Shell;
 /** @internal */
 final class RootNodeBuilder
 {
-    public function __construct(private NodeBuilder $root)
-    {
-    }
+    public function __construct(private NodeBuilder $root) {}
 
     public function build(Shell $shell): TreeNode
     {
index 34528652bf0ede5402b256e2f8a54381cb931fdb..9a0d8a763f74d50685124067b2a37bea878f00d7 100644 (file)
@@ -12,9 +12,7 @@ use function assert;
 /** @internal */
 final class ScalarNodeBuilder implements NodeBuilder
 {
-    public function __construct(private bool $enableFlexibleCasting)
-    {
-    }
+    public function __construct(private bool $enableFlexibleCasting) {}
 
     public function build(Shell $shell, RootNodeBuilder $rootBuilder): TreeNode
     {
index 7fce746167766019176be821ddff9ebe2fab4014..492d74a402434aa33ea7c4d6c7a75a9660ca0c81 100644 (file)
@@ -17,9 +17,7 @@ use function is_array;
 /** @internal */
 final class ShapedArrayNodeBuilder implements NodeBuilder
 {
-    public function __construct(private bool $allowSuperfluousKeys)
-    {
-    }
+    public function __construct(private bool $allowSuperfluousKeys) {}
 
     public function build(Shell $shell, RootNodeBuilder $rootBuilder): TreeNode
     {
index 84d9cfd6683516b75d8fbb8f6f872e94c3c92aef..ecff6142c43e5dd511622d55a16469e87a00282f 100644 (file)
@@ -15,8 +15,7 @@ final class StrictNodeBuilder implements NodeBuilder
         private NodeBuilder $delegate,
         private bool $allowPermissiveTypes,
         private bool $enableFlexibleCasting
-    ) {
-    }
+    ) {}
 
     public function build(Shell $shell, RootNodeBuilder $rootBuilder): TreeNode
     {
index bf6babdaae1818a55d15c2e8cb41ed6863af4464..dd35ef87d329ecd1d8f642ccce7137cea41c059d 100644 (file)
@@ -27,8 +27,7 @@ final class UnionNodeBuilder implements NodeBuilder
         private ObjectBuilderFactory $objectBuilderFactory,
         private ObjectNodeBuilder $objectNodeBuilder,
         private bool $enableFlexibleCasting
-    ) {
-    }
+    ) {}
 
     public function build(Shell $shell, RootNodeBuilder $rootBuilder): TreeNode
     {
index e83333003961f9f023bc0deb2fa021cee182b312..66a6630dac91704fe0849f26a121754c6516991a 100644 (file)
@@ -13,8 +13,7 @@ final class ValueAlteringNodeBuilder implements NodeBuilder
     public function __construct(
         private NodeBuilder $delegate,
         private FunctionsContainer $functions
-    ) {
-    }
+    ) {}
 
     public function build(Shell $shell, RootNodeBuilder $rootBuilder): TreeNode
     {
index ef2f6f9a588fc4b92dc77400301d6ba8337c6af6..1c53b35e5b4462e555af32b81a097edf1e36657f 100644 (file)
@@ -7,6 +7,4 @@ namespace CuyZ\Valinor\Mapper\Tree\Message;
 use Throwable;
 
 /** @api */
-interface ErrorMessage extends Message, Throwable
-{
-}
+interface ErrorMessage extends Message, Throwable {}
index 00f05b70f760ddfdc1fd54b1ca8dd37644891d27..3dc93a3c4096a74ab5a726fc6965054676b96588 100644 (file)
@@ -9,9 +9,7 @@ use CuyZ\Valinor\Mapper\Tree\Message\NodeMessage;
 /** @api */
 final class LocaleMessageFormatter implements MessageFormatter
 {
-    public function __construct(private string $locale)
-    {
-    }
+    public function __construct(private string $locale) {}
 
     public function format(NodeMessage $message): NodeMessage
     {
index 08576e67edf19d79ffb71b0daa73d6f194e411d3..9ca30d56ddc8ca694536650b08629a33ed6d8f3e 100644 (file)
@@ -67,8 +67,7 @@ final class MessageMapFormatter implements MessageFormatter
     public function __construct(
         /** @var array<string|callable(NodeMessage): string> */
         private array $map
-    ) {
-    }
+    ) {}
 
     public function format(NodeMessage $message): NodeMessage
     {
index f9b4f446795be46b42283a3ba4c83e4ac472f59b..2230e1215146cdce5d0bd3d8add9e747b5d2b862 100644 (file)
@@ -31,9 +31,7 @@ final class MessageBuilder
     /** @var array<string, string> */
     private array $parameters = [];
 
-    private function __construct(private string $body)
-    {
-    }
+    private function __construct(private string $body) {}
 
     /**
      * @return self<Message>
@@ -135,9 +133,11 @@ final class MessageBuilder
             /**
              * @param array<string, string> $parameters
              */
-            public function __construct(private string $body, private string $code, private array $parameters)
-            {
-            }
+            public function __construct(
+                private string $body,
+                private string $code,
+                private array  $parameters
+            ) {}
 
             public function body(): string
             {
index 6103840d86d3ae635fb4e6b0b7f700423989801e..a9b4194c7e84c647a9f503cf33560353eff88b73 100644 (file)
@@ -17,8 +17,7 @@ final class TypeTreeMapper implements TreeMapper
     public function __construct(
         private TypeParser $typeParser,
         private RootNodeBuilder $nodeBuilder
-    ) {
-    }
+    ) {}
 
     /** @pure */
     public function map(string $signature, mixed $source): mixed
index db4719f4a9cd465a835d310d8294176ae8f043df..30c191fac5bc9264c3df963dfba1b0dfc6073dda 100644 (file)
@@ -7,12 +7,12 @@ namespace CuyZ\Valinor;
 use CuyZ\Valinor\Library\Container;
 use CuyZ\Valinor\Library\Settings;
 use CuyZ\Valinor\Mapper\ArgumentsMapper;
-use CuyZ\Valinor\Mapper\Object\DateTimeFormatConstructor;
 use CuyZ\Valinor\Mapper\Tree\Message\ErrorMessage;
 use CuyZ\Valinor\Mapper\TreeMapper;
 use Psr\SimpleCache\CacheInterface;
 use Throwable;
 
+use function array_unique;
 use function is_callable;
 
 /** @api */
@@ -235,7 +235,23 @@ final class MapperBuilder
      */
     public function supportDateFormats(string $format, string ...$formats): self
     {
-        return $this->registerConstructor(new DateTimeFormatConstructor($format, ...$formats));
+        $clone = clone $this;
+        $clone->settings->supportedDateFormats = array_unique([$format, ...$formats]);
+
+        return $clone;
+    }
+
+    /**
+     * Returns the date formats supported during mapping.
+     *
+     * By default, any valid timestamp or ATOM-formatted value are accepted.
+     * Custom formats can be set using method `supportDateFormats()`.
+     *
+     * @return non-empty-array<non-empty-string>
+     */
+    public function supportedDateFormats(): array
+    {
+        return $this->settings->supportedDateFormats;
     }
 
     /**
index 2ab01829f0fbd728afaaf0ce74d5b6bc02078dba..62d6cda842bc3c24e61d051cf7d4a2487034e7d4 100644 (file)
@@ -5,6 +5,4 @@ declare(strict_types=1);
 namespace CuyZ\Valinor\Type;
 
 /** @internal */
-interface ClassType extends ObjectType
-{
-}
+interface ClassType extends ObjectType {}
index 7cc049779bf78e6ce7a7636021f5e218dbe1e6af..1d1eefa73e09a787d5f929200856996d2c243b5b 100644 (file)
@@ -12,9 +12,7 @@ final class CachedParser implements TypeParser
     /** @var array<string, Type> */
     private array $types = [];
 
-    public function __construct(private TypeParser $delegate)
-    {
-    }
+    public function __construct(private TypeParser $delegate) {}
 
     public function parse(string $raw): Type
     {
index e691e117ae061d06076e88f117a1be53b1dc4736..ed730a57d869617fb7ad9ca8afcb930d7b59b648 100644 (file)
@@ -7,6 +7,4 @@ namespace CuyZ\Valinor\Type\Parser\Exception;
 use Throwable;
 
 /** @internal */
-interface InvalidType extends Throwable
-{
-}
+interface InvalidType extends Throwable {}
index 1be411d26f37a5390ec70b23fb7be9094533a08c..5e4594e466c4b59524b5dd84f85b1f4a48f5d432 100644 (file)
@@ -7,6 +7,4 @@ namespace CuyZ\Valinor\Type\Parser\Exception\Template;
 use Throwable;
 
 /** @internal */
-interface InvalidTemplate extends Throwable
-{
-}
+interface InvalidTemplate extends Throwable {}
index 56718120e746a69b419947a90d9ce24f51d9dc0b..08d0eea3ae3878394536f34ebb153a16b5be29c8 100644 (file)
@@ -17,9 +17,7 @@ final class LexingTypeParserFactory implements TypeParserFactory
 {
     private TypeParser $nativeParser;
 
-    public function __construct(private TemplateParser $templateParser)
-    {
-    }
+    public function __construct(private TemplateParser $templateParser) {}
 
     public function get(TypeParserSpecification ...$specifications): TypeParser
     {
index 09cbe4eee77cc23cff553ec55074d745a69fed6d..59e706016a23bfe2f4a12c7757343271a0b28513 100644 (file)
@@ -16,8 +16,7 @@ final class AliasSpecification implements TypeParserSpecification
     public function __construct(
         /** @var ReflectionClass<object>|ReflectionFunction */
         private Reflector $reflection
-    ) {
-    }
+    ) {}
 
     public function transform(TypeLexer $lexer): TypeLexer
     {
index fa508ad1900e6de6905bf3c5c9109bea7fe0be6a..dcb3c628e1f80592e3e27e1650173d8104f55e5f 100644 (file)
@@ -13,8 +13,7 @@ final class ClassContextSpecification implements TypeParserSpecification
     public function __construct(
         /** @var class-string */
         private string $className
-    ) {
-    }
+    ) {}
 
     public function transform(TypeLexer $lexer): TypeLexer
     {
index 58181997172d7e3df4b5ace3d6cd888b3549b9dd..140603610eabc893a3093ab2559ca8f90c219b96 100644 (file)
@@ -14,8 +14,7 @@ final class TypeAliasAssignerSpecification implements TypeParserSpecification
     public function __construct(
         /** @var array<string, Type> */
         private array $aliases
-    ) {
-    }
+    ) {}
 
     public function transform(TypeLexer $lexer): TypeLexer
     {
index 40bd49ba187dd417fb6a7c262bdba6fa8e8ca0ef..0ac28d38eb0d7a621ee0659d85af9fa25e906452 100644 (file)
@@ -17,8 +17,7 @@ final class AdvancedClassLexer implements TypeLexer
         private TypeLexer $delegate,
         private TypeParserFactory $typeParserFactory,
         private TemplateParser $templateParser
-    ) {
-    }
+    ) {}
 
     public function tokenize(string $symbol): Token
     {
index d53c9b183e47230b8c70086cc691b002009b152f..96c2ac469d440d5367816d24fd7a82a980b211ab 100644 (file)
@@ -20,8 +20,7 @@ final class AliasLexer implements TypeLexer
         private TypeLexer $delegate,
         /** @var ReflectionClass<object>|ReflectionFunction */
         private Reflector $reflection
-    ) {
-    }
+    ) {}
 
     public function tokenize(string $symbol): Token
     {
index 70c42c75a412a27c3c02b5d8c089ea00dc7b772b..e5bafa96a6e0129a71c878c922523ad878632abe 100644 (file)
@@ -46,8 +46,7 @@ final class AdvancedClassNameToken implements TraversingToken
         private ClassNameToken $delegate,
         private TypeParserFactory $typeParserFactory,
         private TemplateParser $templateParser
-    ) {
-    }
+    ) {}
 
     public function traverse(TokenStream $stream): Type
     {
index 24ea96183b78b99aeebc05cbcff585466ff06aeb..6d37b433e376fc96395264de6c93e3bafb258bb4 100644 (file)
@@ -36,8 +36,7 @@ final class ArrayToken implements TraversingToken
         /** @var class-string<ArrayType|NonEmptyArrayType> */
         private string $arrayType,
         private string $symbol
-    ) {
-    }
+    ) {}
 
     public static function array(): self
     {
index e318ce83415e176c6e6862e82813a53171477356..b5d34d8ecdbaa850f2a2df60955d28b1dd49bd10 100644 (file)
@@ -19,8 +19,7 @@ final class CaseFinder
     public function __construct(
         /** @var array<string, CaseType> */
         private array $cases
-    ) {
-    }
+    ) {}
 
     /**
      * @param list<string> $tokens
index 40dcad9625d5cb415e4d1113e24a9d38bdd7f411..513ba07bfbd63f6d0428b9aa4ff55da0ad6d52aa 100644 (file)
@@ -18,8 +18,7 @@ final class EnumNameToken implements TraversingToken
     public function __construct(
         /** @var class-string<UnitEnum> */
         private string $enumName
-    ) {
-    }
+    ) {}
 
     public function traverse(TokenStream $stream): Type
     {
index d1851deb76c62a204849cac27f0d7fad33d99cb1..23e47843473f393c9933065ded65e094eba47d6c 100644 (file)
@@ -11,9 +11,7 @@ use CuyZ\Valinor\Type\Types\FloatValueType;
 /** @internal */
 final class FloatValueToken implements TraversingToken
 {
-    public function __construct(private float $value)
-    {
-    }
+    public function __construct(private float $value) {}
 
     public function traverse(TokenStream $stream): Type
     {
index 36c153e88030293b7276bfca9fe7673641295aeb..7e2373d04a1db3bea8e9a85376e8a63ca96d7837 100644 (file)
@@ -11,9 +11,7 @@ use CuyZ\Valinor\Type\Types\IntegerValueType;
 /** @internal */
 final class IntegerValueToken implements TraversingToken
 {
-    public function __construct(private int $value)
-    {
-    }
+    public function __construct(private int $value) {}
 
     public function traverse(TokenStream $stream): Type
     {
index c2fd225e9ef39d85bdf41b1bb21c5ccd982ad08e..87254b609a4d4cbcf890105c10f77f07b7f802d1 100644 (file)
@@ -21,8 +21,7 @@ final class ListToken implements TraversingToken
         /** @var class-string<ListType|NonEmptyListType> */
         private string $listType,
         private string $symbol
-    ) {
-    }
+    ) {}
 
     public static function list(): self
     {
index e354526abe5a15f79eb1de2851d4572fa00fc1d6..f476bc46f2beeb4bbeadf2be832e441ab7ef8564 100644 (file)
@@ -30,8 +30,7 @@ final class NativeToken implements TraversingToken
     private function __construct(
         private Type $type,
         private string $symbol
-    ) {
-    }
+    ) {}
 
     public static function accepts(string $symbol): bool
     {
index 055336633de67aac70e7f4b5d638492f11f68e1b..875ddd4ec9c41c73bdaeb2cc730f81210ca2ccdd 100644 (file)
@@ -12,9 +12,7 @@ use CuyZ\Valinor\Type\Types\StringValueType;
 /** @internal */
 final class QuoteToken implements TraversingToken
 {
-    public function __construct(private string $quoteType)
-    {
-    }
+    public function __construct(private string $quoteType) {}
 
     public function traverse(TokenStream $stream): Type
     {
index 4ab0852f10ba5635fb74828a35269a9a696a57b5..cccffa0f05b0eb76762b070b5edeb921aeb1a185 100644 (file)
@@ -13,8 +13,7 @@ final class TypeToken implements TraversingToken
     public function __construct(
         private Type $type,
         private string $symbol
-    ) {
-    }
+    ) {}
 
     public function traverse(TokenStream $stream): Type
     {
index 09efdd7f574917bdac8d05af6999d59398a27105..010496294bcace57c23976846de3c7fe6efb6942 100644 (file)
@@ -11,9 +11,7 @@ use CuyZ\Valinor\Type\Type;
 /** @internal */
 final class UnknownSymbolToken implements TraversingToken
 {
-    public function __construct(private string $symbol)
-    {
-    }
+    public function __construct(private string $symbol) {}
 
     public function traverse(TokenStream $stream): Type
     {
index 89edf8e6db7f082b94d3d5faf22121c1f186b062..698a929299105d5c3a58a40c2bb0c09d48558708 100644 (file)
@@ -15,8 +15,7 @@ final class TypeAliasLexer implements TypeLexer
         private TypeLexer $delegate,
         /** @var array<string, Type> */
         private array $aliases
-    ) {
-    }
+    ) {}
 
     public function tokenize(string $symbol): Token
     {
index ab4c5854d5e242dc1e4484dde1f9e0f7f37c12f7..a1a8379c27668225a2d6d3e45b573a5f809c26d6 100644 (file)
@@ -16,9 +16,7 @@ use function str_contains;
 /** @internal */
 final class LexingParser implements TypeParser
 {
-    public function __construct(private TypeLexer $lexer)
-    {
-    }
+    public function __construct(private TypeLexer $lexer) {}
 
     public function parse(string $raw): Type
     {
index 119b2ddf109f6b98c9861576632c30362bae295f..8e1dea9aff468306fac7d87c77a5526bd349d3a3 100644 (file)
@@ -22,9 +22,7 @@ final class BooleanValueType implements BooleanType, FixedType
     /**
      * @codeCoverageIgnore
      */
-    private function __construct(private bool $value)
-    {
-    }
+    private function __construct(private bool $value) {}
 
     public static function true(): self
     {
index 1147faf1d4183bc82e2ab271f27f6b3053a758a2..a8a456f7dba7ab47145fa94af4552eed3b2a7baf 100644 (file)
@@ -15,9 +15,7 @@ use function assert;
 /** @internal */
 final class FloatValueType implements FloatType, FixedType
 {
-    public function __construct(private float $value)
-    {
-    }
+    public function __construct(private float $value) {}
 
     public function accepts(mixed $value): bool
     {
index dbb55686e2f151f5cefdba75f3acc78ec2de4b39..f6cd7033b326f5122768b8e0833ddb3ad65744a7 100644 (file)
@@ -17,9 +17,7 @@ use function is_bool;
 /** @internal */
 final class IntegerValueType implements IntegerType, FixedType
 {
-    public function __construct(private int $value)
-    {
-    }
+    public function __construct(private int $value) {}
 
     public function accepts(mixed $value): bool
     {
index b7d9374233f8cb4500a03e13fbbaad74aa3e12fc..4db2359d443d7d3ab84bc13abc71e3ac195e404f 100644 (file)
@@ -20,8 +20,7 @@ final class InterfaceType implements ObjectType, GenericType
         private string $interfaceName,
         /** @var array<string, Type> */
         private array $generics = []
-    ) {
-    }
+    ) {}
 
     public function className(): string
     {
index bc6dc0866350cb83d9c086973658b2d9a2358397..fb76a8d7a31287d18a33152fa8547dd2c570e4aa 100644 (file)
@@ -13,8 +13,7 @@ final class ShapedArrayElement
         private StringValueType|IntegerValueType $key,
         private Type $type,
         private bool $optional = false
-    ) {
-    }
+    ) {}
 
     public function key(): StringValueType|IntegerValueType
     {
index 19d0a66cf38b790545b5c1187ed33dbe27f46812..a3babe059e0c47e132015cedc225d142e2c6e94d 100644 (file)
@@ -20,9 +20,7 @@ final class StringValueType implements StringType, FixedType
 {
     private string $quoteChar;
 
-    public function __construct(private string $value)
-    {
-    }
+    public function __construct(private string $value) {}
 
     public static function singleQuote(string $value): self
     {
index 3d74be3f1a916a6d7c672c898d15f1c9b1810adb..a212e12478c010ad509365d8c1bee382ac0d2cc3 100644 (file)
@@ -9,26 +9,20 @@ use CuyZ\Valinor\Type\Parser\Exception\InvalidType;
 use CuyZ\Valinor\Type\Type;
 use CuyZ\Valinor\Utility\ValueDumper;
 use LogicException;
-use Throwable;
 
 /** @internal */
-final class UnresolvableType extends LogicException implements Type
+final class UnresolvableType implements Type
 {
-    private string $rawType;
-
-    public function __construct(string $rawType, string $message, ?Throwable $previous = null)
-    {
-        $this->rawType = $rawType;
-
-        parent::__construct($message, 1679578492, $previous);
-    }
+    public function __construct(
+        private string $rawType,
+        private string $message,
+    ) {}
 
     public static function forProperty(string $raw, string $signature, InvalidType $exception): self
     {
         return new self(
             $raw,
-            "The type `$raw` for property `$signature` could not be resolved: {$exception->getMessage()}",
-            $exception
+            "The type `$raw` for property `$signature` could not be resolved: {$exception->getMessage()}"
         );
     }
 
@@ -36,8 +30,7 @@ final class UnresolvableType extends LogicException implements Type
     {
         return new self(
             $raw,
-            "The type `$raw` for parameter `$signature` could not be resolved: {$exception->getMessage()}",
-            $exception
+            "The type `$raw` for parameter `$signature` could not be resolved: {$exception->getMessage()}"
         );
     }
 
@@ -45,8 +38,7 @@ final class UnresolvableType extends LogicException implements Type
     {
         return new self(
             $raw,
-            "The type `$raw` for return type of method `$signature` could not be resolved: {$exception->getMessage()}",
-            $exception
+            "The type `$raw` for return type of method `$signature` could not be resolved: {$exception->getMessage()}"
         );
     }
 
@@ -74,19 +66,23 @@ final class UnresolvableType extends LogicException implements Type
     {
         return new self(
             $raw,
-            "The type `$raw` for local alias `$name` of the class `{$type->className()}` could not be resolved: {$exception->getMessage()}",
-            $exception
+            "The type `$raw` for local alias `$name` of the class `{$type->className()}` could not be resolved: {$exception->getMessage()}"
         );
     }
 
+    public function message(): string
+    {
+        return $this->message;
+    }
+
     public function accepts(mixed $value): bool
     {
-        throw $this;
+        throw new LogicException();
     }
 
     public function matches(Type $other): bool
     {
-        throw $this;
+        throw new LogicException();
     }
 
     public function toString(): string
diff --git a/wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Utility/String/StringCutter.php b/wcfsetup/install/files/lib/system/api/cuyz/valinor/src/Utility/String/StringCutter.php
new file mode 100644 (file)
index 0000000..00fe67f
--- /dev/null
@@ -0,0 +1,51 @@
+<?php
+
+declare(strict_types=1);
+
+namespace CuyZ\Valinor\Utility\String;
+
+use function substr;
+
+/** @internal */
+final class StringCutter
+{
+    public static function cut(string $s, int $length): string
+    {
+        if (function_exists('mb_strcut')) {
+            return mb_strcut($s, 0, $length);
+        }
+
+        return self::cutPolyfill($s, $length);
+    }
+
+    public static function cutPolyfill(string $s, int $length): string
+    {
+        $s = substr($s, 0, $length);
+        $cur = strlen($s) - 1;
+        // U+0000 - U+007F
+        if ((ord($s[$cur]) & 0b1000_0000) === 0) {
+            return $s;
+        }
+        $cnt = 0;
+        while ((ord($s[$cur]) & 0b1100_0000) === 0b1000_0000) {
+            ++$cnt;
+            if ($cur === 0) {
+                // @infection-ignore-all // Causes infinite loop
+                break;
+            }
+            --$cur;
+        }
+
+        assert($cur >= 0);
+
+        return match (true) {
+            default => substr($s, 0, $cur),
+            // U+0080 - U+07FF
+            $cnt === 1 && (ord($s[$cur]) & 0b1110_0000) === 0b1100_0000,
+            // U+0800 - U+FFFF
+            $cnt === 2 && (ord($s[$cur]) & 0b1111_0000) === 0b1110_0000,
+            // U+10000 - U+10FFFF
+            $cnt === 3 && (ord($s[$cur]) & 0b1111_1000) === 0b1111_0000 => $s
+        };
+    }
+}
index 5723bc6a4fd1c8696a7ca699ebed53891d96dc5c..4fa5d286d033fce819c1f1758a36f268cf0798e4 100644 (file)
@@ -38,7 +38,7 @@ final class StringFormatter
     private static function formatWithIntl(string $locale, string $body, array $parameters): string
     {
         return MessageFormatter::formatMessage($locale, $body, $parameters)
-            ?: throw new StringFormatterError($body);
+            ?: throw new StringFormatterError($body, intl_get_error_message());
     }
 
     /**
index 418d9860a2aea7696de477495cc451fd1e7f30d8..f99729377b75c8bdb78e97cc0168d6ce151d9099 100644 (file)
@@ -9,8 +9,11 @@ use RuntimeException;
 /** @internal */
 final class StringFormatterError extends RuntimeException
 {
-    public function __construct(string $body)
+    public function __construct(string $body, string $message = '')
     {
-        parent::__construct("Message formatter error using `$body`.", 1652901203);
+        if ($message !== '') {
+            $message = ": $message";
+        }
+        parent::__construct("Message formatter error using `$body`$message.", 1652901203);
     }
 }
index 21e95e4d01d36a3c59db2e0fd9b472a1436eb8fc..8e61c26e81beb333fd1916dd9c379172bf7e8fd4 100644 (file)
@@ -5,6 +5,7 @@ declare(strict_types=1);
 namespace CuyZ\Valinor\Utility;
 
 use BackedEnum;
+use CuyZ\Valinor\Utility\String\StringCutter;
 use DateTimeInterface;
 use UnitEnum;
 
@@ -112,11 +113,11 @@ final class ValueDumper
             return $string;
         }
 
-        $string = substr($string, 0, self::MAX_STRING_LENGTH + 1);
+        $string = StringCutter::cut($string, self::MAX_STRING_LENGTH + 1);
 
         for ($i = strlen($string) - 1; $i > 10; $i--) {
             if ($string[$i] === ' ') {
-                return substr($string, 0, $i) . '…';
+                return StringCutter::cut($string, $i) . '…';
             }
         }
 
index 7b6df4b1cb65dd1686ed3b13fb5f0b3d9ab8b46c..17ab2ce44d0e0ce41dffa5be665caa3ed416d72a 100644 (file)
@@ -1,5 +1,17 @@
 # Change Log
 
+## [3.3.3] - 2024-08-10
+
+### Added
+- N/A
+
+### Changed
+- N/A
+
+### Fixed
+- Added fixes for making sure `?` is not passed for both DOM and DOW (#148, thank you https://github.com/LeoVie)
+- Fixed bug in Next Execution Time by sorting minutes properly (#160, thank you https://github.com/imyip)
+
 ## [3.3.2] - 2022-09-19
 
 ### Added
index e853ad4555f2ae0d5edc75ca400e2ee2832d02da..494652c84ef20ce2f87dd1501acc80e9f451d0e3 100644 (file)
@@ -84,4 +84,4 @@ Projects that Use cron-expression
 =================================
 * Part of the [Laravel Framework](https://github.com/laravel/framework/)
 * Available as a [Symfony Bundle - setono/cron-expression-bundle](https://github.com/Setono/CronExpressionBundle)
-* Framework agnostic, PHP-based job scheduler - [Crunz](https://github.com/lavary/crunz)
+* Framework agnostic, PHP-based job scheduler - [Crunz](https://github.com/crunzphp/crunz)
diff --git a/wcfsetup/install/files/lib/system/api/dragonmantank/cron-expression/phpstan.neon b/wcfsetup/install/files/lib/system/api/dragonmantank/cron-expression/phpstan.neon
deleted file mode 100644 (file)
index bea9cb0..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-parameters:
-    checkMissingIterableValueType: false
-
-    ignoreErrors:
-        - '#Call to an undefined method DateTimeInterface::add\(\)#'
-        - '#Call to an undefined method DateTimeInterface::modify\(\)#'
-        - '#Call to an undefined method DateTimeInterface::setDate\(\)#'
-        - '#Call to an undefined method DateTimeInterface::setTime\(\)#'
-        - '#Call to an undefined method DateTimeInterface::setTimezone\(\)#'
-        - '#Call to an undefined method DateTimeInterface::sub\(\)#'
-
-    level: max
-
-    paths:
-        - src/
index d5337cc57f6c2c14680e2601df6a366742714862..216ce432f1635f87316cab71241a13b8c221510b 100644 (file)
@@ -177,6 +177,7 @@ class CronExpression
      *
      * @param string $expression CRON expression (e.g. '8 * * * *')
      * @param null|FieldFactoryInterface $fieldFactory Factory to create cron fields
+     * @throws InvalidArgumentException
      */
     public function __construct(string $expression, FieldFactoryInterface $fieldFactory = null)
     {
@@ -201,13 +202,22 @@ class CronExpression
         $split = preg_split('/\s/', $value, -1, PREG_SPLIT_NO_EMPTY);
         Assert::isArray($split);
 
-        $this->cronParts = $split;
-        if (\count($this->cronParts) < 5) {
+        $notEnoughParts = \count($split) < 5;
+
+        $questionMarkInInvalidPart = array_key_exists(0, $split) && $split[0] === '?'
+            || array_key_exists(1, $split) && $split[1] === '?'
+            || array_key_exists(3, $split) && $split[3] === '?';
+
+        $tooManyQuestionMarks = array_key_exists(2, $split) && $split[2] === '?'
+            && array_key_exists(4, $split) && $split[4] === '?';
+
+        if ($notEnoughParts || $questionMarkInInvalidPart || $tooManyQuestionMarks) {
             throw new InvalidArgumentException(
                 $value . ' is not a valid CRON expression'
             );
         }
 
+        $this->cronParts = $split;
         foreach ($this->cronParts as $position => $part) {
             $this->setPart($position, $part);
         }
index eda91098e8ac6bf2a4db0f1e5a0bd29104cbb824..f077e6ec51d2e8604fda280a99f2b14e36528db2 100644 (file)
@@ -49,6 +49,7 @@ class MinutesField extends AbstractField
         $current_minute = (int) $date->format('i');
 
         $parts = false !== strpos($parts, ',') ? explode(',', $parts) : [$parts];
+        sort($parts);
         $minutes = [];
         foreach ($parts as $part) {
             $minutes = array_merge($minutes, $this->getRangeForExpression($part, 59));