From db9f05f6f6dd03c10b235180b578dd8b3cae5a22 Mon Sep 17 00:00:00 2001 From: Bruno21 Date: Fri, 13 Dec 2024 06:44:07 +0100 Subject: [PATCH] installation de motranslator via Composer --- composer.json | 5 + composer.lock | 692 +++++++++ translator.php | 39 + translator_gettext.php | 19 + vendor/autoload.php | 25 + vendor/composer/ClassLoader.php | 579 ++++++++ vendor/composer/InstalledVersions.php | 362 +++++ vendor/composer/LICENSE | 21 + vendor/composer/autoload_classmap.php | 11 + vendor/composer/autoload_files.php | 10 + vendor/composer/autoload_namespaces.php | 9 + vendor/composer/autoload_psr4.php | 18 + vendor/composer/autoload_real.php | 50 + vendor/composer/autoload_static.php | 84 ++ vendor/composer/installed.json | 709 +++++++++ vendor/composer/installed.php | 131 ++ vendor/composer/platform_check.php | 26 + vendor/phpmyadmin/motranslator/CHANGELOG.md | 104 ++ .../motranslator/CODE_OF_CONDUCT.md | 76 + .../phpmyadmin/motranslator/CONTRIBUTING.md | 42 + vendor/phpmyadmin/motranslator/LICENSE | 339 +++++ vendor/phpmyadmin/motranslator/PERFORMANCE.md | 29 + vendor/phpmyadmin/motranslator/README.md | 242 ++++ .../motranslator/benchmark-apcu.php | 29 + vendor/phpmyadmin/motranslator/composer.json | 56 + .../phpmyadmin/motranslator/phpunit.xml.dist | 31 + .../motranslator/src/Cache/ApcuCache.php | 136 ++ .../src/Cache/ApcuCacheFactory.php | 29 + .../src/Cache/CacheFactoryInterface.php | 12 + .../motranslator/src/Cache/CacheInterface.php | 33 + .../src/Cache/GetAllInterface.php | 13 + .../motranslator/src/Cache/InMemoryCache.php | 49 + .../motranslator/src/CacheException.php | 11 + vendor/phpmyadmin/motranslator/src/Loader.php | 318 +++++ .../phpmyadmin/motranslator/src/MoParser.php | 109 ++ .../motranslator/src/ReaderException.php | 35 + .../motranslator/src/StringReader.php | 116 ++ .../motranslator/src/Translator.php | 388 +++++ .../phpmyadmin/motranslator/src/functions.php | 226 +++ .../tests/Cache/ApcuCacheFactoryTest.php | 98 ++ .../tests/Cache/ApcuCacheTest.php | 270 ++++ .../tests/Cache/ApcuDisabledTest.php | 27 + .../tests/Cache/InMemoryCacheTest.php | 82 ++ .../motranslator/tests/FunctionsTest.php | 102 ++ .../motranslator/tests/LoaderTest.php | 325 +++++ .../motranslator/tests/MoFilesTest.php | 230 +++ .../motranslator/tests/PluralFormulaTest.php | 152 ++ .../motranslator/tests/PluralTest.php | 125 ++ .../motranslator/tests/StringReaderTest.php | 40 + .../motranslator/tests/TranslatorTest.php | 98 ++ .../phpmyadmin/motranslator/tests/data/big.mo | Bin 0 -> 332023 bytes .../motranslator/tests/data/error/big.mo | 1 + .../motranslator/tests/data/error/dos.mo | 1 + .../motranslator/tests/data/error/empty.mo | 0 .../motranslator/tests/data/error/fpd.mo | Bin 0 -> 12 bytes .../motranslator/tests/data/error/fpdle.mo | 1 + .../motranslator/tests/data/error/magic.mo | 1 + .../tests/data/invalid-formula.mo | Bin 0 -> 703 bytes .../motranslator/tests/data/lessplurals.mo | Bin 0 -> 169 bytes .../motranslator/tests/data/little.mo | Bin 0 -> 332023 bytes .../data/locale/be/LC_MESSAGES/phpmyadmin.mo | Bin 0 -> 103648 bytes .../locale/be@latin/LC_MESSAGES/phpmyadmin.mo | Bin 0 -> 79649 bytes .../data/locale/cs/LC_MESSAGES/phpmyadmin.mo | Bin 0 -> 332023 bytes .../motranslator/tests/data/noheader.mo | Bin 0 -> 190 bytes .../tests/data/not-translated/fpd1.mo | Bin 0 -> 30 bytes .../data/not-translated/invalid-equation.mo | Bin 0 -> 158 bytes .../motranslator/tests/data/plurals.mo | Bin 0 -> 332023 bytes vendor/psr/cache/CHANGELOG.md | 16 + vendor/psr/cache/LICENSE.txt | 19 + vendor/psr/cache/README.md | 12 + vendor/psr/cache/composer.json | 25 + vendor/psr/cache/src/CacheException.php | 10 + vendor/psr/cache/src/CacheItemInterface.php | 105 ++ .../psr/cache/src/CacheItemPoolInterface.php | 138 ++ .../cache/src/InvalidArgumentException.php | 13 + vendor/psr/container/.gitignore | 3 + vendor/psr/container/LICENSE | 21 + vendor/psr/container/README.md | 13 + vendor/psr/container/composer.json | 27 + .../src/ContainerExceptionInterface.php | 12 + .../psr/container/src/ContainerInterface.php | 36 + .../src/NotFoundExceptionInterface.php | 10 + vendor/psr/log/LICENSE | 19 + vendor/psr/log/README.md | 58 + vendor/psr/log/composer.json | 26 + vendor/psr/log/src/AbstractLogger.php | 15 + .../psr/log/src/InvalidArgumentException.php | 7 + vendor/psr/log/src/LogLevel.php | 18 + vendor/psr/log/src/LoggerAwareInterface.php | 14 + vendor/psr/log/src/LoggerAwareTrait.php | 22 + vendor/psr/log/src/LoggerInterface.php | 98 ++ vendor/psr/log/src/LoggerTrait.php | 98 ++ vendor/psr/log/src/NullLogger.php | 26 + vendor/symfony/cache-contracts/CHANGELOG.md | 5 + .../cache-contracts/CacheInterface.php | 59 + vendor/symfony/cache-contracts/CacheTrait.php | 72 + .../cache-contracts/CallbackInterface.php | 32 + .../symfony/cache-contracts/ItemInterface.php | 65 + vendor/symfony/cache-contracts/LICENSE | 19 + vendor/symfony/cache-contracts/README.md | 9 + .../TagAwareCacheInterface.php | 38 + vendor/symfony/cache-contracts/composer.json | 35 + .../symfony/cache/Adapter/AbstractAdapter.php | 191 +++ .../cache/Adapter/AbstractTagAwareAdapter.php | 320 +++++ .../cache/Adapter/AdapterInterface.php | 35 + vendor/symfony/cache/Adapter/ApcuAdapter.php | 116 ++ vendor/symfony/cache/Adapter/ArrayAdapter.php | 366 +++++ vendor/symfony/cache/Adapter/ChainAdapter.php | 291 ++++ .../cache/Adapter/CouchbaseBucketAdapter.php | 237 +++ .../Adapter/CouchbaseCollectionAdapter.php | 198 +++ .../cache/Adapter/DoctrineDbalAdapter.php | 383 +++++ .../cache/Adapter/FilesystemAdapter.php | 29 + .../Adapter/FilesystemTagAwareAdapter.php | 267 ++++ .../cache/Adapter/MemcachedAdapter.php | 329 +++++ vendor/symfony/cache/Adapter/NullAdapter.php | 105 ++ .../cache/Adapter/ParameterNormalizer.php | 35 + vendor/symfony/cache/Adapter/PdoAdapter.php | 398 ++++++ .../symfony/cache/Adapter/PhpArrayAdapter.php | 389 +++++ .../symfony/cache/Adapter/PhpFilesAdapter.php | 312 ++++ vendor/symfony/cache/Adapter/ProxyAdapter.php | 206 +++ vendor/symfony/cache/Adapter/Psr16Adapter.php | 71 + vendor/symfony/cache/Adapter/RedisAdapter.php | 25 + .../cache/Adapter/RedisTagAwareAdapter.php | 310 ++++ .../symfony/cache/Adapter/TagAwareAdapter.php | 368 +++++ .../Adapter/TagAwareAdapterInterface.php | 31 + .../cache/Adapter/TraceableAdapter.php | 249 ++++ .../Adapter/TraceableTagAwareAdapter.php | 35 + vendor/symfony/cache/CHANGELOG.md | 154 ++ vendor/symfony/cache/CacheItem.php | 198 +++ .../DataCollector/CacheDataCollector.php | 184 +++ .../CacheCollectorPass.php | 75 + .../CachePoolClearerPass.php | 38 + .../DependencyInjection/CachePoolPass.php | 243 ++++ .../CachePoolPrunerPass.php | 48 + .../cache/Exception/CacheException.php | 25 + .../Exception/InvalidArgumentException.php | 25 + .../cache/Exception/LogicException.php | 25 + vendor/symfony/cache/LICENSE | 19 + vendor/symfony/cache/LockRegistry.php | 166 +++ .../cache/Marshaller/DefaultMarshaller.php | 96 ++ .../cache/Marshaller/DeflateMarshaller.php | 44 + .../cache/Marshaller/MarshallerInterface.php | 38 + .../cache/Marshaller/SodiumMarshaller.php | 74 + .../cache/Marshaller/TagAwareMarshaller.php | 83 ++ .../Messenger/EarlyExpirationDispatcher.php | 60 + .../Messenger/EarlyExpirationHandler.php | 81 ++ .../Messenger/EarlyExpirationMessage.php | 96 ++ vendor/symfony/cache/PruneableInterface.php | 20 + vendor/symfony/cache/Psr16Cache.php | 240 ++++ vendor/symfony/cache/README.md | 19 + vendor/symfony/cache/ResettableInterface.php | 21 + .../cache/Traits/AbstractAdapterTrait.php | 377 +++++ .../symfony/cache/Traits/ContractsTrait.php | 113 ++ .../cache/Traits/FilesystemCommonTrait.php | 190 +++ .../symfony/cache/Traits/FilesystemTrait.php | 113 ++ vendor/symfony/cache/Traits/ProxyTrait.php | 37 + vendor/symfony/cache/Traits/Redis5Proxy.php | 1225 ++++++++++++++++ vendor/symfony/cache/Traits/Redis6Proxy.php | 1266 +++++++++++++++++ .../symfony/cache/Traits/Redis6ProxyTrait.php | 81 ++ .../cache/Traits/RedisCluster5Proxy.php | 980 +++++++++++++ .../cache/Traits/RedisCluster6Proxy.php | 1136 +++++++++++++++ .../cache/Traits/RedisCluster6ProxyTrait.php | 46 + .../cache/Traits/RedisClusterNodeProxy.php | 47 + .../cache/Traits/RedisClusterProxy.php | 23 + vendor/symfony/cache/Traits/RedisProxy.php | 23 + .../symfony/cache/Traits/RedisProxyTrait.php | 51 + vendor/symfony/cache/Traits/RedisTrait.php | 682 +++++++++ .../symfony/cache/Traits/Relay/CopyTrait.php | 36 + .../cache/Traits/Relay/GeosearchTrait.php | 36 + .../cache/Traits/Relay/GetrangeTrait.php | 36 + .../symfony/cache/Traits/Relay/HsetTrait.php | 36 + .../symfony/cache/Traits/Relay/MoveTrait.php | 46 + .../Traits/Relay/NullableReturnTrait.php | 96 ++ .../cache/Traits/Relay/PfcountTrait.php | 36 + vendor/symfony/cache/Traits/RelayProxy.php | 1265 ++++++++++++++++ .../symfony/cache/Traits/RelayProxyTrait.php | 147 ++ vendor/symfony/cache/Traits/ValueWrapper.php | 81 ++ vendor/symfony/cache/composer.json | 61 + .../deprecation-contracts/CHANGELOG.md | 5 + vendor/symfony/deprecation-contracts/LICENSE | 19 + .../symfony/deprecation-contracts/README.md | 26 + .../deprecation-contracts/composer.json | 35 + .../deprecation-contracts/function.php | 27 + .../symfony/expression-language/CHANGELOG.md | 46 + .../symfony/expression-language/Compiler.php | 149 ++ .../expression-language/Expression.php | 35 + .../ExpressionFunction.php | 91 ++ .../ExpressionFunctionProviderInterface.php | 23 + .../ExpressionLanguage.php | 183 +++ vendor/symfony/expression-language/LICENSE | 19 + vendor/symfony/expression-language/Lexer.php | 107 ++ .../Node/ArgumentsNode.php | 40 + .../expression-language/Node/ArrayNode.php | 116 ++ .../expression-language/Node/BinaryNode.php | 204 +++ .../Node/ConditionalNode.php | 56 + .../expression-language/Node/ConstantNode.php | 83 ++ .../expression-language/Node/FunctionNode.php | 70 + .../expression-language/Node/GetAttrNode.php | 166 +++ .../expression-language/Node/NameNode.php | 45 + .../symfony/expression-language/Node/Node.php | 130 ++ .../Node/NullCoalesceNode.php | 65 + .../expression-language/Node/UnaryNode.php | 64 + .../expression-language/ParsedExpression.php | 39 + vendor/symfony/expression-language/Parser.php | 439 ++++++ vendor/symfony/expression-language/README.md | 15 + .../Resources/bin/generate_operator_regex.php | 31 + .../SerializedParsedExpression.php | 42 + .../expression-language/SyntaxError.php | 41 + vendor/symfony/expression-language/Token.php | 58 + .../expression-language/TokenStream.php | 87 ++ .../symfony/expression-language/composer.json | 31 + .../service-contracts/Attribute/Required.php | 25 + .../Attribute/SubscribedService.php | 47 + vendor/symfony/service-contracts/CHANGELOG.md | 5 + vendor/symfony/service-contracts/LICENSE | 19 + vendor/symfony/service-contracts/README.md | 9 + .../service-contracts/ResetInterface.php | 33 + .../ServiceCollectionInterface.php | 26 + .../service-contracts/ServiceLocatorTrait.php | 115 ++ .../ServiceMethodsSubscriberTrait.php | 80 ++ .../ServiceProviderInterface.php | 45 + .../ServiceSubscriberInterface.php | 62 + .../ServiceSubscriberTrait.php | 84 ++ .../Test/ServiceLocatorTest.php | 23 + .../Test/ServiceLocatorTestCase.php | 96 ++ .../symfony/service-contracts/composer.json | 42 + vendor/symfony/var-exporter/CHANGELOG.md | 30 + .../Exception/ClassNotFoundException.php | 20 + .../Exception/ExceptionInterface.php | 16 + .../var-exporter/Exception/LogicException.php | 16 + .../NotInstantiableTypeException.php | 20 + vendor/symfony/var-exporter/Hydrator.php | 78 + vendor/symfony/var-exporter/Instantiator.php | 59 + .../var-exporter/Internal/Exporter.php | 418 ++++++ .../var-exporter/Internal/Hydrator.php | 298 ++++ .../Internal/LazyObjectRegistry.php | 138 ++ .../var-exporter/Internal/LazyObjectState.php | 97 ++ .../var-exporter/Internal/LazyObjectTrait.php | 34 + .../var-exporter/Internal/Reference.php | 28 + .../var-exporter/Internal/Registry.php | 142 ++ .../symfony/var-exporter/Internal/Values.php | 25 + vendor/symfony/var-exporter/LICENSE | 19 + .../symfony/var-exporter/LazyGhostTrait.php | 363 +++++ .../var-exporter/LazyObjectInterface.php | 32 + .../symfony/var-exporter/LazyProxyTrait.php | 366 +++++ vendor/symfony/var-exporter/ProxyHelper.php | 412 ++++++ vendor/symfony/var-exporter/README.md | 137 ++ vendor/symfony/var-exporter/VarExporter.php | 114 ++ vendor/symfony/var-exporter/composer.json | 33 + 249 files changed, 29788 insertions(+) create mode 100644 composer.json create mode 100644 composer.lock create mode 100644 translator.php create mode 100644 translator_gettext.php create mode 100644 vendor/autoload.php create mode 100644 vendor/composer/ClassLoader.php create mode 100644 vendor/composer/InstalledVersions.php create mode 100644 vendor/composer/LICENSE create mode 100644 vendor/composer/autoload_classmap.php create mode 100644 vendor/composer/autoload_files.php create mode 100644 vendor/composer/autoload_namespaces.php create mode 100644 vendor/composer/autoload_psr4.php create mode 100644 vendor/composer/autoload_real.php create mode 100644 vendor/composer/autoload_static.php create mode 100644 vendor/composer/installed.json create mode 100644 vendor/composer/installed.php create mode 100644 vendor/composer/platform_check.php create mode 100644 vendor/phpmyadmin/motranslator/CHANGELOG.md create mode 100644 vendor/phpmyadmin/motranslator/CODE_OF_CONDUCT.md create mode 100644 vendor/phpmyadmin/motranslator/CONTRIBUTING.md create mode 100644 vendor/phpmyadmin/motranslator/LICENSE create mode 100644 vendor/phpmyadmin/motranslator/PERFORMANCE.md create mode 100644 vendor/phpmyadmin/motranslator/README.md create mode 100644 vendor/phpmyadmin/motranslator/benchmark-apcu.php create mode 100644 vendor/phpmyadmin/motranslator/composer.json create mode 100644 vendor/phpmyadmin/motranslator/phpunit.xml.dist create mode 100644 vendor/phpmyadmin/motranslator/src/Cache/ApcuCache.php create mode 100644 vendor/phpmyadmin/motranslator/src/Cache/ApcuCacheFactory.php create mode 100644 vendor/phpmyadmin/motranslator/src/Cache/CacheFactoryInterface.php create mode 100644 vendor/phpmyadmin/motranslator/src/Cache/CacheInterface.php create mode 100644 vendor/phpmyadmin/motranslator/src/Cache/GetAllInterface.php create mode 100644 vendor/phpmyadmin/motranslator/src/Cache/InMemoryCache.php create mode 100644 vendor/phpmyadmin/motranslator/src/CacheException.php create mode 100644 vendor/phpmyadmin/motranslator/src/Loader.php create mode 100644 vendor/phpmyadmin/motranslator/src/MoParser.php create mode 100644 vendor/phpmyadmin/motranslator/src/ReaderException.php create mode 100644 vendor/phpmyadmin/motranslator/src/StringReader.php create mode 100644 vendor/phpmyadmin/motranslator/src/Translator.php create mode 100644 vendor/phpmyadmin/motranslator/src/functions.php create mode 100644 vendor/phpmyadmin/motranslator/tests/Cache/ApcuCacheFactoryTest.php create mode 100644 vendor/phpmyadmin/motranslator/tests/Cache/ApcuCacheTest.php create mode 100644 vendor/phpmyadmin/motranslator/tests/Cache/ApcuDisabledTest.php create mode 100644 vendor/phpmyadmin/motranslator/tests/Cache/InMemoryCacheTest.php create mode 100644 vendor/phpmyadmin/motranslator/tests/FunctionsTest.php create mode 100644 vendor/phpmyadmin/motranslator/tests/LoaderTest.php create mode 100644 vendor/phpmyadmin/motranslator/tests/MoFilesTest.php create mode 100644 vendor/phpmyadmin/motranslator/tests/PluralFormulaTest.php create mode 100644 vendor/phpmyadmin/motranslator/tests/PluralTest.php create mode 100644 vendor/phpmyadmin/motranslator/tests/StringReaderTest.php create mode 100644 vendor/phpmyadmin/motranslator/tests/TranslatorTest.php create mode 100644 vendor/phpmyadmin/motranslator/tests/data/big.mo create mode 100644 vendor/phpmyadmin/motranslator/tests/data/error/big.mo create mode 100644 vendor/phpmyadmin/motranslator/tests/data/error/dos.mo create mode 100644 vendor/phpmyadmin/motranslator/tests/data/error/empty.mo create mode 100644 vendor/phpmyadmin/motranslator/tests/data/error/fpd.mo create mode 100644 vendor/phpmyadmin/motranslator/tests/data/error/fpdle.mo create mode 100644 vendor/phpmyadmin/motranslator/tests/data/error/magic.mo create mode 100644 vendor/phpmyadmin/motranslator/tests/data/invalid-formula.mo create mode 100644 vendor/phpmyadmin/motranslator/tests/data/lessplurals.mo create mode 100644 vendor/phpmyadmin/motranslator/tests/data/little.mo create mode 100644 vendor/phpmyadmin/motranslator/tests/data/locale/be/LC_MESSAGES/phpmyadmin.mo create mode 100644 vendor/phpmyadmin/motranslator/tests/data/locale/be@latin/LC_MESSAGES/phpmyadmin.mo create mode 100644 vendor/phpmyadmin/motranslator/tests/data/locale/cs/LC_MESSAGES/phpmyadmin.mo create mode 100644 vendor/phpmyadmin/motranslator/tests/data/noheader.mo create mode 100644 vendor/phpmyadmin/motranslator/tests/data/not-translated/fpd1.mo create mode 100644 vendor/phpmyadmin/motranslator/tests/data/not-translated/invalid-equation.mo create mode 100644 vendor/phpmyadmin/motranslator/tests/data/plurals.mo create mode 100644 vendor/psr/cache/CHANGELOG.md create mode 100644 vendor/psr/cache/LICENSE.txt create mode 100644 vendor/psr/cache/README.md create mode 100644 vendor/psr/cache/composer.json create mode 100644 vendor/psr/cache/src/CacheException.php create mode 100644 vendor/psr/cache/src/CacheItemInterface.php create mode 100644 vendor/psr/cache/src/CacheItemPoolInterface.php create mode 100644 vendor/psr/cache/src/InvalidArgumentException.php create mode 100644 vendor/psr/container/.gitignore create mode 100644 vendor/psr/container/LICENSE create mode 100644 vendor/psr/container/README.md create mode 100644 vendor/psr/container/composer.json create mode 100644 vendor/psr/container/src/ContainerExceptionInterface.php create mode 100644 vendor/psr/container/src/ContainerInterface.php create mode 100644 vendor/psr/container/src/NotFoundExceptionInterface.php create mode 100644 vendor/psr/log/LICENSE create mode 100644 vendor/psr/log/README.md create mode 100644 vendor/psr/log/composer.json create mode 100644 vendor/psr/log/src/AbstractLogger.php create mode 100644 vendor/psr/log/src/InvalidArgumentException.php create mode 100644 vendor/psr/log/src/LogLevel.php create mode 100644 vendor/psr/log/src/LoggerAwareInterface.php create mode 100644 vendor/psr/log/src/LoggerAwareTrait.php create mode 100644 vendor/psr/log/src/LoggerInterface.php create mode 100644 vendor/psr/log/src/LoggerTrait.php create mode 100644 vendor/psr/log/src/NullLogger.php create mode 100644 vendor/symfony/cache-contracts/CHANGELOG.md create mode 100644 vendor/symfony/cache-contracts/CacheInterface.php create mode 100644 vendor/symfony/cache-contracts/CacheTrait.php create mode 100644 vendor/symfony/cache-contracts/CallbackInterface.php create mode 100644 vendor/symfony/cache-contracts/ItemInterface.php create mode 100644 vendor/symfony/cache-contracts/LICENSE create mode 100644 vendor/symfony/cache-contracts/README.md create mode 100644 vendor/symfony/cache-contracts/TagAwareCacheInterface.php create mode 100644 vendor/symfony/cache-contracts/composer.json create mode 100644 vendor/symfony/cache/Adapter/AbstractAdapter.php create mode 100644 vendor/symfony/cache/Adapter/AbstractTagAwareAdapter.php create mode 100644 vendor/symfony/cache/Adapter/AdapterInterface.php create mode 100644 vendor/symfony/cache/Adapter/ApcuAdapter.php create mode 100644 vendor/symfony/cache/Adapter/ArrayAdapter.php create mode 100644 vendor/symfony/cache/Adapter/ChainAdapter.php create mode 100644 vendor/symfony/cache/Adapter/CouchbaseBucketAdapter.php create mode 100644 vendor/symfony/cache/Adapter/CouchbaseCollectionAdapter.php create mode 100644 vendor/symfony/cache/Adapter/DoctrineDbalAdapter.php create mode 100644 vendor/symfony/cache/Adapter/FilesystemAdapter.php create mode 100644 vendor/symfony/cache/Adapter/FilesystemTagAwareAdapter.php create mode 100644 vendor/symfony/cache/Adapter/MemcachedAdapter.php create mode 100644 vendor/symfony/cache/Adapter/NullAdapter.php create mode 100644 vendor/symfony/cache/Adapter/ParameterNormalizer.php create mode 100644 vendor/symfony/cache/Adapter/PdoAdapter.php create mode 100644 vendor/symfony/cache/Adapter/PhpArrayAdapter.php create mode 100644 vendor/symfony/cache/Adapter/PhpFilesAdapter.php create mode 100644 vendor/symfony/cache/Adapter/ProxyAdapter.php create mode 100644 vendor/symfony/cache/Adapter/Psr16Adapter.php create mode 100644 vendor/symfony/cache/Adapter/RedisAdapter.php create mode 100644 vendor/symfony/cache/Adapter/RedisTagAwareAdapter.php create mode 100644 vendor/symfony/cache/Adapter/TagAwareAdapter.php create mode 100644 vendor/symfony/cache/Adapter/TagAwareAdapterInterface.php create mode 100644 vendor/symfony/cache/Adapter/TraceableAdapter.php create mode 100644 vendor/symfony/cache/Adapter/TraceableTagAwareAdapter.php create mode 100644 vendor/symfony/cache/CHANGELOG.md create mode 100644 vendor/symfony/cache/CacheItem.php create mode 100644 vendor/symfony/cache/DataCollector/CacheDataCollector.php create mode 100644 vendor/symfony/cache/DependencyInjection/CacheCollectorPass.php create mode 100644 vendor/symfony/cache/DependencyInjection/CachePoolClearerPass.php create mode 100644 vendor/symfony/cache/DependencyInjection/CachePoolPass.php create mode 100644 vendor/symfony/cache/DependencyInjection/CachePoolPrunerPass.php create mode 100644 vendor/symfony/cache/Exception/CacheException.php create mode 100644 vendor/symfony/cache/Exception/InvalidArgumentException.php create mode 100644 vendor/symfony/cache/Exception/LogicException.php create mode 100644 vendor/symfony/cache/LICENSE create mode 100644 vendor/symfony/cache/LockRegistry.php create mode 100644 vendor/symfony/cache/Marshaller/DefaultMarshaller.php create mode 100644 vendor/symfony/cache/Marshaller/DeflateMarshaller.php create mode 100644 vendor/symfony/cache/Marshaller/MarshallerInterface.php create mode 100644 vendor/symfony/cache/Marshaller/SodiumMarshaller.php create mode 100644 vendor/symfony/cache/Marshaller/TagAwareMarshaller.php create mode 100644 vendor/symfony/cache/Messenger/EarlyExpirationDispatcher.php create mode 100644 vendor/symfony/cache/Messenger/EarlyExpirationHandler.php create mode 100644 vendor/symfony/cache/Messenger/EarlyExpirationMessage.php create mode 100644 vendor/symfony/cache/PruneableInterface.php create mode 100644 vendor/symfony/cache/Psr16Cache.php create mode 100644 vendor/symfony/cache/README.md create mode 100644 vendor/symfony/cache/ResettableInterface.php create mode 100644 vendor/symfony/cache/Traits/AbstractAdapterTrait.php create mode 100644 vendor/symfony/cache/Traits/ContractsTrait.php create mode 100644 vendor/symfony/cache/Traits/FilesystemCommonTrait.php create mode 100644 vendor/symfony/cache/Traits/FilesystemTrait.php create mode 100644 vendor/symfony/cache/Traits/ProxyTrait.php create mode 100644 vendor/symfony/cache/Traits/Redis5Proxy.php create mode 100644 vendor/symfony/cache/Traits/Redis6Proxy.php create mode 100644 vendor/symfony/cache/Traits/Redis6ProxyTrait.php create mode 100644 vendor/symfony/cache/Traits/RedisCluster5Proxy.php create mode 100644 vendor/symfony/cache/Traits/RedisCluster6Proxy.php create mode 100644 vendor/symfony/cache/Traits/RedisCluster6ProxyTrait.php create mode 100644 vendor/symfony/cache/Traits/RedisClusterNodeProxy.php create mode 100644 vendor/symfony/cache/Traits/RedisClusterProxy.php create mode 100644 vendor/symfony/cache/Traits/RedisProxy.php create mode 100644 vendor/symfony/cache/Traits/RedisProxyTrait.php create mode 100644 vendor/symfony/cache/Traits/RedisTrait.php create mode 100644 vendor/symfony/cache/Traits/Relay/CopyTrait.php create mode 100644 vendor/symfony/cache/Traits/Relay/GeosearchTrait.php create mode 100644 vendor/symfony/cache/Traits/Relay/GetrangeTrait.php create mode 100644 vendor/symfony/cache/Traits/Relay/HsetTrait.php create mode 100644 vendor/symfony/cache/Traits/Relay/MoveTrait.php create mode 100644 vendor/symfony/cache/Traits/Relay/NullableReturnTrait.php create mode 100644 vendor/symfony/cache/Traits/Relay/PfcountTrait.php create mode 100644 vendor/symfony/cache/Traits/RelayProxy.php create mode 100644 vendor/symfony/cache/Traits/RelayProxyTrait.php create mode 100644 vendor/symfony/cache/Traits/ValueWrapper.php create mode 100644 vendor/symfony/cache/composer.json create mode 100644 vendor/symfony/deprecation-contracts/CHANGELOG.md create mode 100644 vendor/symfony/deprecation-contracts/LICENSE create mode 100644 vendor/symfony/deprecation-contracts/README.md create mode 100644 vendor/symfony/deprecation-contracts/composer.json create mode 100644 vendor/symfony/deprecation-contracts/function.php create mode 100644 vendor/symfony/expression-language/CHANGELOG.md create mode 100644 vendor/symfony/expression-language/Compiler.php create mode 100644 vendor/symfony/expression-language/Expression.php create mode 100644 vendor/symfony/expression-language/ExpressionFunction.php create mode 100644 vendor/symfony/expression-language/ExpressionFunctionProviderInterface.php create mode 100644 vendor/symfony/expression-language/ExpressionLanguage.php create mode 100644 vendor/symfony/expression-language/LICENSE create mode 100644 vendor/symfony/expression-language/Lexer.php create mode 100644 vendor/symfony/expression-language/Node/ArgumentsNode.php create mode 100644 vendor/symfony/expression-language/Node/ArrayNode.php create mode 100644 vendor/symfony/expression-language/Node/BinaryNode.php create mode 100644 vendor/symfony/expression-language/Node/ConditionalNode.php create mode 100644 vendor/symfony/expression-language/Node/ConstantNode.php create mode 100644 vendor/symfony/expression-language/Node/FunctionNode.php create mode 100644 vendor/symfony/expression-language/Node/GetAttrNode.php create mode 100644 vendor/symfony/expression-language/Node/NameNode.php create mode 100644 vendor/symfony/expression-language/Node/Node.php create mode 100644 vendor/symfony/expression-language/Node/NullCoalesceNode.php create mode 100644 vendor/symfony/expression-language/Node/UnaryNode.php create mode 100644 vendor/symfony/expression-language/ParsedExpression.php create mode 100644 vendor/symfony/expression-language/Parser.php create mode 100644 vendor/symfony/expression-language/README.md create mode 100644 vendor/symfony/expression-language/Resources/bin/generate_operator_regex.php create mode 100644 vendor/symfony/expression-language/SerializedParsedExpression.php create mode 100644 vendor/symfony/expression-language/SyntaxError.php create mode 100644 vendor/symfony/expression-language/Token.php create mode 100644 vendor/symfony/expression-language/TokenStream.php create mode 100644 vendor/symfony/expression-language/composer.json create mode 100644 vendor/symfony/service-contracts/Attribute/Required.php create mode 100644 vendor/symfony/service-contracts/Attribute/SubscribedService.php create mode 100644 vendor/symfony/service-contracts/CHANGELOG.md create mode 100644 vendor/symfony/service-contracts/LICENSE create mode 100644 vendor/symfony/service-contracts/README.md create mode 100644 vendor/symfony/service-contracts/ResetInterface.php create mode 100644 vendor/symfony/service-contracts/ServiceCollectionInterface.php create mode 100644 vendor/symfony/service-contracts/ServiceLocatorTrait.php create mode 100644 vendor/symfony/service-contracts/ServiceMethodsSubscriberTrait.php create mode 100644 vendor/symfony/service-contracts/ServiceProviderInterface.php create mode 100644 vendor/symfony/service-contracts/ServiceSubscriberInterface.php create mode 100644 vendor/symfony/service-contracts/ServiceSubscriberTrait.php create mode 100644 vendor/symfony/service-contracts/Test/ServiceLocatorTest.php create mode 100644 vendor/symfony/service-contracts/Test/ServiceLocatorTestCase.php create mode 100644 vendor/symfony/service-contracts/composer.json create mode 100644 vendor/symfony/var-exporter/CHANGELOG.md create mode 100644 vendor/symfony/var-exporter/Exception/ClassNotFoundException.php create mode 100644 vendor/symfony/var-exporter/Exception/ExceptionInterface.php create mode 100644 vendor/symfony/var-exporter/Exception/LogicException.php create mode 100644 vendor/symfony/var-exporter/Exception/NotInstantiableTypeException.php create mode 100644 vendor/symfony/var-exporter/Hydrator.php create mode 100644 vendor/symfony/var-exporter/Instantiator.php create mode 100644 vendor/symfony/var-exporter/Internal/Exporter.php create mode 100644 vendor/symfony/var-exporter/Internal/Hydrator.php create mode 100644 vendor/symfony/var-exporter/Internal/LazyObjectRegistry.php create mode 100644 vendor/symfony/var-exporter/Internal/LazyObjectState.php create mode 100644 vendor/symfony/var-exporter/Internal/LazyObjectTrait.php create mode 100644 vendor/symfony/var-exporter/Internal/Reference.php create mode 100644 vendor/symfony/var-exporter/Internal/Registry.php create mode 100644 vendor/symfony/var-exporter/Internal/Values.php create mode 100644 vendor/symfony/var-exporter/LICENSE create mode 100644 vendor/symfony/var-exporter/LazyGhostTrait.php create mode 100644 vendor/symfony/var-exporter/LazyObjectInterface.php create mode 100644 vendor/symfony/var-exporter/LazyProxyTrait.php create mode 100644 vendor/symfony/var-exporter/ProxyHelper.php create mode 100644 vendor/symfony/var-exporter/README.md create mode 100644 vendor/symfony/var-exporter/VarExporter.php create mode 100644 vendor/symfony/var-exporter/composer.json diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..d37275a --- /dev/null +++ b/composer.json @@ -0,0 +1,5 @@ +{ + "require": { + "phpmyadmin/motranslator": "^5.3" + } +} diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000..65da850 --- /dev/null +++ b/composer.lock @@ -0,0 +1,692 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "b102e899e31d62f4d40282ff04a339d9", + "packages": [ + { + "name": "phpmyadmin/motranslator", + "version": "5.3.1", + "source": { + "type": "git", + "url": "https://github.com/phpmyadmin/motranslator.git", + "reference": "d03b4d9c608e7265091bf6decc05323d16c7c047" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpmyadmin/motranslator/zipball/d03b4d9c608e7265091bf6decc05323d16c7c047", + "reference": "d03b4d9c608e7265091bf6decc05323d16c7c047", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0", + "symfony/expression-language": "^4.0 || ^5.0 || ^6.0" + }, + "require-dev": { + "phpmyadmin/coding-standard": "^3.0.0", + "phpstan/phpstan": "^1.4.6", + "phpunit/phpunit": "^7.4 || ^8 || ^9" + }, + "suggest": { + "ext-apcu": "Needed for ACPu-backed translation cache" + }, + "type": "library", + "autoload": { + "psr-4": { + "PhpMyAdmin\\MoTranslator\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0-or-later" + ], + "authors": [ + { + "name": "The phpMyAdmin Team", + "email": "developers@phpmyadmin.net", + "homepage": "https://www.phpmyadmin.net/team/" + } + ], + "description": "Translation API for PHP using Gettext MO files", + "homepage": "https://github.com/phpmyadmin/motranslator", + "keywords": [ + "gettext", + "i18n", + "mo", + "translator" + ], + "support": { + "issues": "https://github.com/phpmyadmin/motranslator/issues", + "source": "https://github.com/phpmyadmin/motranslator" + }, + "time": "2023-08-23T18:32:07+00:00" + }, + { + "name": "psr/cache", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/cache.git", + "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/cache/zipball/aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", + "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Cache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for caching libraries", + "keywords": [ + "cache", + "psr", + "psr-6" + ], + "support": { + "source": "https://github.com/php-fig/cache/tree/3.0.0" + }, + "time": "2021-02-03T23:26:27+00:00" + }, + { + "name": "psr/container", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "shasum": "" + }, + "require": { + "php": ">=7.4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/2.0.2" + }, + "time": "2021-11-05T16:47:00+00:00" + }, + { + "name": "psr/log", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "support": { + "source": "https://github.com/php-fig/log/tree/3.0.2" + }, + "time": "2024-09-11T13:17:53+00:00" + }, + { + "name": "symfony/cache", + "version": "v7.2.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/cache.git", + "reference": "e7e983596b744c4539f31e79b0350a6cf5878a20" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/cache/zipball/e7e983596b744c4539f31e79b0350a6cf5878a20", + "reference": "e7e983596b744c4539f31e79b0350a6cf5878a20", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "psr/cache": "^2.0|^3.0", + "psr/log": "^1.1|^2|^3", + "symfony/cache-contracts": "^2.5|^3", + "symfony/deprecation-contracts": "^2.5|^3.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/var-exporter": "^6.4|^7.0" + }, + "conflict": { + "doctrine/dbal": "<3.6", + "symfony/dependency-injection": "<6.4", + "symfony/http-kernel": "<6.4", + "symfony/var-dumper": "<6.4" + }, + "provide": { + "psr/cache-implementation": "2.0|3.0", + "psr/simple-cache-implementation": "1.0|2.0|3.0", + "symfony/cache-implementation": "1.1|2.0|3.0" + }, + "require-dev": { + "cache/integration-tests": "dev-master", + "doctrine/dbal": "^3.6|^4", + "predis/predis": "^1.1|^2.0", + "psr/simple-cache": "^1.0|^2.0|^3.0", + "symfony/clock": "^6.4|^7.0", + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/filesystem": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/messenger": "^6.4|^7.0", + "symfony/var-dumper": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Cache\\": "" + }, + "classmap": [ + "Traits/ValueWrapper.php" + ], + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides extended PSR-6, PSR-16 (and tags) implementations", + "homepage": "https://symfony.com", + "keywords": [ + "caching", + "psr6" + ], + "support": { + "source": "https://github.com/symfony/cache/tree/v7.2.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-12-07T08:08:50+00:00" + }, + { + "name": "symfony/cache-contracts", + "version": "v3.5.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/cache-contracts.git", + "reference": "15a4f8e5cd3bce9aeafc882b1acab39ec8de2c1b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/15a4f8e5cd3bce9aeafc882b1acab39ec8de2c1b", + "reference": "15a4f8e5cd3bce9aeafc882b1acab39ec8de2c1b", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/cache": "^3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Cache\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to caching", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/cache-contracts/tree/v3.5.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:20:29+00:00" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v3.5.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", + "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:20:29+00:00" + }, + { + "name": "symfony/expression-language", + "version": "v6.4.13", + "source": { + "type": "git", + "url": "https://github.com/symfony/expression-language.git", + "reference": "3524904fb026356a5230cd197f9a4e6a61e0e7df" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/expression-language/zipball/3524904fb026356a5230cd197f9a4e6a61e0e7df", + "reference": "3524904fb026356a5230cd197f9a4e6a61e0e7df", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/cache": "^5.4|^6.0|^7.0", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/service-contracts": "^2.5|^3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\ExpressionLanguage\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an engine that can compile and evaluate expressions", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/expression-language/tree/v6.4.13" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-10-09T08:40:40+00:00" + }, + { + "name": "symfony/service-contracts", + "version": "v3.5.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/e53260aabf78fb3d63f8d79d69ece59f80d5eda0", + "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/service-contracts/tree/v3.5.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:20:29+00:00" + }, + { + "name": "symfony/var-exporter", + "version": "v7.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-exporter.git", + "reference": "1a6a89f95a46af0f142874c9d650a6358d13070d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/1a6a89f95a46af0f142874c9d650a6358d13070d", + "reference": "1a6a89f95a46af0f142874c9d650a6358d13070d", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "symfony/property-access": "^6.4|^7.0", + "symfony/serializer": "^6.4|^7.0", + "symfony/var-dumper": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\VarExporter\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Allows exporting any serializable PHP data structure to plain PHP code", + "homepage": "https://symfony.com", + "keywords": [ + "clone", + "construct", + "export", + "hydrate", + "instantiate", + "lazy-loading", + "proxy", + "serialize" + ], + "support": { + "source": "https://github.com/symfony/var-exporter/tree/v7.2.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-10-18T07:58:17+00:00" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": {}, + "prefer-stable": false, + "prefer-lowest": false, + "platform": {}, + "platform-dev": {}, + "plugin-api-version": "2.6.0" +} diff --git a/translator.php b/translator.php new file mode 100644 index 0000000..0bf721e --- /dev/null +++ b/translator.php @@ -0,0 +1,39 @@ +setlocale('fr_FR.utf8'); + +// Set default text domain +$loader->textdomain($domain); + +// Set path where to look for a domain +$loader->bindtextdomain($domain, __DIR__ . '/Locale/'); + +// Get translator +$translator = $loader->getTranslator(); + + + +// Now you can use Translator API (see below) + +echo $translator->gettext('String'); + +echo $translator->gettext('Aperture Priority'); + +//echo $translator->getTranslations(); +/* +echo $translator->setTranslations([ + 'String' => 'ChaĆ®ne', + 'Number' => 'Nombre', +]); + +echo $translator->gettext('String'); +*/ +?> diff --git a/translator_gettext.php b/translator_gettext.php new file mode 100644 index 0000000..cfffc72 --- /dev/null +++ b/translator_gettext.php @@ -0,0 +1,19 @@ + diff --git a/vendor/autoload.php b/vendor/autoload.php new file mode 100644 index 0000000..67a1231 --- /dev/null +++ b/vendor/autoload.php @@ -0,0 +1,25 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Autoload; + +/** + * ClassLoader implements a PSR-0, PSR-4 and classmap class loader. + * + * $loader = new \Composer\Autoload\ClassLoader(); + * + * // register classes with namespaces + * $loader->add('Symfony\Component', __DIR__.'/component'); + * $loader->add('Symfony', __DIR__.'/framework'); + * + * // activate the autoloader + * $loader->register(); + * + * // to enable searching the include path (eg. for PEAR packages) + * $loader->setUseIncludePath(true); + * + * In this example, if you try to use a class in the Symfony\Component + * namespace or one of its children (Symfony\Component\Console for instance), + * the autoloader will first look for the class under the component/ + * directory, and it will then fallback to the framework/ directory if not + * found before giving up. + * + * This class is loosely based on the Symfony UniversalClassLoader. + * + * @author Fabien Potencier + * @author Jordi Boggiano + * @see https://www.php-fig.org/psr/psr-0/ + * @see https://www.php-fig.org/psr/psr-4/ + */ +class ClassLoader +{ + /** @var \Closure(string):void */ + private static $includeFile; + + /** @var string|null */ + private $vendorDir; + + // PSR-4 + /** + * @var array> + */ + private $prefixLengthsPsr4 = array(); + /** + * @var array> + */ + private $prefixDirsPsr4 = array(); + /** + * @var list + */ + private $fallbackDirsPsr4 = array(); + + // PSR-0 + /** + * List of PSR-0 prefixes + * + * Structured as array('F (first letter)' => array('Foo\Bar (full prefix)' => array('path', 'path2'))) + * + * @var array>> + */ + private $prefixesPsr0 = array(); + /** + * @var list + */ + private $fallbackDirsPsr0 = array(); + + /** @var bool */ + private $useIncludePath = false; + + /** + * @var array + */ + private $classMap = array(); + + /** @var bool */ + private $classMapAuthoritative = false; + + /** + * @var array + */ + private $missingClasses = array(); + + /** @var string|null */ + private $apcuPrefix; + + /** + * @var array + */ + private static $registeredLoaders = array(); + + /** + * @param string|null $vendorDir + */ + public function __construct($vendorDir = null) + { + $this->vendorDir = $vendorDir; + self::initializeIncludeClosure(); + } + + /** + * @return array> + */ + public function getPrefixes() + { + if (!empty($this->prefixesPsr0)) { + return call_user_func_array('array_merge', array_values($this->prefixesPsr0)); + } + + return array(); + } + + /** + * @return array> + */ + public function getPrefixesPsr4() + { + return $this->prefixDirsPsr4; + } + + /** + * @return list + */ + public function getFallbackDirs() + { + return $this->fallbackDirsPsr0; + } + + /** + * @return list + */ + public function getFallbackDirsPsr4() + { + return $this->fallbackDirsPsr4; + } + + /** + * @return array Array of classname => path + */ + public function getClassMap() + { + return $this->classMap; + } + + /** + * @param array $classMap Class to filename map + * + * @return void + */ + public function addClassMap(array $classMap) + { + if ($this->classMap) { + $this->classMap = array_merge($this->classMap, $classMap); + } else { + $this->classMap = $classMap; + } + } + + /** + * Registers a set of PSR-0 directories for a given prefix, either + * appending or prepending to the ones previously set for this prefix. + * + * @param string $prefix The prefix + * @param list|string $paths The PSR-0 root directories + * @param bool $prepend Whether to prepend the directories + * + * @return void + */ + public function add($prefix, $paths, $prepend = false) + { + $paths = (array) $paths; + if (!$prefix) { + if ($prepend) { + $this->fallbackDirsPsr0 = array_merge( + $paths, + $this->fallbackDirsPsr0 + ); + } else { + $this->fallbackDirsPsr0 = array_merge( + $this->fallbackDirsPsr0, + $paths + ); + } + + return; + } + + $first = $prefix[0]; + if (!isset($this->prefixesPsr0[$first][$prefix])) { + $this->prefixesPsr0[$first][$prefix] = $paths; + + return; + } + if ($prepend) { + $this->prefixesPsr0[$first][$prefix] = array_merge( + $paths, + $this->prefixesPsr0[$first][$prefix] + ); + } else { + $this->prefixesPsr0[$first][$prefix] = array_merge( + $this->prefixesPsr0[$first][$prefix], + $paths + ); + } + } + + /** + * Registers a set of PSR-4 directories for a given namespace, either + * appending or prepending to the ones previously set for this namespace. + * + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param list|string $paths The PSR-4 base directories + * @param bool $prepend Whether to prepend the directories + * + * @throws \InvalidArgumentException + * + * @return void + */ + public function addPsr4($prefix, $paths, $prepend = false) + { + $paths = (array) $paths; + if (!$prefix) { + // Register directories for the root namespace. + if ($prepend) { + $this->fallbackDirsPsr4 = array_merge( + $paths, + $this->fallbackDirsPsr4 + ); + } else { + $this->fallbackDirsPsr4 = array_merge( + $this->fallbackDirsPsr4, + $paths + ); + } + } elseif (!isset($this->prefixDirsPsr4[$prefix])) { + // Register directories for a new namespace. + $length = strlen($prefix); + if ('\\' !== $prefix[$length - 1]) { + throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); + } + $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; + $this->prefixDirsPsr4[$prefix] = $paths; + } elseif ($prepend) { + // Prepend directories for an already registered namespace. + $this->prefixDirsPsr4[$prefix] = array_merge( + $paths, + $this->prefixDirsPsr4[$prefix] + ); + } else { + // Append directories for an already registered namespace. + $this->prefixDirsPsr4[$prefix] = array_merge( + $this->prefixDirsPsr4[$prefix], + $paths + ); + } + } + + /** + * Registers a set of PSR-0 directories for a given prefix, + * replacing any others previously set for this prefix. + * + * @param string $prefix The prefix + * @param list|string $paths The PSR-0 base directories + * + * @return void + */ + public function set($prefix, $paths) + { + if (!$prefix) { + $this->fallbackDirsPsr0 = (array) $paths; + } else { + $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths; + } + } + + /** + * Registers a set of PSR-4 directories for a given namespace, + * replacing any others previously set for this namespace. + * + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param list|string $paths The PSR-4 base directories + * + * @throws \InvalidArgumentException + * + * @return void + */ + public function setPsr4($prefix, $paths) + { + if (!$prefix) { + $this->fallbackDirsPsr4 = (array) $paths; + } else { + $length = strlen($prefix); + if ('\\' !== $prefix[$length - 1]) { + throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); + } + $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; + $this->prefixDirsPsr4[$prefix] = (array) $paths; + } + } + + /** + * Turns on searching the include path for class files. + * + * @param bool $useIncludePath + * + * @return void + */ + public function setUseIncludePath($useIncludePath) + { + $this->useIncludePath = $useIncludePath; + } + + /** + * Can be used to check if the autoloader uses the include path to check + * for classes. + * + * @return bool + */ + public function getUseIncludePath() + { + return $this->useIncludePath; + } + + /** + * Turns off searching the prefix and fallback directories for classes + * that have not been registered with the class map. + * + * @param bool $classMapAuthoritative + * + * @return void + */ + public function setClassMapAuthoritative($classMapAuthoritative) + { + $this->classMapAuthoritative = $classMapAuthoritative; + } + + /** + * Should class lookup fail if not found in the current class map? + * + * @return bool + */ + public function isClassMapAuthoritative() + { + return $this->classMapAuthoritative; + } + + /** + * APCu prefix to use to cache found/not-found classes, if the extension is enabled. + * + * @param string|null $apcuPrefix + * + * @return void + */ + public function setApcuPrefix($apcuPrefix) + { + $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null; + } + + /** + * The APCu prefix in use, or null if APCu caching is not enabled. + * + * @return string|null + */ + public function getApcuPrefix() + { + return $this->apcuPrefix; + } + + /** + * Registers this instance as an autoloader. + * + * @param bool $prepend Whether to prepend the autoloader or not + * + * @return void + */ + public function register($prepend = false) + { + spl_autoload_register(array($this, 'loadClass'), true, $prepend); + + if (null === $this->vendorDir) { + return; + } + + if ($prepend) { + self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders; + } else { + unset(self::$registeredLoaders[$this->vendorDir]); + self::$registeredLoaders[$this->vendorDir] = $this; + } + } + + /** + * Unregisters this instance as an autoloader. + * + * @return void + */ + public function unregister() + { + spl_autoload_unregister(array($this, 'loadClass')); + + if (null !== $this->vendorDir) { + unset(self::$registeredLoaders[$this->vendorDir]); + } + } + + /** + * Loads the given class or interface. + * + * @param string $class The name of the class + * @return true|null True if loaded, null otherwise + */ + public function loadClass($class) + { + if ($file = $this->findFile($class)) { + $includeFile = self::$includeFile; + $includeFile($file); + + return true; + } + + return null; + } + + /** + * Finds the path to the file where the class is defined. + * + * @param string $class The name of the class + * + * @return string|false The path if found, false otherwise + */ + public function findFile($class) + { + // class map lookup + if (isset($this->classMap[$class])) { + return $this->classMap[$class]; + } + if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) { + return false; + } + if (null !== $this->apcuPrefix) { + $file = apcu_fetch($this->apcuPrefix.$class, $hit); + if ($hit) { + return $file; + } + } + + $file = $this->findFileWithExtension($class, '.php'); + + // Search for Hack files if we are running on HHVM + if (false === $file && defined('HHVM_VERSION')) { + $file = $this->findFileWithExtension($class, '.hh'); + } + + if (null !== $this->apcuPrefix) { + apcu_add($this->apcuPrefix.$class, $file); + } + + if (false === $file) { + // Remember that this class does not exist. + $this->missingClasses[$class] = true; + } + + return $file; + } + + /** + * Returns the currently registered loaders keyed by their corresponding vendor directories. + * + * @return array + */ + public static function getRegisteredLoaders() + { + return self::$registeredLoaders; + } + + /** + * @param string $class + * @param string $ext + * @return string|false + */ + private function findFileWithExtension($class, $ext) + { + // PSR-4 lookup + $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; + + $first = $class[0]; + if (isset($this->prefixLengthsPsr4[$first])) { + $subPath = $class; + while (false !== $lastPos = strrpos($subPath, '\\')) { + $subPath = substr($subPath, 0, $lastPos); + $search = $subPath . '\\'; + if (isset($this->prefixDirsPsr4[$search])) { + $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1); + foreach ($this->prefixDirsPsr4[$search] as $dir) { + if (file_exists($file = $dir . $pathEnd)) { + return $file; + } + } + } + } + } + + // PSR-4 fallback dirs + foreach ($this->fallbackDirsPsr4 as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { + return $file; + } + } + + // PSR-0 lookup + if (false !== $pos = strrpos($class, '\\')) { + // namespaced class name + $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) + . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR); + } else { + // PEAR-like class name + $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext; + } + + if (isset($this->prefixesPsr0[$first])) { + foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { + if (0 === strpos($class, $prefix)) { + foreach ($dirs as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + return $file; + } + } + } + } + } + + // PSR-0 fallback dirs + foreach ($this->fallbackDirsPsr0 as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + return $file; + } + } + + // PSR-0 include paths. + if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { + return $file; + } + + return false; + } + + /** + * @return void + */ + private static function initializeIncludeClosure() + { + if (self::$includeFile !== null) { + return; + } + + /** + * Scope isolated include. + * + * Prevents access to $this/self from included files. + * + * @param string $file + * @return void + */ + self::$includeFile = \Closure::bind(static function($file) { + include $file; + }, null, null); + } +} diff --git a/vendor/composer/InstalledVersions.php b/vendor/composer/InstalledVersions.php new file mode 100644 index 0000000..07b32ed --- /dev/null +++ b/vendor/composer/InstalledVersions.php @@ -0,0 +1,362 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer; + +use Composer\Autoload\ClassLoader; +use Composer\Semver\VersionParser; + +/** + * This class is copied in every Composer installed project and available to all + * + * See also https://getcomposer.org/doc/07-runtime.md#installed-versions + * + * To require its presence, you can require `composer-runtime-api ^2.0` + * + * @final + */ +class InstalledVersions +{ + /** + * @var mixed[]|null + * @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array}|array{}|null + */ + private static $installed; + + /** + * @var bool|null + */ + private static $canGetVendors; + + /** + * @var array[] + * @psalm-var array}> + */ + private static $installedByVendor = array(); + + /** + * Returns a list of all package names which are present, either by being installed, replaced or provided + * + * @return string[] + * @psalm-return list + */ + public static function getInstalledPackages() + { + $packages = array(); + foreach (self::getInstalled() as $installed) { + $packages[] = array_keys($installed['versions']); + } + + if (1 === \count($packages)) { + return $packages[0]; + } + + return array_keys(array_flip(\call_user_func_array('array_merge', $packages))); + } + + /** + * Returns a list of all package names with a specific type e.g. 'library' + * + * @param string $type + * @return string[] + * @psalm-return list + */ + public static function getInstalledPackagesByType($type) + { + $packagesByType = array(); + + foreach (self::getInstalled() as $installed) { + foreach ($installed['versions'] as $name => $package) { + if (isset($package['type']) && $package['type'] === $type) { + $packagesByType[] = $name; + } + } + } + + return $packagesByType; + } + + /** + * Checks whether the given package is installed + * + * This also returns true if the package name is provided or replaced by another package + * + * @param string $packageName + * @param bool $includeDevRequirements + * @return bool + */ + public static function isInstalled($packageName, $includeDevRequirements = true) + { + foreach (self::getInstalled() as $installed) { + if (isset($installed['versions'][$packageName])) { + return $includeDevRequirements || !isset($installed['versions'][$packageName]['dev_requirement']) || $installed['versions'][$packageName]['dev_requirement'] === false; + } + } + + return false; + } + + /** + * Checks whether the given package satisfies a version constraint + * + * e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call: + * + * Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3') + * + * @param VersionParser $parser Install composer/semver to have access to this class and functionality + * @param string $packageName + * @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package + * @return bool + */ + public static function satisfies(VersionParser $parser, $packageName, $constraint) + { + $constraint = $parser->parseConstraints((string) $constraint); + $provided = $parser->parseConstraints(self::getVersionRanges($packageName)); + + return $provided->matches($constraint); + } + + /** + * Returns a version constraint representing all the range(s) which are installed for a given package + * + * It is easier to use this via isInstalled() with the $constraint argument if you need to check + * whether a given version of a package is installed, and not just whether it exists + * + * @param string $packageName + * @return string Version constraint usable with composer/semver + */ + public static function getVersionRanges($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + $ranges = array(); + if (isset($installed['versions'][$packageName]['pretty_version'])) { + $ranges[] = $installed['versions'][$packageName]['pretty_version']; + } + if (array_key_exists('aliases', $installed['versions'][$packageName])) { + $ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']); + } + if (array_key_exists('replaced', $installed['versions'][$packageName])) { + $ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']); + } + if (array_key_exists('provided', $installed['versions'][$packageName])) { + $ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']); + } + + return implode(' || ', $ranges); + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @param string $packageName + * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present + */ + public static function getVersion($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + if (!isset($installed['versions'][$packageName]['version'])) { + return null; + } + + return $installed['versions'][$packageName]['version']; + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @param string $packageName + * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present + */ + public static function getPrettyVersion($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + if (!isset($installed['versions'][$packageName]['pretty_version'])) { + return null; + } + + return $installed['versions'][$packageName]['pretty_version']; + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @param string $packageName + * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference + */ + public static function getReference($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + if (!isset($installed['versions'][$packageName]['reference'])) { + return null; + } + + return $installed['versions'][$packageName]['reference']; + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @param string $packageName + * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path. + */ + public static function getInstallPath($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null; + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @return array + * @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool} + */ + public static function getRootPackage() + { + $installed = self::getInstalled(); + + return $installed[0]['root']; + } + + /** + * Returns the raw installed.php data for custom implementations + * + * @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect. + * @return array[] + * @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} + */ + public static function getRawData() + { + @trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED); + + if (null === self::$installed) { + // only require the installed.php file if this file is loaded from its dumped location, + // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937 + if (substr(__DIR__, -8, 1) !== 'C') { + self::$installed = include __DIR__ . '/installed.php'; + } else { + self::$installed = array(); + } + } + + return self::$installed; + } + + /** + * Returns the raw data of all installed.php which are currently loaded for custom implementations + * + * @return array[] + * @psalm-return list}> + */ + public static function getAllRawData() + { + return self::getInstalled(); + } + + /** + * Lets you reload the static array from another file + * + * This is only useful for complex integrations in which a project needs to use + * this class but then also needs to execute another project's autoloader in process, + * and wants to ensure both projects have access to their version of installed.php. + * + * A typical case would be PHPUnit, where it would need to make sure it reads all + * the data it needs from this class, then call reload() with + * `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure + * the project in which it runs can then also use this class safely, without + * interference between PHPUnit's dependencies and the project's dependencies. + * + * @param array[] $data A vendor/composer/installed.php data set + * @return void + * + * @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} $data + */ + public static function reload($data) + { + self::$installed = $data; + self::$installedByVendor = array(); + } + + /** + * @return array[] + * @psalm-return list}> + */ + private static function getInstalled() + { + if (null === self::$canGetVendors) { + self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders'); + } + + $installed = array(); + $copiedLocalDir = false; + + if (self::$canGetVendors) { + foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) { + if (isset(self::$installedByVendor[$vendorDir])) { + $installed[] = self::$installedByVendor[$vendorDir]; + } elseif (is_file($vendorDir.'/composer/installed.php')) { + /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} $required */ + $required = require $vendorDir.'/composer/installed.php'; + self::$installedByVendor[$vendorDir] = $required; + $installed[] = $required; + if (strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) { + self::$installed = $required; + $copiedLocalDir = true; + } + } + } + } + + if (null === self::$installed) { + // only require the installed.php file if this file is loaded from its dumped location, + // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937 + if (substr(__DIR__, -8, 1) !== 'C') { + /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} $required */ + $required = require __DIR__ . '/installed.php'; + self::$installed = $required; + } else { + self::$installed = array(); + } + } + + if (self::$installed !== array() && !$copiedLocalDir) { + $installed[] = self::$installed; + } + + return $installed; + } +} diff --git a/vendor/composer/LICENSE b/vendor/composer/LICENSE new file mode 100644 index 0000000..f27399a --- /dev/null +++ b/vendor/composer/LICENSE @@ -0,0 +1,21 @@ + +Copyright (c) Nils Adermann, Jordi Boggiano + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php new file mode 100644 index 0000000..322ba01 --- /dev/null +++ b/vendor/composer/autoload_classmap.php @@ -0,0 +1,11 @@ + $vendorDir . '/composer/InstalledVersions.php', + '©' => $vendorDir . '/symfony/cache/Traits/ValueWrapper.php', +); diff --git a/vendor/composer/autoload_files.php b/vendor/composer/autoload_files.php new file mode 100644 index 0000000..be8e1c3 --- /dev/null +++ b/vendor/composer/autoload_files.php @@ -0,0 +1,10 @@ + $vendorDir . '/symfony/deprecation-contracts/function.php', +); diff --git a/vendor/composer/autoload_namespaces.php b/vendor/composer/autoload_namespaces.php new file mode 100644 index 0000000..15a2ff3 --- /dev/null +++ b/vendor/composer/autoload_namespaces.php @@ -0,0 +1,9 @@ + array($vendorDir . '/symfony/service-contracts'), + 'Symfony\\Contracts\\Cache\\' => array($vendorDir . '/symfony/cache-contracts'), + 'Symfony\\Component\\VarExporter\\' => array($vendorDir . '/symfony/var-exporter'), + 'Symfony\\Component\\ExpressionLanguage\\' => array($vendorDir . '/symfony/expression-language'), + 'Symfony\\Component\\Cache\\' => array($vendorDir . '/symfony/cache'), + 'Psr\\Log\\' => array($vendorDir . '/psr/log/src'), + 'Psr\\Container\\' => array($vendorDir . '/psr/container/src'), + 'Psr\\Cache\\' => array($vendorDir . '/psr/cache/src'), + 'PhpMyAdmin\\MoTranslator\\' => array($vendorDir . '/phpmyadmin/motranslator/src'), +); diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php new file mode 100644 index 0000000..c17a605 --- /dev/null +++ b/vendor/composer/autoload_real.php @@ -0,0 +1,50 @@ +register(true); + + $filesToLoad = \Composer\Autoload\ComposerStaticInitf0f23926796d6825a9caf18ca123a270::$files; + $requireFile = \Closure::bind(static function ($fileIdentifier, $file) { + if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { + $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; + + require $file; + } + }, null, null); + foreach ($filesToLoad as $fileIdentifier => $file) { + $requireFile($fileIdentifier, $file); + } + + return $loader; + } +} diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php new file mode 100644 index 0000000..cb74c64 --- /dev/null +++ b/vendor/composer/autoload_static.php @@ -0,0 +1,84 @@ + __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php', + ); + + public static $prefixLengthsPsr4 = array ( + 'S' => + array ( + 'Symfony\\Contracts\\Service\\' => 26, + 'Symfony\\Contracts\\Cache\\' => 24, + 'Symfony\\Component\\VarExporter\\' => 30, + 'Symfony\\Component\\ExpressionLanguage\\' => 37, + 'Symfony\\Component\\Cache\\' => 24, + ), + 'P' => + array ( + 'Psr\\Log\\' => 8, + 'Psr\\Container\\' => 14, + 'Psr\\Cache\\' => 10, + 'PhpMyAdmin\\MoTranslator\\' => 24, + ), + ); + + public static $prefixDirsPsr4 = array ( + 'Symfony\\Contracts\\Service\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/service-contracts', + ), + 'Symfony\\Contracts\\Cache\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/cache-contracts', + ), + 'Symfony\\Component\\VarExporter\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/var-exporter', + ), + 'Symfony\\Component\\ExpressionLanguage\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/expression-language', + ), + 'Symfony\\Component\\Cache\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/cache', + ), + 'Psr\\Log\\' => + array ( + 0 => __DIR__ . '/..' . '/psr/log/src', + ), + 'Psr\\Container\\' => + array ( + 0 => __DIR__ . '/..' . '/psr/container/src', + ), + 'Psr\\Cache\\' => + array ( + 0 => __DIR__ . '/..' . '/psr/cache/src', + ), + 'PhpMyAdmin\\MoTranslator\\' => + array ( + 0 => __DIR__ . '/..' . '/phpmyadmin/motranslator/src', + ), + ); + + public static $classMap = array ( + 'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php', + '©' => __DIR__ . '/..' . '/symfony/cache/Traits/ValueWrapper.php', + ); + + public static function getInitializer(ClassLoader $loader) + { + return \Closure::bind(function () use ($loader) { + $loader->prefixLengthsPsr4 = ComposerStaticInitf0f23926796d6825a9caf18ca123a270::$prefixLengthsPsr4; + $loader->prefixDirsPsr4 = ComposerStaticInitf0f23926796d6825a9caf18ca123a270::$prefixDirsPsr4; + $loader->classMap = ComposerStaticInitf0f23926796d6825a9caf18ca123a270::$classMap; + + }, null, ClassLoader::class); + } +} diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json new file mode 100644 index 0000000..e309fbb --- /dev/null +++ b/vendor/composer/installed.json @@ -0,0 +1,709 @@ +{ + "packages": [ + { + "name": "phpmyadmin/motranslator", + "version": "5.3.1", + "version_normalized": "5.3.1.0", + "source": { + "type": "git", + "url": "https://github.com/phpmyadmin/motranslator.git", + "reference": "d03b4d9c608e7265091bf6decc05323d16c7c047" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpmyadmin/motranslator/zipball/d03b4d9c608e7265091bf6decc05323d16c7c047", + "reference": "d03b4d9c608e7265091bf6decc05323d16c7c047", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0", + "symfony/expression-language": "^4.0 || ^5.0 || ^6.0" + }, + "require-dev": { + "phpmyadmin/coding-standard": "^3.0.0", + "phpstan/phpstan": "^1.4.6", + "phpunit/phpunit": "^7.4 || ^8 || ^9" + }, + "suggest": { + "ext-apcu": "Needed for ACPu-backed translation cache" + }, + "time": "2023-08-23T18:32:07+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "PhpMyAdmin\\MoTranslator\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0-or-later" + ], + "authors": [ + { + "name": "The phpMyAdmin Team", + "email": "developers@phpmyadmin.net", + "homepage": "https://www.phpmyadmin.net/team/" + } + ], + "description": "Translation API for PHP using Gettext MO files", + "homepage": "https://github.com/phpmyadmin/motranslator", + "keywords": [ + "gettext", + "i18n", + "mo", + "translator" + ], + "support": { + "issues": "https://github.com/phpmyadmin/motranslator/issues", + "source": "https://github.com/phpmyadmin/motranslator" + }, + "install-path": "../phpmyadmin/motranslator" + }, + { + "name": "psr/cache", + "version": "3.0.0", + "version_normalized": "3.0.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/cache.git", + "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/cache/zipball/aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", + "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "time": "2021-02-03T23:26:27+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Psr\\Cache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for caching libraries", + "keywords": [ + "cache", + "psr", + "psr-6" + ], + "support": { + "source": "https://github.com/php-fig/cache/tree/3.0.0" + }, + "install-path": "../psr/cache" + }, + { + "name": "psr/container", + "version": "2.0.2", + "version_normalized": "2.0.2.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "shasum": "" + }, + "require": { + "php": ">=7.4.0" + }, + "time": "2021-11-05T16:47:00+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/2.0.2" + }, + "install-path": "../psr/container" + }, + { + "name": "psr/log", + "version": "3.0.2", + "version_normalized": "3.0.2.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "time": "2024-09-11T13:17:53+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Psr\\Log\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "support": { + "source": "https://github.com/php-fig/log/tree/3.0.2" + }, + "install-path": "../psr/log" + }, + { + "name": "symfony/cache", + "version": "v7.2.1", + "version_normalized": "7.2.1.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/cache.git", + "reference": "e7e983596b744c4539f31e79b0350a6cf5878a20" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/cache/zipball/e7e983596b744c4539f31e79b0350a6cf5878a20", + "reference": "e7e983596b744c4539f31e79b0350a6cf5878a20", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "psr/cache": "^2.0|^3.0", + "psr/log": "^1.1|^2|^3", + "symfony/cache-contracts": "^2.5|^3", + "symfony/deprecation-contracts": "^2.5|^3.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/var-exporter": "^6.4|^7.0" + }, + "conflict": { + "doctrine/dbal": "<3.6", + "symfony/dependency-injection": "<6.4", + "symfony/http-kernel": "<6.4", + "symfony/var-dumper": "<6.4" + }, + "provide": { + "psr/cache-implementation": "2.0|3.0", + "psr/simple-cache-implementation": "1.0|2.0|3.0", + "symfony/cache-implementation": "1.1|2.0|3.0" + }, + "require-dev": { + "cache/integration-tests": "dev-master", + "doctrine/dbal": "^3.6|^4", + "predis/predis": "^1.1|^2.0", + "psr/simple-cache": "^1.0|^2.0|^3.0", + "symfony/clock": "^6.4|^7.0", + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/filesystem": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/messenger": "^6.4|^7.0", + "symfony/var-dumper": "^6.4|^7.0" + }, + "time": "2024-12-07T08:08:50+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\Cache\\": "" + }, + "classmap": [ + "Traits/ValueWrapper.php" + ], + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides extended PSR-6, PSR-16 (and tags) implementations", + "homepage": "https://symfony.com", + "keywords": [ + "caching", + "psr6" + ], + "support": { + "source": "https://github.com/symfony/cache/tree/v7.2.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "install-path": "../symfony/cache" + }, + { + "name": "symfony/cache-contracts", + "version": "v3.5.1", + "version_normalized": "3.5.1.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/cache-contracts.git", + "reference": "15a4f8e5cd3bce9aeafc882b1acab39ec8de2c1b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/15a4f8e5cd3bce9aeafc882b1acab39ec8de2c1b", + "reference": "15a4f8e5cd3bce9aeafc882b1acab39ec8de2c1b", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/cache": "^3.0" + }, + "time": "2024-09-25T14:20:29+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Cache\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to caching", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/cache-contracts/tree/v3.5.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "install-path": "../symfony/cache-contracts" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v3.5.1", + "version_normalized": "3.5.1.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", + "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "time": "2024-09-25T14:20:29+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "installation-source": "dist", + "autoload": { + "files": [ + "function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "install-path": "../symfony/deprecation-contracts" + }, + { + "name": "symfony/expression-language", + "version": "v6.4.13", + "version_normalized": "6.4.13.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/expression-language.git", + "reference": "3524904fb026356a5230cd197f9a4e6a61e0e7df" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/expression-language/zipball/3524904fb026356a5230cd197f9a4e6a61e0e7df", + "reference": "3524904fb026356a5230cd197f9a4e6a61e0e7df", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/cache": "^5.4|^6.0|^7.0", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/service-contracts": "^2.5|^3" + }, + "time": "2024-10-09T08:40:40+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\ExpressionLanguage\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an engine that can compile and evaluate expressions", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/expression-language/tree/v6.4.13" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "install-path": "../symfony/expression-language" + }, + { + "name": "symfony/service-contracts", + "version": "v3.5.1", + "version_normalized": "3.5.1.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/e53260aabf78fb3d63f8d79d69ece59f80d5eda0", + "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "time": "2024-09-25T14:20:29+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/service-contracts/tree/v3.5.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "install-path": "../symfony/service-contracts" + }, + { + "name": "symfony/var-exporter", + "version": "v7.2.0", + "version_normalized": "7.2.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-exporter.git", + "reference": "1a6a89f95a46af0f142874c9d650a6358d13070d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/1a6a89f95a46af0f142874c9d650a6358d13070d", + "reference": "1a6a89f95a46af0f142874c9d650a6358d13070d", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "symfony/property-access": "^6.4|^7.0", + "symfony/serializer": "^6.4|^7.0", + "symfony/var-dumper": "^6.4|^7.0" + }, + "time": "2024-10-18T07:58:17+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\VarExporter\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Allows exporting any serializable PHP data structure to plain PHP code", + "homepage": "https://symfony.com", + "keywords": [ + "clone", + "construct", + "export", + "hydrate", + "instantiate", + "lazy-loading", + "proxy", + "serialize" + ], + "support": { + "source": "https://github.com/symfony/var-exporter/tree/v7.2.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "install-path": "../symfony/var-exporter" + } + ], + "dev": true, + "dev-package-names": [] +} diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php new file mode 100644 index 0000000..d3fbad4 --- /dev/null +++ b/vendor/composer/installed.php @@ -0,0 +1,131 @@ + array( + 'name' => '__root__', + 'pretty_version' => 'dev-master', + 'version' => 'dev-master', + 'reference' => '4c22f27eb63b45502b3a4a42004e6d40d7da55a3', + 'type' => 'library', + 'install_path' => __DIR__ . '/../../', + 'aliases' => array(), + 'dev' => true, + ), + 'versions' => array( + '__root__' => array( + 'pretty_version' => 'dev-master', + 'version' => 'dev-master', + 'reference' => '4c22f27eb63b45502b3a4a42004e6d40d7da55a3', + 'type' => 'library', + 'install_path' => __DIR__ . '/../../', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'phpmyadmin/motranslator' => array( + 'pretty_version' => '5.3.1', + 'version' => '5.3.1.0', + 'reference' => 'd03b4d9c608e7265091bf6decc05323d16c7c047', + 'type' => 'library', + 'install_path' => __DIR__ . '/../phpmyadmin/motranslator', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'psr/cache' => array( + 'pretty_version' => '3.0.0', + 'version' => '3.0.0.0', + 'reference' => 'aa5030cfa5405eccfdcb1083ce040c2cb8d253bf', + 'type' => 'library', + 'install_path' => __DIR__ . '/../psr/cache', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'psr/cache-implementation' => array( + 'dev_requirement' => false, + 'provided' => array( + 0 => '2.0|3.0', + ), + ), + 'psr/container' => array( + 'pretty_version' => '2.0.2', + 'version' => '2.0.2.0', + 'reference' => 'c71ecc56dfe541dbd90c5360474fbc405f8d5963', + 'type' => 'library', + 'install_path' => __DIR__ . '/../psr/container', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'psr/log' => array( + 'pretty_version' => '3.0.2', + 'version' => '3.0.2.0', + 'reference' => 'f16e1d5863e37f8d8c2a01719f5b34baa2b714d3', + 'type' => 'library', + 'install_path' => __DIR__ . '/../psr/log', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'psr/simple-cache-implementation' => array( + 'dev_requirement' => false, + 'provided' => array( + 0 => '1.0|2.0|3.0', + ), + ), + 'symfony/cache' => array( + 'pretty_version' => 'v7.2.1', + 'version' => '7.2.1.0', + 'reference' => 'e7e983596b744c4539f31e79b0350a6cf5878a20', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/cache', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'symfony/cache-contracts' => array( + 'pretty_version' => 'v3.5.1', + 'version' => '3.5.1.0', + 'reference' => '15a4f8e5cd3bce9aeafc882b1acab39ec8de2c1b', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/cache-contracts', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'symfony/cache-implementation' => array( + 'dev_requirement' => false, + 'provided' => array( + 0 => '1.1|2.0|3.0', + ), + ), + 'symfony/deprecation-contracts' => array( + 'pretty_version' => 'v3.5.1', + 'version' => '3.5.1.0', + 'reference' => '74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/deprecation-contracts', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'symfony/expression-language' => array( + 'pretty_version' => 'v6.4.13', + 'version' => '6.4.13.0', + 'reference' => '3524904fb026356a5230cd197f9a4e6a61e0e7df', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/expression-language', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'symfony/service-contracts' => array( + 'pretty_version' => 'v3.5.1', + 'version' => '3.5.1.0', + 'reference' => 'e53260aabf78fb3d63f8d79d69ece59f80d5eda0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/service-contracts', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'symfony/var-exporter' => array( + 'pretty_version' => 'v7.2.0', + 'version' => '7.2.0.0', + 'reference' => '1a6a89f95a46af0f142874c9d650a6358d13070d', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/var-exporter', + 'aliases' => array(), + 'dev_requirement' => false, + ), + ), +); diff --git a/vendor/composer/platform_check.php b/vendor/composer/platform_check.php new file mode 100644 index 0000000..d32d90c --- /dev/null +++ b/vendor/composer/platform_check.php @@ -0,0 +1,26 @@ += 80200)) { + $issues[] = 'Your Composer dependencies require a PHP version ">= 8.2.0". You are running ' . PHP_VERSION . '.'; +} + +if ($issues) { + if (!headers_sent()) { + header('HTTP/1.1 500 Internal Server Error'); + } + if (!ini_get('display_errors')) { + if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') { + fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL); + } elseif (!headers_sent()) { + echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL; + } + } + trigger_error( + 'Composer detected issues in your platform: ' . implode(' ', $issues), + E_USER_ERROR + ); +} diff --git a/vendor/phpmyadmin/motranslator/CHANGELOG.md b/vendor/phpmyadmin/motranslator/CHANGELOG.md new file mode 100644 index 0000000..f5b5c34 --- /dev/null +++ b/vendor/phpmyadmin/motranslator/CHANGELOG.md @@ -0,0 +1,104 @@ +# Change Log + +## [5.3.1] - 2023-08-23 + +* Add function guards to the global functions (#44) + +## [5.3.0] - 2022-04-26 + +* Add support for Symfony 6 +* Split out `.mo` parsing to separate `MoParser` class +* Added `CacheInterface` so alternate cache implementations are pluggable +* Added `ApcuCache` implementation to leverage shared in-memory translation cache + +## [5.2.0] - 2021-02-05 + +* Fix "Translator::selectString() must be of the type integer, boolean returned" (#37) +* Fix "TypeError: StringReader::readintarray() ($count) must be of type int, float given" failing tests on ARM (#36) +* Add support for getting and setting all translations (#30) + +## [5.1.0] - 2020-11-15 + +* Allow PHPUnit 9 (#35) +* Fix some typos +* Sync config files +* Allow PHP 8.0 + +## [5.0.0] - 2020-02-28 + +* Drop support for PHP 5.3, PHP 5.4, PHP 5.5, PHP 5.6, PHP 7.0 and HHVM +* Enabled strict mode on PHP files +* Add support for Symfony 5 (#34) +* Add support for phpunit 8 +* Rename CHANGES.md to CHANGELOG.md and follow a standard format + +## [4.0] - 2018-02-12 + +* The library no longer changes system locales. + +## [3.4] - 2017-12-15 + +* Added Translator::setTranslation method. + +## [3.3] - 2017-06-01 + +* Add support for switching locales for Loader instance. + +## [3.2] - 2017-05-23 + +* Various fixes when handling corrupted mo files. + +## [3.1] - 2017-05-15 + +* Documentation improvements. + +## [3.0] - 2017-01-23 + +* All classes moved to the PhpMyAdmin namespace. + +## [2.2] - 2017-01-07 + +* Coding style cleanup. +* Avoid installing tests using composer. + +## [2.1] - 2016-12-21 + +* Various code cleanups. +* Added support for PHP 5.3. + +## [2.0] - 2016-10-13 + +* Consistently use camelCase in API. +* No more relies on using eval(). +* Depends on symfony/expression-language for calculations. + +## [1.2] - 2016-09-22 + +* Stricter validation of plural expression. + +## [1.1] - 2016-08-29 + +* Improved handling of corrupted mo files. +* Minor performance improvements. +* Stricter validation of plural expression. + +## [1.0] - 2016-04-27 + +* Documentation improvements. +* Testsuite improvements. + +## [0.4] - 2016-03-02 + +* Fixed test failures with hhvm due to broken putenv. + +## [0.3] - 2016-03-01 + +* Added Loader::detectlocale method. + +## [0.2] - 2016-02-24 + +* Marked PHP 5.4 and 5.5 as supported. + +## [0.1] - 2016-02-23 + +* Initial release. diff --git a/vendor/phpmyadmin/motranslator/CODE_OF_CONDUCT.md b/vendor/phpmyadmin/motranslator/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..4c40291 --- /dev/null +++ b/vendor/phpmyadmin/motranslator/CODE_OF_CONDUCT.md @@ -0,0 +1,76 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, sex characteristics, gender identity and expression, +level of experience, education, socio-economic status, nationality, personal +appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or + advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at info@phpmyadmin.net. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see +https://www.contributor-covenant.org/faq diff --git a/vendor/phpmyadmin/motranslator/CONTRIBUTING.md b/vendor/phpmyadmin/motranslator/CONTRIBUTING.md new file mode 100644 index 0000000..bbd7ffb --- /dev/null +++ b/vendor/phpmyadmin/motranslator/CONTRIBUTING.md @@ -0,0 +1,42 @@ +# Contributing to motranslator + +## Reporting issues + +Our issue tracker is hosted at GitHub: + +https://github.com/phpmyadmin/motranslator/issues + +Please search for existing issues before reporting new ones. + +## Working with Git checkout + +The dependencies are managed by Composer, to get them all installed (or update +on consequent runs) do: + +``` +composer update +``` + +## Submitting patches + +Please submit your patches using GitHub pull requests, this allows us to review +them and to run automated tests on the code. + +## Coding standards + +We do follow PSR-1 and PSR-2 coding standards. + +You can use phpcbf to fix the code to match our expectations: + +``` +composer run phpcbf +``` + +## Testsuite + +Our code comes with quite comprehensive testsuite, it is automatically executed +on every commit and pull request, you can also run it locally: + +``` +composer run phpunit +``` diff --git a/vendor/phpmyadmin/motranslator/LICENSE b/vendor/phpmyadmin/motranslator/LICENSE new file mode 100644 index 0000000..23cb790 --- /dev/null +++ b/vendor/phpmyadmin/motranslator/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + {description} + Copyright (C) {year} {fullname} + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + {signature of Ty Coon}, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/vendor/phpmyadmin/motranslator/PERFORMANCE.md b/vendor/phpmyadmin/motranslator/PERFORMANCE.md new file mode 100644 index 0000000..cd0f3e1 --- /dev/null +++ b/vendor/phpmyadmin/motranslator/PERFORMANCE.md @@ -0,0 +1,29 @@ +# Performance + +This library was tweaked for best performance for single use - translating +application with many strings using mo file. Current benchmarks show it's about +four times faster than original php-gettext. + +There are two benchmark scripts in the code: + +* ``benchmark-context.php`` - benchmarks context usage +* ``benchmark-plural.php`` - benchmarks plural evaluation +* ``benchmark.php`` - benchmarks file parsing +* ``benchmark-apcu.php`` - benchmarks file parsing with APCu cache enabled + +## Performance measurements + +The performance improvements based on individual changes in the code: + +| Stage | Seconds | +| -------------- | --------------- | +| Original code | 4.7929680347443 | +| Remove nocache | 4.6308250427246 | +| Direct endian | 4.5883052349091 | +| Remove attribs | 4.5297479629517 | +| String reader | 1.8148958683014 | +| No offset | 1.2436759471893 | +| Less attribs | 1.1722540855408 | +| Remove shift | 1.0970499515533 | +| Magic order | 1.0868430137634 | + diff --git a/vendor/phpmyadmin/motranslator/README.md b/vendor/phpmyadmin/motranslator/README.md new file mode 100644 index 0000000..1aea481 --- /dev/null +++ b/vendor/phpmyadmin/motranslator/README.md @@ -0,0 +1,242 @@ +# motranslator + +Translation API for PHP using Gettext MO files. + +![Test-suite](https://github.com/phpmyadmin/motranslator/workflows/Run%20tests/badge.svg?branch=master) +[![codecov.io](https://codecov.io/github/phpmyadmin/motranslator/coverage.svg?branch=master)](https://codecov.io/github/phpmyadmin/motranslator?branch=master) +[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/phpmyadmin/motranslator/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/phpmyadmin/motranslator/?branch=master) +[![Packagist](https://img.shields.io/packagist/dt/phpmyadmin/motranslator.svg)](https://packagist.org/packages/phpmyadmin/motranslator) + +## Features + +* All strings are stored in memory for fast lookup +* Fast loading of MO files +* Low level API for reading MO files +* Emulation of Gettext API +* No use of `eval()` for plural equation + +## Limitations + +* Default `InMemoryCache` not suitable for huge MO files which you don't want to store in memory +* Input and output encoding has to match (preferably UTF-8) + +## Installation + +Please use [Composer][1] to install: + +```sh +composer require phpmyadmin/motranslator +``` + +## Documentation + +The API documentation is available at . + +## Object API usage + +```php +// Create loader object +$loader = new PhpMyAdmin\MoTranslator\Loader(); + +// Set locale +$loader->setlocale('cs'); + +// Set default text domain +$loader->textdomain('domain'); + +// Set path where to look for a domain +$loader->bindtextdomain('domain', __DIR__ . '/data/locale/'); + +// Get translator +$translator = $loader->getTranslator(); + +// Now you can use Translator API (see below) +``` + +## Low level API usage + +```php +// Directly load the mo file +// You can use null to not load a file and the use a setter to set the translations +$cache = new PhpMyAdmin\MoTranslator\Cache\InMemoryCache(new PhpMyAdmin\MoTranslator\MoParser('./path/to/file.mo')); +$translator = new PhpMyAdmin\MoTranslator\Translator($cache); + +// Now you can use Translator API (see below) +``` + +## Translator API usage + +```php +// Translate string +echo $translator->gettext('String'); + +// Translate plural string +echo $translator->ngettext('String', 'Plural string', $count); + +// Translate string with context +echo $translator->pgettext('Context', 'String'); + +// Translate plural string with context +echo $translator->npgettext('Context', 'String', 'Plural string', $count); + +// Get the translations +echo $translator->getTranslations(); + +// All getters and setters below are more to be used if you are using a manual loading mode +// Example: $translator = new PhpMyAdmin\MoTranslator\Translator(null); + +// Set a translation +echo $translator->setTranslation('Test', 'Translation for "Test" key'); + +// Set translations +echo $translator->setTranslations([ + 'Test' => 'Translation for "Test" key', + 'Test 2' => 'Translation for "Test 2" key', +]); + +// Use the translation +echo $translator->gettext('Test 2'); // -> Translation for "Test 2" key +``` + +## Gettext compatibility usage + +```php +// Load compatibility layer +PhpMyAdmin\MoTranslator\Loader::loadFunctions(); + +// Configure +_setlocale(LC_MESSAGES, 'cs'); +_textdomain('phpmyadmin'); +_bindtextdomain('phpmyadmin', __DIR__ . '/data/locale/'); +_bind_textdomain_codeset('phpmyadmin', 'UTF-8'); + +// Use functions +echo _gettext('Type'); +echo __('Type'); + +// It also support other Gettext functions +_dnpgettext($domain, $msgctxt, $msgid, $msgidPlural, $number); +_dngettext($domain, $msgid, $msgidPlural, $number); +_npgettext($msgctxt, $msgid, $msgidPlural, $number); +_ngettext($msgid, $msgidPlural, $number); +_dpgettext($domain, $msgctxt, $msgid); +_dgettext($domain, $msgid); +_pgettext($msgctxt, $msgid); +``` + +## Using APCu-backed cache + +If you have the [APCu][5] extension installed you can use it for storing the translation cache. The `.mo` file +will then only be loaded once and all processes will share the same cache, reducing memory usage and resulting in +performance comparable to the native `gettext` extension. + +If you are using `Loader`, pass it an `ApcuCacheFactory` _before_ getting the translator instance: + +```php +PhpMyAdmin\MoTranslator\Loader::setCacheFactory( + new PhpMyAdmin\MoTranslator\Cache\AcpuCacheFactory() +); +$loader = new PhpMyAdmin\MoTranslator\Loader(); + +// Proceed as before +``` + +If you are using the low level API, instantiate the `ApcuCache` directly: + +```php +$cache = new PhpMyAdmin\MoTranslator\Cache\ApcuCache( + new PhpMyAdmin\MoTranslator\MoParser('./path/to/file.mo'), + 'de_DE', // the locale + 'phpmyadmin' // the domain +); +$translator = new PhpMyAdmin\MoTranslator\Translator($cache); + +// Proceed as before +``` + +By default, APCu will cache the translations until next server restart and prefix the cache entries with `mo_` to +avoid clashes with other cache entries. You can control this behaviour by passing `$ttl` and `$prefix` arguments, either +to the `ApcuCacheFactory` or when instantiating `ApcuCache`: + +```php +PhpMyAdmin\MoTranslator\Loader::setCacheFactory( + new PhpMyAdmin\MoTranslator\Cache\AcpuCacheFactory( + 3600, // cache for 1 hour + true, // reload on cache miss + 'custom_' // custom prefix for cache entries + ) +); +$loader = new PhpMyAdmin\MoTranslator\Loader(); + +// or... + +$cache = new PhpMyAdmin\MoTranslator\Cache\ApcuCache( + new PhpMyAdmin\MoTranslator\MoParser('./path/to/file.mo'), + 'de_DE', + 'phpmyadmin', + 3600, // cache for 1 hour + true, // reload on cache miss + 'custom_' // custom prefix for cache entries +); +$translator = new PhpMyAdmin\MoTranslator\Translator($cache); +``` + +If you receive updated translation files you can load them without restarting the server using the low-level API: + +```php +$parser = new PhpMyAdmin\MoTranslator\MoParser('./path/to/file.mo'); +$cache = new PhpMyAdmin\MoTranslator\Cache\ApcuCache($parser, 'de_DE', 'phpmyadmin'); +$parser->parseIntoCache($cache); +``` + +You should ensure APCu has enough memory to store all your translations, along with any other entries you use it +for. If an entry is evicted from cache, the `.mo` file will be re-parsed, impacting performance. See the +`apc.shm_size` and `apc.shm_segments` [documentation][6] and monitor cache usage when first rolling out. + +If your `.mo` files are missing lots of translations, the first time a missing entry is requested the `.mo` file +will be re-parsed. Again, this will impact performance until all the missing entries are hit once. You can turn off this +behaviour by setting the `$reloadOnMiss` argument to `false`. If you do this it is _critical_ that APCu has enough +memory, or users will see untranslated text when entries are evicted. + +## History + +This library is based on [php-gettext][2]. It adds some performance +improvements and ability to install using [Composer][1]. + +## Motivation + +Motivation for this library includes: + +* The [php-gettext][2] library is not maintained anymore +* It doesn't work with recent PHP version (phpMyAdmin has patched version) +* It relies on `eval()` function for plural equations what can have severe security implications, see [CVE-2016-6175][4] +* It's not possible to install it using [Composer][1] +* There was place for performance improvements in the library + +### Why not to use native gettext in PHP? + +We've tried that, but it's not a viable solution: + +* You can not use locales not known to system, what is something you can not + control from web application. This gets even more tricky with minimalist + virtualisation containers. +* Changing the MO file usually leads to PHP segmentation fault. It (or rather + Gettext library) caches headers of MO file and if it's content is changed + (for example new version is uploaded to server) it tries to access new data + with old references. This is bug known for ages: + https://bugs.php.net/bug.php?id=45943 + +### Why use Gettext and not JSON, YAML or whatever? + +We want translators to be able to use their favorite tools and we want us to be +able to use wide range of tools available with Gettext as well such as +[web based translation using Weblate][3]. Using custom format usually adds +another barrier for translators and we want to make it easy for them to +contribute. + +[1]:https://getcomposer.org/ +[2]:https://launchpad.net/php-gettext +[3]:https://weblate.org/ +[4]: https://www.cve.org/CVERecord?id=CVE-2016-6175 +[5]:https://www.php.net/manual/en/book.apcu.php +[6]:https://www.php.net/manual/en/apcu.configuration.php diff --git a/vendor/phpmyadmin/motranslator/benchmark-apcu.php b/vendor/phpmyadmin/motranslator/benchmark-apcu.php new file mode 100644 index 0000000..90ef494 --- /dev/null +++ b/vendor/phpmyadmin/motranslator/benchmark-apcu.php @@ -0,0 +1,29 @@ + './tests/data/big.mo', + 'little' => './tests/data/little.mo', +]; + +$start = microtime(true); + +for ($i = 0; $i < 2000; ++$i) { + foreach ($files as $domain => $filename) { + $translator = new PhpMyAdmin\MoTranslator\Translator( + new PhpMyAdmin\MoTranslator\Cache\ApcuCache( + new PhpMyAdmin\MoTranslator\MoParser($filename), 'foo', $domain + ) + ); + $translator->gettext('Column'); + } +} + +$end = microtime(true); + +$diff = $end - $start; + +echo 'Execution took ' . $diff . ' seconds' . "\n"; diff --git a/vendor/phpmyadmin/motranslator/composer.json b/vendor/phpmyadmin/motranslator/composer.json new file mode 100644 index 0000000..2536f58 --- /dev/null +++ b/vendor/phpmyadmin/motranslator/composer.json @@ -0,0 +1,56 @@ +{ + "name": "phpmyadmin/motranslator", + "description": "Translation API for PHP using Gettext MO files", + "license": "GPL-2.0-or-later", + "keywords": ["gettext", "mo", "translator", "i18n"], + "homepage": "https://github.com/phpmyadmin/motranslator", + "authors": [ + { + "name": "The phpMyAdmin Team", + "email": "developers@phpmyadmin.net", + "homepage": "https://www.phpmyadmin.net/team/" + } + ], + "support": { + "issues": "https://github.com/phpmyadmin/motranslator/issues", + "source": "https://github.com/phpmyadmin/motranslator" + }, + "scripts": { + "phpcbf": "@php phpcbf", + "phpcs": "@php phpcs", + "phpstan": "@php phpstan", + "phpunit": "@php phpunit", + "test": [ + "@phpcs", + "@phpstan", + "@phpunit" + ] + }, + "require": { + "php": "^7.1 || ^8.0", + "symfony/expression-language": "^4.0 || ^5.0 || ^6.0" + }, + "require-dev": { + "phpunit/phpunit": "^7.4 || ^8 || ^9", + "phpmyadmin/coding-standard": "^3.0.0", + "phpstan/phpstan": "^1.4.6" + }, + "autoload": { + "psr-4": { + "PhpMyAdmin\\MoTranslator\\": "src" + } + }, + "autoload-dev": { + "psr-4": { + "PhpMyAdmin\\MoTranslator\\Tests\\": "tests" + } + }, + "config": { + "allow-plugins": { + "dealerdirect/phpcodesniffer-composer-installer": true + } + }, + "suggest": { + "ext-apcu": "Needed for ACPu-backed translation cache" + } +} diff --git a/vendor/phpmyadmin/motranslator/phpunit.xml.dist b/vendor/phpmyadmin/motranslator/phpunit.xml.dist new file mode 100644 index 0000000..d49892d --- /dev/null +++ b/vendor/phpmyadmin/motranslator/phpunit.xml.dist @@ -0,0 +1,31 @@ + + + + + + + + ./tests + + + + + src/ + + + + + + + + diff --git a/vendor/phpmyadmin/motranslator/src/Cache/ApcuCache.php b/vendor/phpmyadmin/motranslator/src/Cache/ApcuCache.php new file mode 100644 index 0000000..43b957e --- /dev/null +++ b/vendor/phpmyadmin/motranslator/src/Cache/ApcuCache.php @@ -0,0 +1,136 @@ +parser = $parser; + $this->locale = $locale; + $this->domain = $domain; + $this->ttl = $ttl; + $this->reloadOnMiss = $reloadOnMiss; + $this->prefix = $prefix; + + $this->ensureTranslationsLoaded(); + } + + public function get(string $msgid): string + { + $msgstr = apcu_fetch($this->getKey($msgid), $success); + if ($success && is_string($msgstr)) { + return $msgstr; + } + + if (! $this->reloadOnMiss) { + return $msgid; + } + + return $this->reloadOnMiss($msgid); + } + + private function reloadOnMiss(string $msgid): string + { + // store original if translation is not present + $cached = apcu_entry($this->getKey($msgid), static function () use ($msgid) { + return $msgid; + }, $this->ttl); + // if another process has updated cache, return early + if ($cached !== $msgid && is_string($cached)) { + return $cached; + } + + // reload .mo file, in case entry has been evicted + $this->parser->parseIntoCache($this); + + $msgstr = apcu_fetch($this->getKey($msgid), $success); + + return $success && is_string($msgstr) ? $msgstr : $msgid; + } + + public function set(string $msgid, string $msgstr): void + { + apcu_store($this->getKey($msgid), $msgstr, $this->ttl); + } + + public function has(string $msgid): bool + { + return apcu_exists($this->getKey($msgid)); + } + + public function setAll(array $translations): void + { + $keys = array_map(function (string $msgid): string { + return $this->getKey($msgid); + }, array_keys($translations)); + $translations = array_combine($keys, $translations); + assert(is_array($translations)); + + apcu_store($translations, null, $this->ttl); + } + + private function getKey(string $msgid): string + { + return $this->prefix . $this->locale . '.' . $this->domain . '.' . $msgid; + } + + private function ensureTranslationsLoaded(): void + { + // Try to prevent cache slam if multiple processes are trying to load translations. There is still a race + // between the exists check and creating the entry, but at least it's small + $key = $this->getKey(self::LOADED_KEY); + $loaded = apcu_exists($key) || apcu_entry($key, static function (): int { + return 0; + }, $this->ttl); + if ($loaded) { + return; + } + + $this->parser->parseIntoCache($this); + apcu_store($this->getKey(self::LOADED_KEY), 1, $this->ttl); + } +} diff --git a/vendor/phpmyadmin/motranslator/src/Cache/ApcuCacheFactory.php b/vendor/phpmyadmin/motranslator/src/Cache/ApcuCacheFactory.php new file mode 100644 index 0000000..e30540d --- /dev/null +++ b/vendor/phpmyadmin/motranslator/src/Cache/ApcuCacheFactory.php @@ -0,0 +1,29 @@ +ttl = $ttl; + $this->reloadOnMiss = $reloadOnMiss; + $this->prefix = $prefix; + } + + public function getInstance(MoParser $parser, string $locale, string $domain): CacheInterface + { + return new ApcuCache($parser, $locale, $domain, $this->ttl, $this->reloadOnMiss, $this->prefix); + } +} diff --git a/vendor/phpmyadmin/motranslator/src/Cache/CacheFactoryInterface.php b/vendor/phpmyadmin/motranslator/src/Cache/CacheFactoryInterface.php new file mode 100644 index 0000000..5e3fc3f --- /dev/null +++ b/vendor/phpmyadmin/motranslator/src/Cache/CacheFactoryInterface.php @@ -0,0 +1,12 @@ + $msgstr` entries + * + * This will overwrite existing values for `$msgid`, but is not guaranteed to clear cache of existing entries + * not present in `$translations`. + * + * @param array $translations + */ + public function setAll(array $translations): void; +} diff --git a/vendor/phpmyadmin/motranslator/src/Cache/GetAllInterface.php b/vendor/phpmyadmin/motranslator/src/Cache/GetAllInterface.php new file mode 100644 index 0000000..c391438 --- /dev/null +++ b/vendor/phpmyadmin/motranslator/src/Cache/GetAllInterface.php @@ -0,0 +1,13 @@ + + */ + public function getAll(): array; +} diff --git a/vendor/phpmyadmin/motranslator/src/Cache/InMemoryCache.php b/vendor/phpmyadmin/motranslator/src/Cache/InMemoryCache.php new file mode 100644 index 0000000..bf7bc1d --- /dev/null +++ b/vendor/phpmyadmin/motranslator/src/Cache/InMemoryCache.php @@ -0,0 +1,49 @@ + */ + private $cache; + + public function __construct(MoParser $parser) + { + $this->cache = []; + $parser->parseIntoCache($this); + } + + public function get(string $msgid): string + { + return array_key_exists($msgid, $this->cache) ? $this->cache[$msgid] : $msgid; + } + + public function set(string $msgid, string $msgstr): void + { + $this->cache[$msgid] = $msgstr; + } + + public function has(string $msgid): bool + { + return array_key_exists($msgid, $this->cache); + } + + public function setAll(array $translations): void + { + $this->cache = $translations; + } + + /** + * @inheritDoc + */ + public function getAll(): array + { + return $this->cache; + } +} diff --git a/vendor/phpmyadmin/motranslator/src/CacheException.php b/vendor/phpmyadmin/motranslator/src/CacheException.php new file mode 100644 index 0000000..aa37fae --- /dev/null +++ b/vendor/phpmyadmin/motranslator/src/CacheException.php @@ -0,0 +1,11 @@ + + Copyright (c) 2009 Danilo Segan + Copyright (c) 2016 Michal Čihař + + This file is part of MoTranslator. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +namespace PhpMyAdmin\MoTranslator; + +use PhpMyAdmin\MoTranslator\Cache\CacheFactoryInterface; +use PhpMyAdmin\MoTranslator\Cache\InMemoryCache; + +use function array_push; +use function file_exists; +use function getenv; +use function in_array; +use function preg_match; +use function sprintf; + +class Loader +{ + /** + * Loader instance. + * + * @static + * @var Loader + */ + private static $instance = null; + + /** + * Factory to return a factory responsible for returning a `CacheInterface` + * + * @static + * @var CacheFactoryInterface|null + */ + private static $cacheFactory = null; + + /** + * Default gettext domain to use. + * + * @var string + */ + private $defaultDomain = ''; + + /** + * Configured locale. + * + * @var string + */ + private $locale = ''; + + /** + * Loaded domains. + * + * @var array> + */ + private $domains = []; + + /** + * Bound paths for domains. + * + * @var array + */ + private $paths = ['' => './']; + + /** + * Returns the singleton Loader object. + * + * @return Loader object + */ + public static function getInstance(): Loader + { + if (self::$instance === null) { + self::$instance = new self(); + } + + return self::$instance; + } + + /** + * Loads global localization functions. + */ + public static function loadFunctions(): void + { + require_once __DIR__ . '/functions.php'; + } + + /** + * Figure out all possible locale names and start with the most + * specific ones. I.e. for sr_CS.UTF-8@latin, look through all of + * sr_CS.UTF-8@latin, sr_CS@latin, sr@latin, sr_CS.UTF-8, sr_CS, sr. + * + * @param string $locale Locale code + * + * @return string[] list of locales to try for any POSIX-style locale specification + */ + public static function listLocales(string $locale): array + { + $localeNames = []; + + if ($locale) { + if ( + preg_match( + '/^(?P[a-z]{2,3})' // language code + . '(?:_(?P[A-Z]{2}))?' // country code + . '(?:\\.(?P[-A-Za-z0-9_]+))?' // charset + . '(?:@(?P[-A-Za-z0-9_]+))?$/', // @ modifier + $locale, + $matches + ) + ) { + $lang = $matches['lang'] ?? null; + $country = $matches['country'] ?? null; + $charset = $matches['charset'] ?? null; + $modifier = $matches['modifier'] ?? null; + + if ($modifier) { + if ($country) { + if ($charset) { + array_push( + $localeNames, + sprintf('%s_%s.%s@%s', $lang, $country, $charset, $modifier) + ); + } + + array_push( + $localeNames, + sprintf('%s_%s@%s', $lang, $country, $modifier) + ); + } elseif ($charset) { + array_push( + $localeNames, + sprintf('%s.%s@%s', $lang, $charset, $modifier) + ); + } + + array_push( + $localeNames, + sprintf('%s@%s', $lang, $modifier) + ); + } + + if ($country) { + if ($charset) { + array_push( + $localeNames, + sprintf('%s_%s.%s', $lang, $country, $charset) + ); + } + + array_push( + $localeNames, + sprintf('%s_%s', $lang, $country) + ); + } elseif ($charset) { + array_push( + $localeNames, + sprintf('%s.%s', $lang, $charset) + ); + } + + array_push($localeNames, $lang); + } + + // If the locale name doesn't match POSIX style, just include it as-is. + if (! in_array($locale, $localeNames)) { + array_push($localeNames, $locale); + } + } + + return $localeNames; + } + + /** + * Sets factory responsible for composing a `CacheInterface` + */ + public static function setCacheFactory(?CacheFactoryInterface $cacheFactory): void + { + self::$cacheFactory = $cacheFactory; + } + + /** + * Returns Translator object for domain or for default domain. + * + * @param string $domain Translation domain + */ + public function getTranslator(string $domain = ''): Translator + { + if (empty($domain)) { + $domain = $this->defaultDomain; + } + + if (! isset($this->domains[$this->locale])) { + $this->domains[$this->locale] = []; + } + + if (! isset($this->domains[$this->locale][$domain])) { + if (isset($this->paths[$domain])) { + $base = $this->paths[$domain]; + } else { + $base = './'; + } + + $localeNames = $this->listLocales($this->locale); + + $filename = ''; + foreach ($localeNames as $locale) { + $filename = $base . '/' . $locale . '/LC_MESSAGES/' . $domain . '.mo'; + if (file_exists($filename)) { + break; + } + } + + // We don't care about invalid path, we will get fallback + // translator here + $moParser = new MoParser($filename); + if (self::$cacheFactory instanceof CacheFactoryInterface) { + $cache = self::$cacheFactory->getInstance($moParser, $this->locale, $domain); + } else { + $cache = new InMemoryCache($moParser); + } + + $this->domains[$this->locale][$domain] = new Translator($cache); + } + + return $this->domains[$this->locale][$domain]; + } + + /** + * Sets the path for a domain. + * + * @param string $domain Domain name + * @param string $path Path where to find locales + */ + public function bindtextdomain(string $domain, string $path): void + { + $this->paths[$domain] = $path; + } + + /** + * Sets the default domain. + * + * @param string $domain Domain name + */ + public function textdomain(string $domain): void + { + $this->defaultDomain = $domain; + } + + /** + * Sets a requested locale. + * + * @param string $locale Locale name + * + * @return string Set or current locale + */ + public function setlocale(string $locale): string + { + if (! empty($locale)) { + $this->locale = $locale; + } + + return $this->locale; + } + + /** + * Detects currently configured locale. + * + * It checks: + * + * - global lang variable + * - environment for LC_ALL, LC_MESSAGES and LANG + * + * @return string with locale name + */ + public function detectlocale(): string + { + if (isset($GLOBALS['lang'])) { + return $GLOBALS['lang']; + } + + $locale = getenv('LC_ALL'); + if ($locale !== false) { + return $locale; + } + + $locale = getenv('LC_MESSAGES'); + if ($locale !== false) { + return $locale; + } + + $locale = getenv('LANG'); + if ($locale !== false) { + return $locale; + } + + return 'en'; + } +} diff --git a/vendor/phpmyadmin/motranslator/src/MoParser.php b/vendor/phpmyadmin/motranslator/src/MoParser.php new file mode 100644 index 0000000..ff176ed --- /dev/null +++ b/vendor/phpmyadmin/motranslator/src/MoParser.php @@ -0,0 +1,109 @@ +filename = $filename; + } + + /** + * Parses .mo file and stores results to `$cache` + */ + public function parseIntoCache(CacheInterface $cache): void + { + if ($this->filename === null) { + return; + } + + if (! is_readable($this->filename)) { + $this->error = self::ERROR_DOES_NOT_EXIST; + + return; + } + + $stream = new StringReader($this->filename); + + try { + $magic = $stream->read(0, 4); + if (strcmp($magic, self::MAGIC_LE) === 0) { + $unpack = 'V'; + } elseif (strcmp($magic, self::MAGIC_BE) === 0) { + $unpack = 'N'; + } else { + $this->error = self::ERROR_BAD_MAGIC; + + return; + } + + /* Parse header */ + $total = $stream->readint($unpack, 8); + $originals = $stream->readint($unpack, 12); + $translations = $stream->readint($unpack, 16); + + /* get original and translations tables */ + $totalTimesTwo = (int) ($total * 2);// Fix for issue #36 on ARM + $tableOriginals = $stream->readintarray($unpack, $originals, $totalTimesTwo); + $tableTranslations = $stream->readintarray($unpack, $translations, $totalTimesTwo); + + /* read all strings to the cache */ + for ($i = 0; $i < $total; ++$i) { + $iTimesTwo = $i * 2; + $iPlusOne = $iTimesTwo + 1; + $iPlusTwo = $iTimesTwo + 2; + $original = $stream->read($tableOriginals[$iPlusTwo], $tableOriginals[$iPlusOne]); + $translation = $stream->read($tableTranslations[$iPlusTwo], $tableTranslations[$iPlusOne]); + $cache->set($original, $translation); + } + } catch (ReaderException $e) { + $this->error = self::ERROR_READING; + + return; + } + } +} diff --git a/vendor/phpmyadmin/motranslator/src/ReaderException.php b/vendor/phpmyadmin/motranslator/src/ReaderException.php new file mode 100644 index 0000000..3c06394 --- /dev/null +++ b/vendor/phpmyadmin/motranslator/src/ReaderException.php @@ -0,0 +1,35 @@ +. + Copyright (c) 2016 Michal Čihař + + This file is part of MoTranslator. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +namespace PhpMyAdmin\MoTranslator; + +use Exception; + +/** + * Exception thrown when file can not be read. + */ +class ReaderException extends Exception +{ +} diff --git a/vendor/phpmyadmin/motranslator/src/StringReader.php b/vendor/phpmyadmin/motranslator/src/StringReader.php new file mode 100644 index 0000000..a40a9f6 --- /dev/null +++ b/vendor/phpmyadmin/motranslator/src/StringReader.php @@ -0,0 +1,116 @@ +. + Copyright (c) 2016 Michal Čihař + + This file is part of MoTranslator. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +namespace PhpMyAdmin\MoTranslator; + +use function file_get_contents; +use function strlen; +use function substr; +use function unpack; + +use const PHP_INT_MAX; + +/** + * Simple wrapper around string buffer for + * random access and values parsing. + */ +class StringReader +{ + /** @var string */ + private $string; + /** @var int */ + private $length; + + /** + * @param string $filename Name of file to load + */ + public function __construct(string $filename) + { + $this->string = (string) file_get_contents($filename); + $this->length = strlen($this->string); + } + + /** + * Read number of bytes from given offset. + * + * @param int $pos Offset + * @param int $bytes Number of bytes to read + */ + public function read(int $pos, int $bytes): string + { + if ($pos + $bytes > $this->length) { + throw new ReaderException('Not enough bytes!'); + } + + $data = substr($this->string, $pos, $bytes); + + return $data === false ? '' : $data; + } + + /** + * Reads a 32bit integer from the stream. + * + * @param string $unpack Unpack string + * @param int $pos Position + * + * @return int Integer from the stream + */ + public function readint(string $unpack, int $pos): int + { + $data = unpack($unpack, $this->read($pos, 4)); + if ($data === false) { + return PHP_INT_MAX; + } + + $result = $data[1]; + + /* We're reading unsigned int, but PHP will happily + * give us negative number on 32-bit platforms. + * + * See also documentation: + * https://secure.php.net/manual/en/function.unpack.php#refsect1-function.unpack-notes + */ + return $result < 0 ? PHP_INT_MAX : $result; + } + + /** + * Reads an array of integers from the stream. + * + * @param string $unpack Unpack string + * @param int $pos Position + * @param int $count How many elements should be read + * + * @return int[] Array of Integers + */ + public function readintarray(string $unpack, int $pos, int $count): array + { + $data = unpack($unpack . $count, $this->read($pos, 4 * $count)); + if ($data === false) { + return []; + } + + return $data; + } +} diff --git a/vendor/phpmyadmin/motranslator/src/Translator.php b/vendor/phpmyadmin/motranslator/src/Translator.php new file mode 100644 index 0000000..bb423cf --- /dev/null +++ b/vendor/phpmyadmin/motranslator/src/Translator.php @@ -0,0 +1,388 @@ +. + Copyright (c) 2005 Nico Kaiser + Copyright (c) 2016 Michal Čihař + + This file is part of MoTranslator. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +namespace PhpMyAdmin\MoTranslator; + +use PhpMyAdmin\MoTranslator\Cache\CacheInterface; +use PhpMyAdmin\MoTranslator\Cache\GetAllInterface; +use PhpMyAdmin\MoTranslator\Cache\InMemoryCache; +use Symfony\Component\ExpressionLanguage\ExpressionLanguage; +use Throwable; + +use function chr; +use function count; +use function explode; +use function get_class; +use function implode; +use function intval; +use function ltrim; +use function preg_replace; +use function rtrim; +use function sprintf; +use function stripos; +use function strpos; +use function strtolower; +use function substr; +use function trim; + +/** + * Provides a simple gettext replacement that works independently from + * the system's gettext abilities. + * It can read MO files and use them for translating strings. + * + * It caches ll strings and translations to speed up the string lookup. + */ +class Translator +{ + /** + * None error. + */ + public const ERROR_NONE = 0; + /** + * File does not exist. + */ + public const ERROR_DOES_NOT_EXIST = 1; + /** + * File has bad magic number. + */ + public const ERROR_BAD_MAGIC = 2; + /** + * Error while reading file, probably too short. + */ + public const ERROR_READING = 3; + + /** + * Big endian mo file magic bytes. + */ + public const MAGIC_BE = "\x95\x04\x12\xde"; + /** + * Little endian mo file magic bytes. + */ + public const MAGIC_LE = "\xde\x12\x04\x95"; + + /** + * Parse error code (0 if no error). + * + * @var int + */ + public $error = self::ERROR_NONE; + + /** + * Cache header field for plural forms. + * + * @var string|null + */ + private $pluralEquation = null; + + /** @var ExpressionLanguage|null Evaluator for plurals */ + private $pluralExpression = null; + + /** @var int|null number of plurals */ + private $pluralCount = null; + + /** @var CacheInterface */ + private $cache; + + /** + * @param CacheInterface|string|null $cache Mo file to load (null for no file) or a CacheInterface implementation + */ + public function __construct($cache) + { + if (! $cache instanceof CacheInterface) { + $cache = new InMemoryCache(new MoParser($cache)); + } + + $this->cache = $cache; + } + + /** + * Translates a string. + * + * @param string $msgid String to be translated + * + * @return string translated string (or original, if not found) + */ + public function gettext(string $msgid): string + { + return $this->cache->get($msgid); + } + + /** + * Check if a string is translated. + * + * @param string $msgid String to be checked + */ + public function exists(string $msgid): bool + { + return $this->cache->has($msgid); + } + + /** + * Sanitize plural form expression for use in ExpressionLanguage. + * + * @param string $expr Expression to sanitize + * + * @return string sanitized plural form expression + */ + public static function sanitizePluralExpression(string $expr): string + { + // Parse equation + $expr = explode(';', $expr); + if (count($expr) >= 2) { + $expr = $expr[1]; + } else { + $expr = $expr[0]; + } + + $expr = trim(strtolower($expr)); + // Strip plural prefix + if (substr($expr, 0, 6) === 'plural') { + $expr = ltrim(substr($expr, 6)); + } + + // Strip equals + if (substr($expr, 0, 1) === '=') { + $expr = ltrim(substr($expr, 1)); + } + + // Cleanup from unwanted chars + $expr = preg_replace('@[^n0-9:\(\)\?=!<>/%&| ]@', '', $expr); + + return (string) $expr; + } + + /** + * Extracts number of plurals from plurals form expression. + * + * @param string $expr Expression to process + * + * @return int Total number of plurals + */ + public static function extractPluralCount(string $expr): int + { + $parts = explode(';', $expr, 2); + $nplurals = explode('=', trim($parts[0]), 2); + if (strtolower(rtrim($nplurals[0])) !== 'nplurals') { + return 1; + } + + if (count($nplurals) === 1) { + return 1; + } + + return intval($nplurals[1]); + } + + /** + * Parse full PO header and extract only plural forms line. + * + * @param string $header Gettext header + * + * @return string verbatim plural form header field + */ + public static function extractPluralsForms(string $header): string + { + $headers = explode("\n", $header); + $expr = 'nplurals=2; plural=n == 1 ? 0 : 1;'; + foreach ($headers as $header) { + if (stripos($header, 'Plural-Forms:') !== 0) { + continue; + } + + $expr = substr($header, 13); + } + + return $expr; + } + + /** + * Get possible plural forms from MO header. + * + * @return string plural form header + */ + private function getPluralForms(): string + { + // lets assume message number 0 is header + // this is true, right? + + // cache header field for plural forms + if ($this->pluralEquation === null) { + $header = $this->cache->get(''); + + $expr = $this->extractPluralsForms($header); + $this->pluralEquation = $this->sanitizePluralExpression($expr); + $this->pluralCount = $this->extractPluralCount($expr); + } + + return $this->pluralEquation; + } + + /** + * Detects which plural form to take. + * + * @param int $n count of objects + * + * @return int array index of the right plural form + */ + private function selectString(int $n): int + { + if ($this->pluralExpression === null) { + $this->pluralExpression = new ExpressionLanguage(); + } + + try { + $plural = (int) $this->pluralExpression->evaluate( + $this->getPluralForms(), + ['n' => $n] + ); + } catch (Throwable $e) { + $plural = 0; + } + + if ($plural >= $this->pluralCount) { + $plural = $this->pluralCount - 1; + } + + return $plural; + } + + /** + * Plural version of gettext. + * + * @param string $msgid Single form + * @param string $msgidPlural Plural form + * @param int $number Number of objects + * + * @return string translated plural form + */ + public function ngettext(string $msgid, string $msgidPlural, int $number): string + { + // this should contains all strings separated by NULLs + $key = implode(chr(0), [$msgid, $msgidPlural]); + if (! $this->cache->has($key)) { + return $number !== 1 ? $msgidPlural : $msgid; + } + + $result = $this->cache->get($key); + + // find out the appropriate form + $select = $this->selectString($number); + + $list = explode(chr(0), $result); + // @codeCoverageIgnoreStart + if ($list === false) { + // This was added in 3ff2c63bcf85f81b3a205ce7222de11b33e2bf56 for phpstan + // But according to the php manual it should never happen + return ''; + } + + // @codeCoverageIgnoreEnd + + if (! isset($list[$select])) { + return $list[0]; + } + + return $list[$select]; + } + + /** + * Translate with context. + * + * @param string $msgctxt Context + * @param string $msgid String to be translated + * + * @return string translated plural form + */ + public function pgettext(string $msgctxt, string $msgid): string + { + $key = implode(chr(4), [$msgctxt, $msgid]); + $ret = $this->gettext($key); + if (strpos($ret, chr(4)) !== false) { + return $msgid; + } + + return $ret; + } + + /** + * Plural version of pgettext. + * + * @param string $msgctxt Context + * @param string $msgid Single form + * @param string $msgidPlural Plural form + * @param int $number Number of objects + * + * @return string translated plural form + */ + public function npgettext(string $msgctxt, string $msgid, string $msgidPlural, int $number): string + { + $key = implode(chr(4), [$msgctxt, $msgid]); + $ret = $this->ngettext($key, $msgidPlural, $number); + if (strpos($ret, chr(4)) !== false) { + return $msgid; + } + + return $ret; + } + + /** + * Set translation in place + * + * @param string $msgid String to be set + * @param string $msgstr Translation + */ + public function setTranslation(string $msgid, string $msgstr): void + { + $this->cache->set($msgid, $msgstr); + } + + /** + * Set the translations + * + * @param array $translations The translations "key => value" array + */ + public function setTranslations(array $translations): void + { + $this->cache->setAll($translations); + } + + /** + * Get the translations + * + * @return array The translations "key => value" array + */ + public function getTranslations(): array + { + if ($this->cache instanceof GetAllInterface) { + return $this->cache->getAll(); + } + + throw new CacheException(sprintf( + "Cache '%s' does not support getting translations", + get_class($this->cache) + )); + } +} diff --git a/vendor/phpmyadmin/motranslator/src/functions.php b/vendor/phpmyadmin/motranslator/src/functions.php new file mode 100644 index 0000000..2ef8392 --- /dev/null +++ b/vendor/phpmyadmin/motranslator/src/functions.php @@ -0,0 +1,226 @@ + + Copyright (c) 2009 Danilo Segan + Copyright (c) 2016 Michal Čihař + + This file is part of MoTranslator. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +use PhpMyAdmin\MoTranslator\Loader; + +if (! function_exists('_setlocale')) { + /** + * Sets a requested locale. + * + * @param int $category Locale category, ignored + * @param string $locale Locale name + * + * @return string Set or current locale + */ + function _setlocale(int $category, string $locale): string + { + return Loader::getInstance()->setlocale($locale); + } +} + +if (! function_exists('_bindtextdomain')) { + /** + * Sets the path for a domain. + * + * @param string $domain Domain name + * @param string $path Path where to find locales + */ + function _bindtextdomain(string $domain, string $path): void + { + Loader::getInstance()->bindtextdomain($domain, $path); + } +} + +if (! function_exists('_bind_textdomain_codeset')) { + /** + * Dummy compatibility function, MoTranslator assumes + * everything is using same character set on input and + * output. + * + * Generally it is wise to output in UTF-8 and have + * mo files in UTF-8. + * + * @param string $domain Domain where to set character set + * @param string $codeset Character set to set + */ + function _bind_textdomain_codeset($domain, $codeset): void + { + } +} + +if (! function_exists('_textdomain')) { + /** + * Sets the default domain. + * + * @param string $domain Domain name + */ + function _textdomain(string $domain): void + { + Loader::getInstance()->textdomain($domain); + } +} + +if (! function_exists('_gettext')) { + /** + * Translates a string. + * + * @param string $msgid String to be translated + * + * @return string translated string (or original, if not found) + */ + function _gettext(string $msgid): string + { + return Loader::getInstance()->getTranslator()->gettext($msgid); + } +} + +if (! function_exists('__')) { + /** + * Translates a string, alias for _gettext. + * + * @param string $msgid String to be translated + * + * @return string translated string (or original, if not found) + */ + function __(string $msgid): string + { + return Loader::getInstance()->getTranslator()->gettext($msgid); + } +} + +if (! function_exists('_ngettext')) { + /** + * Plural version of gettext. + * + * @param string $msgid Single form + * @param string $msgidPlural Plural form + * @param int $number Number of objects + * + * @return string translated plural form + */ + function _ngettext(string $msgid, string $msgidPlural, int $number): string + { + return Loader::getInstance()->getTranslator()->ngettext($msgid, $msgidPlural, $number); + } +} + +if (! function_exists('_pgettext')) { + /** + * Translate with context. + * + * @param string $msgctxt Context + * @param string $msgid String to be translated + * + * @return string translated plural form + */ + function _pgettext(string $msgctxt, string $msgid): string + { + return Loader::getInstance()->getTranslator()->pgettext($msgctxt, $msgid); + } +} + +if (! function_exists('_npgettext')) { + /** + * Plural version of pgettext. + * + * @param string $msgctxt Context + * @param string $msgid Single form + * @param string $msgidPlural Plural form + * @param int $number Number of objects + * + * @return string translated plural form + */ + function _npgettext(string $msgctxt, string $msgid, string $msgidPlural, int $number): string + { + return Loader::getInstance()->getTranslator()->npgettext($msgctxt, $msgid, $msgidPlural, $number); + } +} + +if (! function_exists('_dgettext')) { + /** + * Translates a string. + * + * @param string $domain Domain to use + * @param string $msgid String to be translated + * + * @return string translated string (or original, if not found) + */ + function _dgettext(string $domain, string $msgid): string + { + return Loader::getInstance()->getTranslator($domain)->gettext($msgid); + } +} + +if (! function_exists('_dngettext')) { + /** + * Plural version of gettext. + * + * @param string $domain Domain to use + * @param string $msgid Single form + * @param string $msgidPlural Plural form + * @param int $number Number of objects + * + * @return string translated plural form + */ + function _dngettext(string $domain, string $msgid, string $msgidPlural, int $number): string + { + return Loader::getInstance()->getTranslator($domain)->ngettext($msgid, $msgidPlural, $number); + } +} + +if (! function_exists('_dpgettext')) { + /** + * Translate with context. + * + * @param string $domain Domain to use + * @param string $msgctxt Context + * @param string $msgid String to be translated + * + * @return string translated plural form + */ + function _dpgettext(string $domain, string $msgctxt, string $msgid): string + { + return Loader::getInstance()->getTranslator($domain)->pgettext($msgctxt, $msgid); + } +} + +if (! function_exists('_dnpgettext')) { + /** + * Plural version of pgettext. + * + * @param string $domain Domain to use + * @param string $msgctxt Context + * @param string $msgid Single form + * @param string $msgidPlural Plural form + * @param int $number Number of objects + * + * @return string translated plural form + */ + function _dnpgettext(string $domain, string $msgctxt, string $msgid, string $msgidPlural, int $number): string + { + return Loader::getInstance()->getTranslator($domain)->npgettext($msgctxt, $msgid, $msgidPlural, $number); + } +} diff --git a/vendor/phpmyadmin/motranslator/tests/Cache/ApcuCacheFactoryTest.php b/vendor/phpmyadmin/motranslator/tests/Cache/ApcuCacheFactoryTest.php new file mode 100644 index 0000000..b6262b1 --- /dev/null +++ b/vendor/phpmyadmin/motranslator/tests/Cache/ApcuCacheFactoryTest.php @@ -0,0 +1,98 @@ +markTestSkipped('ACPu extension is not installed and enabled for CLI'); + } + + protected function tearDown(): void + { + parent::tearDown(); + + apcu_clear_cache(); + } + + public function testGetInstanceReturnApcuCache(): void + { + $factory = new ApcuCacheFactory(); + $instance = $factory->getInstance(new MoParser(null), 'foo', 'bar'); + $this->assertInstanceOf(ApcuCache::class, $instance); + } + + public function testConstructorSetsTtl(): void + { + $locale = 'foo'; + $domain = 'bar'; + $msgid = 'Column'; + $ttl = 1; + + $factory = new ApcuCacheFactory($ttl); + $parser = new MoParser(__DIR__ . '/../data/little.mo'); + $factory->getInstance($parser, $locale, $domain); + sleep($ttl * 2); + + apcu_fetch('mo_' . $locale . '.' . $domain . '.' . $msgid, $success); + $this->assertFalse($success); + } + + public function testConstructorSetsReloadOnMiss(): void + { + $expected = 'Column'; + $locale = 'foo'; + $domain = 'bar'; + $msgid = 'Column'; + + $factory = new ApcuCacheFactory(0, false); + $parser = new MoParser(__DIR__ . '/../data/little.mo'); + + $instance = $factory->getInstance($parser, $locale, $domain); + + apcu_delete('mo_' . $locale . '.' . $domain . '.' . $msgid); + $actual = $instance->get($msgid); + $this->assertSame($expected, $actual); + } + + public function testConstructorSetsPrefix(): void + { + $expected = 'Pole'; + $locale = 'foo'; + $domain = 'bar'; + $msgid = 'Column'; + $prefix = 'baz_'; + + $factory = new ApcuCacheFactory(0, true, $prefix); + $parser = new MoParser(__DIR__ . '/../data/little.mo'); + + $factory->getInstance($parser, $locale, $domain); + + $actual = apcu_fetch($prefix . $locale . '.' . $domain . '.' . $msgid); + $this->assertSame($expected, $actual); + } +} diff --git a/vendor/phpmyadmin/motranslator/tests/Cache/ApcuCacheTest.php b/vendor/phpmyadmin/motranslator/tests/Cache/ApcuCacheTest.php new file mode 100644 index 0000000..5fa06f4 --- /dev/null +++ b/vendor/phpmyadmin/motranslator/tests/Cache/ApcuCacheTest.php @@ -0,0 +1,270 @@ +markTestSkipped('ACPu extension is not installed and enabled for CLI'); + } + + protected function tearDown(): void + { + parent::tearDown(); + + apcu_clear_cache(); + } + + public function testConstructorLoadsCache(): void + { + $expected = 'Pole'; + $locale = 'foo'; + $domain = 'bar'; + $msgid = 'Column'; + + new ApcuCache(new MoParser(__DIR__ . '/../data/little.mo'), $locale, $domain); + + $actual = apcu_fetch('mo_' . $locale . '.' . $domain . '.' . $msgid); + $this->assertSame($expected, $actual); + } + + public function testConstructorSetsTtl(): void + { + $locale = 'foo'; + $domain = 'bar'; + $msgid = 'Column'; + $ttl = 1; + + new ApcuCache(new MoParser(__DIR__ . '/../data/little.mo'), $locale, $domain, $ttl); + sleep($ttl * 2); + + apcu_fetch('mo_' . $locale . '.' . $domain . '.' . $msgid, $success); + $this->assertFalse($success); + apcu_fetch('mo_' . $locale . '.' . $domain . '.' . ApcuCache::LOADED_KEY, $success); + $this->assertFalse($success); + } + + public function testConstructorSetsReloadOnMiss(): void + { + $expected = 'Column'; + $locale = 'foo'; + $domain = 'bar'; + $msgid = 'Column'; + $prefix = 'baz_'; + + $cache = new ApcuCache( + new MoParser(__DIR__ . '/../data/little.mo'), + $locale, + $domain, + 0, + false, + $prefix + ); + + apcu_delete($prefix . $locale . '.' . $domain . '.' . $msgid); + $actual = $cache->get($msgid); + $this->assertEquals($expected, $actual); + } + + public function testConstructorSetsPrefix(): void + { + $expected = 'Pole'; + $locale = 'foo'; + $domain = 'bar'; + $msgid = 'Column'; + $prefix = 'baz_'; + + new ApcuCache(new MoParser(__DIR__ . '/../data/little.mo'), $locale, $domain, 0, true, $prefix); + + $actual = apcu_fetch($prefix . $locale . '.' . $domain . '.' . $msgid); + $this->assertSame($expected, $actual); + } + + public function testEnsureTranslationsLoadedSetsLoadedKey(): void + { + $expected = 1; + $locale = 'foo'; + $domain = 'bar'; + + new ApcuCache(new MoParser(__DIR__ . '/../data/little.mo'), $locale, $domain); + + $actual = apcu_fetch('mo_' . $locale . '.' . $domain . '.' . ApcuCache::LOADED_KEY); + $this->assertSame($expected, $actual); + } + + public function testEnsureTranslationsLoadedHonorsLock(): void + { + $locale = 'foo'; + $domain = 'bar'; + $msgid = 'Column'; + + $lock = 'mo_' . $locale . '.' . $domain . '.' . ApcuCache::LOADED_KEY; + apcu_entry($lock, static function () { + sleep(1); + + return 1; + }); + + new ApcuCache(new MoParser(__DIR__ . '/../data/little.mo'), $locale, $domain); + + $actual = apcu_fetch($lock); + $this->assertSame(1, $actual); + apcu_fetch('mo_' . $locale . '.' . $domain . '.' . $msgid, $success); + $this->assertFalse($success); + } + + public function testGetReturnsMsgstr(): void + { + $expected = 'Pole'; + $msgid = 'Column'; + + $cache = new ApcuCache(new MoParser(__DIR__ . '/../data/little.mo'), 'foo', 'bar'); + + $actual = $cache->get($msgid); + $this->assertSame($expected, $actual); + } + + public function testGetReturnsMsgidForCacheMiss(): void + { + $expected = 'Column'; + + $cache = new ApcuCache(new MoParser(null), 'foo', 'bar'); + + $actual = $cache->get($expected); + $this->assertSame($expected, $actual); + } + + public function testStoresMsgidOnCacheMiss(): void + { + $expected = 'Column'; + $locale = 'foo'; + $domain = 'bar'; + + $cache = new ApcuCache(new MoParser(null), $locale, $domain); + $cache->get($expected); + + $actual = apcu_fetch('mo_' . $locale . '.' . $domain . '.' . $expected); + $this->assertSame($expected, $actual); + } + + public function testGetReloadsOnCacheMiss(): void + { + $expected = 'Pole'; + $locale = 'foo'; + $domain = 'bar'; + $msgid = 'Column'; + + $cache = new ApcuCache(new MoParser(__DIR__ . '/../data/little.mo'), $locale, $domain); + + apcu_delete('mo_' . $locale . '.' . $domain . '.' . ApcuCache::LOADED_KEY); + $actual = $cache->get($msgid); + $this->assertSame($expected, $actual); + } + + public function testReloadOnMissHonorsLock(): void + { + $expected = 'Pole'; + $locale = 'foo'; + $domain = 'bar'; + $msgid = 'Column'; + + $cache = new ApcuCache(new MoParser(null), $locale, $domain); + + $method = new ReflectionMethod($cache, 'reloadOnMiss'); + $method->setAccessible(true); + + $key = 'mo_' . $locale . '.' . $domain . '.' . $msgid; + apcu_entry($key, static function () use ($expected): string { + sleep(1); + + return $expected; + }); + $actual = $method->invoke($cache, $msgid); + + $this->assertSame($expected, $actual); + } + + public function testSetSetsMsgstr(): void + { + $expected = 'Pole'; + $msgid = 'Column'; + + $cache = new ApcuCache(new MoParser(null), 'foo', 'bar'); + $cache->set($msgid, $expected); + + $actual = $cache->get($msgid); + $this->assertSame($expected, $actual); + } + + public function testHasReturnsFalse(): void + { + $cache = new ApcuCache(new MoParser(null), 'foo', 'bar'); + $actual = $cache->has('Column'); + $this->assertFalse($actual); + } + + public function testHasReturnsTrue(): void + { + $cache = new ApcuCache(new MoParser(__DIR__ . '/../data/little.mo'), 'foo', 'bar'); + $actual = $cache->has('Column'); + $this->assertTrue($actual); + } + + public function testSetAllSetsTranslations(): void + { + $translations = [ + 'foo' => 'bar', + 'and' => 'another', + ]; + + $cache = new ApcuCache(new MoParser(null), 'foo', 'bar'); + $cache->setAll($translations); + + foreach ($translations as $msgid => $expected) { + $actual = $cache->get($msgid); + $this->assertEquals($expected, $actual); + } + } + + public function testCacheStoresPluralForms(): void + { + $expected = ['first', 'second']; + $plural = ["%d pig went to the market\n", "%d pigs went to the market\n"]; + $msgid = implode(chr(0), $plural); + + $cache = new ApcuCache(new MoParser(null), 'foo', 'bar'); + $cache->set($msgid, implode(chr(0), $expected)); + + $msgstr = $cache->get($msgid); + $actual = explode(chr(0), $msgstr); + $this->assertSame($expected, $actual); + } +} diff --git a/vendor/phpmyadmin/motranslator/tests/Cache/ApcuDisabledTest.php b/vendor/phpmyadmin/motranslator/tests/Cache/ApcuDisabledTest.php new file mode 100644 index 0000000..60b4a49 --- /dev/null +++ b/vendor/phpmyadmin/motranslator/tests/Cache/ApcuDisabledTest.php @@ -0,0 +1,27 @@ +markTestSkipped('ext-apcu is enabled'); + } + + $this->expectException(CacheException::class); + $this->expectExceptionMessage('ACPu extension must be installed and enabled'); + new ApcuCache(new MoParser(null), 'foo', 'bar'); + } +} diff --git a/vendor/phpmyadmin/motranslator/tests/Cache/InMemoryCacheTest.php b/vendor/phpmyadmin/motranslator/tests/Cache/InMemoryCacheTest.php new file mode 100644 index 0000000..c81a56e --- /dev/null +++ b/vendor/phpmyadmin/motranslator/tests/Cache/InMemoryCacheTest.php @@ -0,0 +1,82 @@ +get('Column'); + $this->assertSame($expected, $actual); + } + + public function testGetReturnsMsgidForCacheMiss(): void + { + $expected = 'Column'; + $cache = new InMemoryCache(new MoParser(null)); + $actual = $cache->get($expected); + $this->assertSame($expected, $actual); + } + + public function testSetSetsMsgstr(): void + { + $expected = 'Pole'; + $msgid = 'Column'; + $cache = new InMemoryCache(new MoParser(null)); + $cache->set($msgid, $expected); + $actual = $cache->get($msgid); + $this->assertSame($expected, $actual); + } + + public function testHasReturnsFalse(): void + { + $cache = new InMemoryCache(new MoParser(null)); + $actual = $cache->has('Column'); + $this->assertFalse($actual); + } + + public function testHasReturnsTrue(): void + { + $cache = new InMemoryCache(new MoParser(__DIR__ . '/../data/little.mo')); + $actual = $cache->has('Column'); + $this->assertTrue($actual); + } + + public function testSetAllSetsTranslations(): void + { + $translations = [ + 'foo' => 'bar', + 'and' => 'another', + ]; + $cache = new InMemoryCache(new MoParser(null)); + $cache->setAll($translations); + foreach ($translations as $msgid => $expected) { + $actual = $cache->get($msgid); + $this->assertEquals($expected, $actual); + } + } + + public function testGetAllReturnsTranslations(): void + { + $expected = [ + 'foo' => 'bar', + 'and' => 'another', + ]; + $cache = new InMemoryCache(new MoParser(null)); + $cache->setAll($expected); + $actual = $cache->getAll(); + $this->assertSame($expected, $actual); + } +} diff --git a/vendor/phpmyadmin/motranslator/tests/FunctionsTest.php b/vendor/phpmyadmin/motranslator/tests/FunctionsTest.php new file mode 100644 index 0000000..8551957 --- /dev/null +++ b/vendor/phpmyadmin/motranslator/tests/FunctionsTest.php @@ -0,0 +1,102 @@ +assertEquals( + 'Typ', + _gettext('Type') + ); + + $this->assertEquals( + 'Typ', + __('Type') + ); + + $this->assertEquals( + '%d sekundy', + _ngettext( + '%d second', + '%d seconds', + 2 + ) + ); + + $this->assertEquals( + '%d seconds', + _npgettext( + 'context', + '%d second', + '%d seconds', + 2 + ) + ); + + $this->assertEquals( + 'Tabulka', + _pgettext( + 'Display format', + 'Table' + ) + ); + } + + public function testDomain(): void + { + $this->assertEquals( + 'Typ', + _dgettext('phpmyadmin', 'Type') + ); + + $this->assertEquals( + '%d sekundy', + _dngettext( + 'phpmyadmin', + '%d second', + '%d seconds', + 2 + ) + ); + + $this->assertEquals( + '%d seconds', + _dnpgettext( + 'phpmyadmin', + 'context', + '%d second', + '%d seconds', + 2 + ) + ); + + $this->assertEquals( + 'Tabulka', + _dpgettext( + 'phpmyadmin', + 'Display format', + 'Table' + ) + ); + } +} diff --git a/vendor/phpmyadmin/motranslator/tests/LoaderTest.php b/vendor/phpmyadmin/motranslator/tests/LoaderTest.php new file mode 100644 index 0000000..c9ee6d3 --- /dev/null +++ b/vendor/phpmyadmin/motranslator/tests/LoaderTest.php @@ -0,0 +1,325 @@ +assertEquals( + $expected, + Loader::listLocales($locale) + ); + } + + /** + * @return array[] + */ + public function localeList(): array + { + return [ + [ + 'cs_CZ', + [ + 'cs_CZ', + 'cs', + ], + ], + [ + 'sr_CS.UTF-8@latin', + [ + 'sr_CS.UTF-8@latin', + 'sr_CS@latin', + 'sr@latin', + 'sr_CS.UTF-8', + 'sr_CS', + 'sr', + ], + ], + // For a locale containing country code, we prefer + // full locale name, but if that's not found, fall back + // to the language only locale name. + [ + 'sr_RS', + [ + 'sr_RS', + 'sr', + ], + ], + // If language code is used, it's the only thing returned. + [ + 'sr', + ['sr'], + ], + // There is support for language and charset only. + [ + 'sr.UTF-8', + [ + 'sr.UTF-8', + 'sr', + ], + ], + + // It can also split out character set from the full locale name. + [ + 'sr_RS.UTF-8', + [ + 'sr_RS.UTF-8', + 'sr_RS', + 'sr', + ], + ], + + // There is support for @modifier in locale names as well. + [ + 'sr_RS.UTF-8@latin', + [ + 'sr_RS.UTF-8@latin', + 'sr_RS@latin', + 'sr@latin', + 'sr_RS.UTF-8', + 'sr_RS', + 'sr', + ], + ], + [ + 'sr.UTF-8@latin', + [ + 'sr.UTF-8@latin', + 'sr@latin', + 'sr.UTF-8', + 'sr', + ], + ], + + // We can pass in only language and modifier. + [ + 'sr@latin', + [ + 'sr@latin', + 'sr', + ], + ], + + // If locale name is not following the regular POSIX pattern, + // it's used verbatim. + [ + 'something', + ['something'], + ], + + // Passing in an empty string returns an empty array. + [ + '', + [], + ], + ]; + } + + private function getLoader(string $domain, string $locale): Loader + { + $loader = new Loader(); + $loader->setlocale($locale); + $loader->textdomain($domain); + $loader->bindtextdomain($domain, __DIR__ . '/data/locale/'); + + return $loader; + } + + public function testLocaleChange(): void + { + $loader = new Loader(); + $loader->setlocale('cs'); + $loader->textdomain('phpmyadmin'); + $loader->bindtextdomain('phpmyadmin', __DIR__ . '/data/locale/'); + $translator = $loader->getTranslator('phpmyadmin'); + $this->assertEquals('Typ', $translator->gettext('Type')); + $loader->setlocale('be_BY'); + $translator = $loader->getTranslator('phpmyadmin'); + $this->assertEquals('Тып', $translator->gettext('Type')); + } + + /** + * @dataProvider translatorData + */ + public function testGetTranslator(string $domain, string $locale, string $otherdomain, string $expected): void + { + $loader = $this->getLoader($domain, $locale); + $translator = $loader->getTranslator($otherdomain); + $this->assertEquals( + $expected, + $translator->gettext('Type') + ); + } + + /** + * @return array[] + */ + public function translatorData(): array + { + return [ + [ + 'phpmyadmin', + 'cs', + '', + 'Typ', + ], + [ + 'phpmyadmin', + 'cs_CZ', + '', + 'Typ', + ], + [ + 'phpmyadmin', + 'be_BY', + '', + 'Тып', + ], + [ + 'phpmyadmin', + 'be@latin', + '', + 'Typ', + ], + [ + 'phpmyadmin', + 'cs', + 'other', + 'Type', + ], + [ + 'other', + 'cs', + 'phpmyadmin', + 'Type', + ], + ]; + } + + public function testInstance(): void + { + $loader = Loader::getInstance(); + $loader->setlocale('cs'); + $loader->textdomain('phpmyadmin'); + $loader->bindtextdomain('phpmyadmin', __DIR__ . '/data/locale/'); + + $translator = $loader->getTranslator(); + $this->assertEquals( + 'Typ', + $translator->gettext('Type') + ); + + /* Ensure the object survives */ + $loader = Loader::getInstance(); + $translator = $loader->getTranslator(); + $this->assertEquals( + 'Typ', + $translator->gettext('Type') + ); + + /* Ensure the object can support different locale files for the same domain */ + $loader = Loader::getInstance(); + $loader->setlocale('be_BY'); + $loader->bindtextdomain('phpmyadmin', __DIR__ . '/data/locale/'); + $translator = $loader->getTranslator(); + $this->assertEquals( + 'Тып', + $translator->gettext('Type') + ); + } + + public function testDetect(): void + { + $GLOBALS['lang'] = 'foo'; + $loader = Loader::getInstance(); + $this->assertEquals( + 'foo', + $loader->detectlocale() + ); + unset($GLOBALS['lang']); + } + + public function testDetectEnv(): void + { + $loader = Loader::getInstance(); + foreach (['LC_MESSAGES', 'LC_ALL', 'LANG'] as $var) { + putenv($var); + if (getenv($var) === false) { + continue; + } + + $this->markTestSkipped('Unsetting environment does not work'); + } + + unset($GLOBALS['lang']); + putenv('LC_ALL=baz'); + $this->assertEquals( + 'baz', + $loader->detectlocale() + ); + putenv('LC_ALL'); + putenv('LC_MESSAGES=bar'); + $this->assertEquals( + 'bar', + $loader->detectlocale() + ); + putenv('LC_MESSAGES'); + putenv('LANG=barr'); + $this->assertEquals( + 'barr', + $loader->detectlocale() + ); + putenv('LANG'); + $this->assertEquals( + 'en', + $loader->detectlocale() + ); + } + + public function testSetCacheFactory(): void + { + $expected = 'Foo'; + $locale = 'be_BY'; + $domain = 'apcu'; + + $cache = $this->createMock(CacheInterface::class); + $cache->method('get') + ->willReturn($expected); + /** @var CacheFactoryInterface&MockObject $factory */ + $factory = $this->createMock(CacheFactoryInterface::class); + $factory->expects($this->once()) + ->method('getInstance') + ->with($this->isInstanceOf(MoParser::class), $locale, $domain) + ->willReturn($cache); + + Loader::setCacheFactory($factory); + $loader = Loader::getInstance(); + $loader->setlocale($locale); + $loader->bindtextdomain($domain, __DIR__ . '/data/locale/'); + $translator = $loader->getTranslator($domain); + + $actual = $translator->gettext('Type'); + $this->assertEquals($expected, $actual); + } +} diff --git a/vendor/phpmyadmin/motranslator/tests/MoFilesTest.php b/vendor/phpmyadmin/motranslator/tests/MoFilesTest.php new file mode 100644 index 0000000..b75bf75 --- /dev/null +++ b/vendor/phpmyadmin/motranslator/tests/MoFilesTest.php @@ -0,0 +1,230 @@ +getTranslator($filename); + $this->assertEquals( + 'Pole', + $parser->gettext('Column') + ); + // Non existing string + $this->assertEquals( + 'Column parser', + $parser->gettext('Column parser') + ); + } + + /** + * @dataProvider provideMoFiles + */ + public function testMoFilePlurals(string $filename): void + { + $parser = $this->getTranslator($filename); + $expected2 = '%d sekundy'; + if (strpos($filename, 'invalid-formula.mo') !== false || strpos($filename, 'lessplurals.mo') !== false) { + $expected0 = '%d sekunda'; + $expected2 = '%d sekunda'; + } elseif (strpos($filename, 'plurals.mo') !== false || strpos($filename, 'noheader.mo') !== false) { + $expected0 = '%d sekundy'; + } else { + $expected0 = '%d sekund'; + } + + $this->assertEquals( + $expected0, + $parser->ngettext( + '%d second', + '%d seconds', + 0 + ) + ); + $this->assertEquals( + '%d sekunda', + $parser->ngettext( + '%d second', + '%d seconds', + 1 + ) + ); + $this->assertEquals( + $expected2, + $parser->ngettext( + '%d second', + '%d seconds', + 2 + ) + ); + $this->assertEquals( + $expected0, + $parser->ngettext( + '%d second', + '%d seconds', + 5 + ) + ); + $this->assertEquals( + $expected0, + $parser->ngettext( + '%d second', + '%d seconds', + 10 + ) + ); + // Non existing string + $this->assertEquals( + '"%d" seconds', + $parser->ngettext( + '"%d" second', + '"%d" seconds', + 10 + ) + ); + } + + /** + * @dataProvider provideMoFiles + */ + public function testMoFileContext(string $filename): void + { + $parser = $this->getTranslator($filename); + $this->assertEquals( + 'Tabulka', + $parser->pgettext( + 'Display format', + 'Table' + ) + ); + } + + /** + * @dataProvider provideNotTranslatedFiles + */ + public function testMoFileNotTranslated(string $filename): void + { + $parser = $this->getTranslator($filename); + $this->assertEquals( + '%d second', + $parser->ngettext( + '%d second', + '%d seconds', + 1 + ) + ); + } + + /** + * @return array[] + */ + public function provideMoFiles(): array + { + return $this->getFiles('./tests/data/*.mo'); + } + + /** + * @return array[] + */ + public function provideErrorMoFiles(): array + { + return $this->getFiles('./tests/data/error/*.mo'); + } + + /** + * @return array[] + */ + public function provideNotTranslatedFiles(): array + { + return $this->getFiles('./tests/data/not-translated/*.mo'); + } + + /** + * @dataProvider provideErrorMoFiles + */ + public function testEmptyMoFile(string $file): void + { + $parser = new MoParser($file); + $translator = new Translator(new InMemoryCache($parser)); + if (basename($file) === 'magic.mo') { + $this->assertEquals(Translator::ERROR_BAD_MAGIC, $parser->error); + } else { + $this->assertEquals(Translator::ERROR_READING, $parser->error); + } + + $this->assertEquals( + 'Table', + $translator->pgettext( + 'Display format', + 'Table' + ) + ); + $this->assertEquals( + '"%d" seconds', + $translator->ngettext( + '"%d" second', + '"%d" seconds', + 10 + ) + ); + } + + /** + * @dataProvider provideMoFiles + */ + public function testExists(string $file): void + { + $parser = $this->getTranslator($file); + $this->assertEquals( + true, + $parser->exists('Column') + ); + $this->assertEquals( + false, + $parser->exists('Column parser') + ); + } + + /** + * @param string $pattern path names pattern to match + * + * @return array[] + */ + private function getFiles(string $pattern): array + { + $files = glob($pattern); + if ($files === false) { + return []; + } + + $result = []; + foreach ($files as $file) { + $result[] = [$file]; + } + + return $result; + } + + private function getTranslator(string $filename): Translator + { + return new Translator(new InMemoryCache(new MoParser($filename))); + } +} diff --git a/vendor/phpmyadmin/motranslator/tests/PluralFormulaTest.php b/vendor/phpmyadmin/motranslator/tests/PluralFormulaTest.php new file mode 100644 index 0000000..769f121 --- /dev/null +++ b/vendor/phpmyadmin/motranslator/tests/PluralFormulaTest.php @@ -0,0 +1,152 @@ +assertEquals( + $expected, + Translator::extractPluralsForms($header) + ); + } + + /** + * @return array[] + */ + public function pluralExtractionData(): array + { + return [ + // It defaults to a "Western-style" plural header. + [ + '', + 'nplurals=2; plural=n == 1 ? 0 : 1;', + ], + // Extracting it from the middle of the header works. + [ + "Content-type: text/html; charset=UTF-8\n" + . "Plural-Forms: nplurals=1; plural=0;\n" + . "Last-Translator: nobody\n", + ' nplurals=1; plural=0;', + ], + // It's also case-insensitive. + [ + "PLURAL-forms: nplurals=1; plural=0;\n", + ' nplurals=1; plural=0;', + ], + // It falls back to default if it's not on a separate line. + [ + 'Content-type: text/html; charset=UTF-8' // note the missing \n here + . "Plural-Forms: nplurals=1; plural=0;\n" + . "Last-Translator: nobody\n", + 'nplurals=2; plural=n == 1 ? 0 : 1;', + ], + ]; + } + + /** + * @dataProvider pluralCounts + */ + public function testPluralCounts(string $expr, int $expected): void + { + $this->assertEquals( + $expected, + Translator::extractPluralCount($expr) + ); + } + + /** + * @return array[] + */ + public function pluralCounts(): array + { + return [ + [ + '', + 1, + ], + [ + 'foo=2; expr', + 1, + ], + [ + 'nplurals=2; epxr', + 2, + ], + [ + ' nplurals = 3 ; epxr', + 3, + ], + [ + ' nplurals = 4 ; epxr ; ', + 4, + ], + [ + 'nplurals', + 1, + ], + ]; + } + + /** + * @dataProvider pluralExpressions + */ + public function testPluralExpression(string $expr, string $expected): void + { + $this->assertEquals( + $expected, + Translator::sanitizePluralExpression($expr) + ); + } + + /** + * @return array[] + */ + public function pluralExpressions(): array + { + return [ + [ + '', + '', + ], + [ + 'nplurals=2; plural=n == 1 ? 0 : 1;', + 'n == 1 ? 0 : 1', + ], + [ + ' nplurals=1; plural=0;', + '0', + ], + [ + "nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 ? 4 : 5;\n", + 'n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 ? 4 : 5', + ], + [ + ' nplurals=1; plural=baz(n);', + '(n)', + ], + [ + ' plural=n', + 'n', + ], + [ + 'nplurals', + 'n', + ], + ]; + } +} diff --git a/vendor/phpmyadmin/motranslator/tests/PluralTest.php b/vendor/phpmyadmin/motranslator/tests/PluralTest.php new file mode 100644 index 0000000..28da262 --- /dev/null +++ b/vendor/phpmyadmin/motranslator/tests/PluralTest.php @@ -0,0 +1,125 @@ +getTranslator(''); + $result = $parser->npgettext('context', "%d pig went to the market\n", "%d pigs went to the market\n", $number); + $this->assertSame($expected, $result); + } + + /** + * Data provider for test_npgettext. + * + * @return array[] + */ + public static function providerTestNpgettext(): array + { + return [ + [ + 1, + "%d pig went to the market\n", + ], + [ + 2, + "%d pigs went to the market\n", + ], + ]; + } + + /** + * Test for ngettext + */ + public function testNgettext(): void + { + $parser = $this->getTranslator(''); + $translationKey = implode(chr(0), ["%d pig went to the market\n", "%d pigs went to the market\n"]); + $parser->setTranslation($translationKey, ''); + $result = $parser->ngettext("%d pig went to the market\n", "%d pigs went to the market\n", 1); + $this->assertSame('', $result); + } + + /** + * @return array[] + */ + public function dataProviderPluralForms(): array + { + return [ + ['Plural-Forms: nplurals=2; plural=n != 1;'], + ['Plural-Forms: nplurals=1; plural=0;'], + ['Plural-Forms: nplurals=2; plural=(n > 1);'], + [ + 'Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n' + . '%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;', + ], + ['Plural-Forms: nplurals=2; plural=n >= 2 && (n < 11 || n > 99);'], + ['Plural-Forms: nplurals=4; plural=n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3;'], + ['Plural-Forms: nplurals=3; plural=n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < 20)) ? 1 : 2;'], + [ + 'Plural-Forms: nplurals=2; plural=n != 1 && n != 2 && n != 3 &' + . '& (n % 10 == 4 || n % 10 == 6 || n % 10 == 9);', + ], + ]; + } + + /** + * Test for ngettext + * + * @see https://github.com/phpmyadmin/motranslator/issues/37 + * + * @dataProvider dataProviderPluralForms + */ + public function testNgettextSelectString(string $pluralForms): void + { + $parser = $this->getTranslator(''); + $parser->setTranslation( + '', + "Project-Id-Version: phpMyAdmin 5.1.0-dev\n" + . "Report-Msgid-Bugs-To: translators@phpmyadmin.net\n" + . "PO-Revision-Date: 2020-09-01 09:12+0000\n" + . "Last-Translator: William Desportes \n" + . 'Language-Team: English (United Kingdom) ' + . "\n" + . "Language: en_GB\n" + . "MIME-Version: 1.0\n" + . "Content-Type: text\/plain; charset=UTF-8\n" + . "Content-Transfer-Encoding: 8bit\n" + . $pluralForms . "\n" + . "X-Generator: Weblate 4.2.1-dev\n" + . '' + ); + $translationKey = implode(chr(0), ["%d pig went to the market\n", "%d pigs went to the market\n"]); + $parser->setTranslation($translationKey, 'ok'); + $result = $parser->ngettext("%d pig went to the market\n", "%d pigs went to the market\n", 1); + $this->assertSame('ok', $result); + } + + private function getTranslator(string $filename): Translator + { + return new Translator(new InMemoryCache(new MoParser($filename))); + } +} diff --git a/vendor/phpmyadmin/motranslator/tests/StringReaderTest.php b/vendor/phpmyadmin/motranslator/tests/StringReaderTest.php new file mode 100644 index 0000000..17dc794 --- /dev/null +++ b/vendor/phpmyadmin/motranslator/tests/StringReaderTest.php @@ -0,0 +1,40 @@ +assertFileExists($tempFile); + $stringReader = new StringReader($tempFile); + unlink($tempFile); + $actual = $stringReader->read(-1, -1); + $this->assertSame('', $actual); + } + + public function testReadIntArray(): void + { + $tempFile = (string) tempnam(sys_get_temp_dir(), 'phpMyAdmin_StringReaderTest'); + file_put_contents($tempFile, "\0\0\0\0\0\0\0\0\0\0\0\0"); + $this->assertFileExists($tempFile); + $stringReader = new StringReader($tempFile); + unlink($tempFile); + $actual = $stringReader->readintarray('V', 2, 2); + $this->assertSame([ + 1 => 0, + 2 => 0, + ], $actual); + } +} diff --git a/vendor/phpmyadmin/motranslator/tests/TranslatorTest.php b/vendor/phpmyadmin/motranslator/tests/TranslatorTest.php new file mode 100644 index 0000000..dd135b5 --- /dev/null +++ b/vendor/phpmyadmin/motranslator/tests/TranslatorTest.php @@ -0,0 +1,98 @@ +gettext('Column'); + $this->assertSame($expected, $actual); + } + + public function testConstructorWithNullParam(): void + { + $expected = 'Column'; + $translator = new Translator(null); + $actual = $translator->gettext($expected); + $this->assertSame($expected, $actual); + } + + /** + * Test on empty gettext + */ + public function testGettext(): void + { + $translator = $this->getTranslator(''); + $this->assertEquals('Test', $translator->gettext('Test')); + } + + /** + * Test set a translation + */ + public function testSetTranslation(): void + { + $translator = $this->getTranslator(''); + $translator->setTranslation('Test', 'Translation'); + $this->assertEquals('Translation', $translator->gettext('Test')); + } + + /** + * Test get and set all translations + */ + public function testGetSetTranslations(): void + { + $transTable = ['Test' => 'Translation']; + $translator = $this->getTranslator(''); + $translator->setTranslations($transTable); + $this->assertEquals('Translation', $translator->gettext('Test')); + $this->assertSame($transTable, $translator->getTranslations()); + $translator = $this->getTranslator(null); + $translator->setTranslations($transTable); + $this->assertSame($transTable, $translator->getTranslations()); + $this->assertEquals('Translation', $translator->gettext('Test')); + $transTable = [ + 'Test' => 'Translation', + 'shouldIWriteTests' => 'as much as possible', + 'is it hard' => 'it depends', + ]; + $translator = $this->getTranslator(''); + $translator->setTranslations($transTable); + $this->assertSame($transTable, $translator->getTranslations()); + $this->assertEquals('as much as possible', $translator->gettext('shouldIWriteTests')); + $translator = $this->getTranslator(null); + $translator->setTranslations($transTable); + $this->assertSame($transTable, $translator->getTranslations()); + $this->assertEquals('it depends', $translator->gettext('is it hard')); + } + + public function testGetTranslationsThrowsException(): void + { + /** @var CacheInterface&MockObject $cache */ + $cache = $this->createMock(CacheInterface::class); + $translator = new Translator($cache); + + $this->expectException(CacheException::class); + $translator->getTranslations(); + } + + private function getTranslator(?string $filename): Translator + { + return new Translator(new InMemoryCache(new MoParser($filename))); + } +} diff --git a/vendor/phpmyadmin/motranslator/tests/data/big.mo b/vendor/phpmyadmin/motranslator/tests/data/big.mo new file mode 100644 index 0000000000000000000000000000000000000000..d913c35df8bc17ef131b34cda2eae18e544fef38 GIT binary patch literal 332023 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 QnpEny#Q04Q>0VF&0n~K^DgXcg literal 0 HcmV?d00001 diff --git a/vendor/phpmyadmin/motranslator/tests/data/error/big.mo b/vendor/phpmyadmin/motranslator/tests/data/error/big.mo new file mode 100644 index 0000000..cec12d5 --- /dev/null +++ b/vendor/phpmyadmin/motranslator/tests/data/error/big.mo @@ -0,0 +1 @@ +•Ž1111’’’’ \ No newline at end of file diff --git a/vendor/phpmyadmin/motranslator/tests/data/error/dos.mo b/vendor/phpmyadmin/motranslator/tests/data/error/dos.mo new file mode 100644 index 0000000..a86b22f --- /dev/null +++ b/vendor/phpmyadmin/motranslator/tests/data/error/dos.mo @@ -0,0 +1 @@ +•Ž1111’’’ \ No newline at end of file diff --git a/vendor/phpmyadmin/motranslator/tests/data/error/empty.mo b/vendor/phpmyadmin/motranslator/tests/data/error/empty.mo new file mode 100644 index 0000000..e69de29 diff --git a/vendor/phpmyadmin/motranslator/tests/data/error/fpd.mo b/vendor/phpmyadmin/motranslator/tests/data/error/fpd.mo new file mode 100644 index 0000000000000000000000000000000000000000..6c5e67ac3d62c06c40a14ed9528bcf4193326151 GIT binary patch literal 12 RcmbQrB6QCX2pAX`xBwKo0$2b5 literal 0 HcmV?d00001 diff --git a/vendor/phpmyadmin/motranslator/tests/data/error/fpdle.mo b/vendor/phpmyadmin/motranslator/tests/data/error/fpdle.mo new file mode 100644 index 0000000..7b55e41 --- /dev/null +++ b/vendor/phpmyadmin/motranslator/tests/data/error/fpdle.mo @@ -0,0 +1 @@ +Ž•’’’’’’’’’’’’’’’’’’’’’’’’ \ No newline at end of file diff --git a/vendor/phpmyadmin/motranslator/tests/data/error/magic.mo b/vendor/phpmyadmin/motranslator/tests/data/error/magic.mo new file mode 100644 index 0000000..81c545e --- /dev/null +++ b/vendor/phpmyadmin/motranslator/tests/data/error/magic.mo @@ -0,0 +1 @@ +1234 diff --git a/vendor/phpmyadmin/motranslator/tests/data/invalid-formula.mo b/vendor/phpmyadmin/motranslator/tests/data/invalid-formula.mo new file mode 100644 index 0000000000000000000000000000000000000000..5838d693dc1b837975f0853619655fc503294c79 GIT binary patch literal 703 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%0Aa8j(F#9K-Lw%g? z`nEU=eB9<#`K7e}eiA}!BP?}G5W8aJs%XMtmA*AM9~4fcJc1LclY$ufVSFkZNw!gS zYXw^Jp|S{QlnfiDM^N=wPIY?`Lh2T0qT4d`?v8IZB~3P>u!PSB&?xp8TJ1&?m#G(v zxjQfj^4#_!=F34!eSZ;)BVuSeOuh$Q$|Z%T%^E(pgLZXJ!k^1(lc*|7e()tg6g(t3 z`hBR_;f!V|U5?nub_Tb^*8T`ipW7GA4!3w*;= zW$VL#L)NL#)rqp-pN|eGl+kG{hJ~eo0 zyjCO?WL46YdjAvan#lohNTCwfys;T~I9m!n2p@3Jg&?B*+@vro$=Ke*NXe$SsRS^N zia>o|XgPZ&)Tb^3>xOhIhBW=eEnqnr?~Z00!|B-)=n(}n*0_M6u1tqg8{r?V$mK+v zmsBQTAnMqyiYsl8t}9oR7|08U3UYzlRIF%XEY9qQP80z04%QV+p6FQ_~< zKM$t!&R$Uu#2^^xSzZNSLVws2*v*wU=cmk+tAmIv{F#JU zp~^dOehE3i34cqM zjF54DFupfhnO!`Ds{e|O!dNre3G?|4E)(tp}@d0nM%OM2hCv z$n}G2d*$i)^}SK__S`vOqthGe;xz0D*{4s#Os|YnAYfl18_Rxy2`*oLm`vUyagl=$ zUBEB4xD$fHANh` zLcio;`7Wv_SM()`U?l}q=c`AA2Kz*?u~A5|IX$T+UY35Pm69siZIS`he&boYxxVx} zVYRTbxp*#InE7fD3`uMi=p}**vnVGVckZa>-)(h-rVo2xiq1oWq=V8TRi>C0T5On% zZ$(^i7XjkB-cw_Tj1UQJc_g39s(noamlXA#{I(nU+5Up~M z{T)Vn(hz5(8@MCm8P-?{gl5PY-w+RlCLDl~9(Be|Acd5}H2!R+v9Sxq87YONb25l| zL&0#pMk40H{7eikUL3$^1Xq=7@7MPA?3n3j2o+&kYX$l5xyUH^@iX1Dk6YpO87;@XCcShkb$)DC|`mCvIOV2Kz|`1IQbW0;P|a(V)e%)LevA#cJ9hjQNKL(@2Oa`UD1ci4rZan&TWri!c_FZ=|p=aiKBad;^G~=QaCV76t8i=OI!M>I1 z5%s7RCL$x5qA_Yss^p+|w`@-di0^%w!dfhU8EYa|k<|1M!A=PWj5yIE_9-qXTPtj; zTSo*t`unQEk#%k%$VXA=DQ%Nl$BONI7(hj&?enC^*|gOVsg??gWhlWN2^n04EPj$m$o~ju9sv zb%wukl#rAW9u?Et!cOlqwdPBj^C;3v;LaR2S8K-upsj>DASXp|+hu31tTZ>}gM)Dv ztD}G*HH$%^7_11pc1}urESg`89>a*iZk;J*_8Z(#Q~n+bx~dhNuBde5Q1BnA4m>tB zOw9Y%`~4GXQx9a?1={09u^ZuF=`w@-+fmA{am$#geHADTs;xY=fX&;4fP63Rx0C<1 z?&7{zBpA@|jlfx21~Y(yx9|u=lIA?pG$4*q#C;|6Pw0W%_gVMzqv-`nrSaWnQc5Zg zdXlm^c`&rJMnR9CBTPYul&7jWs@6xH^~=A))%7)KZmy^4$_@(09UT8S28Z*9C<)mx zC7Qv;Ge*ll@gfizDq}gl_g|fwRg_$|cAwk+*2SJ4jjc}&R>{gL5%|A9JY!4xn$Stk zqz56_k+l?)CJk_Yp;(j%0DpA)RS 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�_OymZPoaB=`R=7nNkamvbT_eo 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 literal 0 HcmV?d00001 diff --git a/vendor/phpmyadmin/motranslator/tests/data/locale/be/LC_MESSAGES/phpmyadmin.mo b/vendor/phpmyadmin/motranslator/tests/data/locale/be/LC_MESSAGES/phpmyadmin.mo new file mode 100644 index 0000000000000000000000000000000000000000..1394f80a7e6db3c9a9d3f1e2140699bbc142d22c GIT binary patch literal 103648 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 literal 0 HcmV?d00001 diff --git a/vendor/phpmyadmin/motranslator/tests/data/locale/be@latin/LC_MESSAGES/phpmyadmin.mo b/vendor/phpmyadmin/motranslator/tests/data/locale/be@latin/LC_MESSAGES/phpmyadmin.mo new file mode 100644 index 0000000000000000000000000000000000000000..c1633d3fbd81cc1bc67944354187a42c79168111 GIT binary patch literal 79649 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 Hy1V#a>;+r> literal 0 HcmV?d00001 diff --git a/vendor/phpmyadmin/motranslator/tests/data/locale/cs/LC_MESSAGES/phpmyadmin.mo b/vendor/phpmyadmin/motranslator/tests/data/locale/cs/LC_MESSAGES/phpmyadmin.mo new file mode 100644 index 0000000000000000000000000000000000000000..1d838852dabe02c87f5a4ab2a11221a3094923ac GIT binary patch literal 332023 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%0Aa8j(F#9K-Lw%g? z`nEU=eB9<#`K7e}eiA}!BP?}G5W8aJs%XMtmA*AM9~4fcJc1LclY$ufVSFkZNw!gS zYXw^Jp|S{QlnfiDM^N=wPIY?`Lh2T0qT4d`?v8IZB~3P>u!PSB&?xp8TJ1&?m#G(v zxjQfj^4#_!=F34!eSZ;)BVuSeOuh$Q$|Z%T%^E(pgLZXJ!k^1(lc*|7e()tg6g(t3 z`hBR_;f!V|U5?nub_Tb^*8T`ipW7GA4!3w*;= zW$VL#L)NL#)rqp-pN|eGl+kG{hJ~eo0 zyjCO?WL46YdjAvan#lohNTCwfys;T~I9m!n2p@3Jg&?B*+@vro$=Ke*NXe$SsRS^N zia>o|XgPZ&)Tb^3>xOhIhBW=eEnqnr?~Z00!|B-)=n(}n*0_M6u1tqg8{r?V$mK+v zmsBQTAnMqyiYsl8t}9oR7|08U3UYzlRIF%XEY9qQP80z04%QV+p6FQ_~< zKM$t!&R$Uu#2^^xSzZNSLVws2*v*wU=cmk+tAmIv{F#JU zp~^dOehE3i34cqM zjF54DFupfhnO!`Ds{e|O!dNre3G?|4E)(tp}@d0nM%OM2hCv z$n}G2d*$i)^}SK__S`vOqthGe;xz0D*{4s#Os|YnAYfl18_Rxy2`*oLm`vUyagl=$ zUBEB4xD$fHANh` zLcio;`7Wv_SM()`U?l}q=c`AA2Kz*?u~A5|IX$T+UY35Pm69siZIS`he&boYxxVx} zVYRTbxp*#InE7fD3`uMi=p}**vnVGVckZa>-)(h-rVo2xiq1oWq=V8TRi>C0T5On% zZ$(^i7XjkB-cw_Tj1UQJc_g39s(noamlXA#{I(nU+5Up~M z{T)Vn(hz5(8@MCm8P-?{gl5PY-w+RlCLDl~9(Be|Acd5}H2!R+v9Sxq87YONb25l| zL&0#pMk40H{7eikUL3$^1Xq=7@7MPA?3n3j2o+&kYX$l5xyUH^@iX1Dk6YpO87;@XCcShkb$)DC|`mCvIOV2Kz|`1IQbW0;P|a(V)e%)LevA#cJ9hjQNKL(@2Oa`UD1ci4rZan&TWri!c_FZ=|p=aiKBad;^G~=QaCV76t8i=OI!M>I1 z5%s7RCL$x5qA_Yss^p+|w`@-di0^%w!dfhU8EYa|k<|1M!A=PWj5yIE_9-qXTPtj; zTSo*t`unQEk#%k%$VXA=DQ%Nl$BONI7(hj&?enC^*|gOVsg??gWhlWN2^n04EPj$m$o~ju9sv zb%wukl#rAW9u?Et!cOlqwdPBj^C;3v;LaR2S8K-upsj>DASXp|+hu31tTZ>}gM)Dv ztD}G*HH$%^7_11pc1}urESg`89>a*iZk;J*_8Z(#Q~n+bx~dhNuBde5Q1BnA4m>tB zOw9Y%`~4GXQx9a?1={09u^ZuF=`w@-+fmA{am$#geHADTs;xY=fX&;4fP63Rx0C<1 z?&7{zBpA@|jlfx21~Y(yx9|u=lIA?pG$4*q#C;|6Pw0W%_gVMzqv-`nrSaWnQc5Zg zdXlm^c`&rJMnR9CBTPYul&7jWs@6xH^~=A))%7)KZmy^4$_@(09UT8S28Z*9C<)mx zC7Qv;Ge*ll@gfizDq}gl_g|fwRg_$|cAwk+*2SJ4jjc}&R>{gL5%|A9JY!4xn$Stk zqz56_k+l?)CJk_Yp;(j%0DpA)RS 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�_OymZPoaB=`R=7nNkamvbT_eo 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 literal 0 HcmV?d00001 diff --git a/vendor/phpmyadmin/motranslator/tests/data/noheader.mo b/vendor/phpmyadmin/motranslator/tests/data/noheader.mo new file mode 100644 index 0000000000000000000000000000000000000000..599315c926bfcc305d1115404581a11863b3c0a7 GIT binary patch literal 190 zcmca7#4?ou2$+Fb28d07m=%b9fLH{G6M&cvh)aPO#IFHjc_5w$#4JF(5s2A=cpDId z%m4uqI5+yPK literal 0 HcmV?d00001 diff --git a/vendor/phpmyadmin/motranslator/tests/data/not-translated/fpd1.mo b/vendor/phpmyadmin/motranslator/tests/data/not-translated/fpd1.mo new file mode 100644 index 0000000000000000000000000000000000000000..031ce0826b6b96adc53ecbd520af56e5d568d885 GIT binary patch literal 30 Wcmca7#4?qGfq{V$h*_XG1r7j1H3fqJ literal 0 HcmV?d00001 diff --git a/vendor/phpmyadmin/motranslator/tests/data/not-translated/invalid-equation.mo b/vendor/phpmyadmin/motranslator/tests/data/not-translated/invalid-equation.mo new file mode 100644 index 0000000000000000000000000000000000000000..69788dfbc7878f92d803605e196a1aa57501a9ca GIT binary patch literal 158 zcmca7#4?ou2pEA_28dOFm>Gz5fEWZUfH(z+ErA%M1`eF_^GZ_lN_0ai3sS8VN>VFI z^b2wlGxMw!k~0#Eic?E$LqptjEw}=5N{bS6blvica*M4L@(RG*Vq0Tt1qjntBhS{> cP*cHP!9c-EK_k!3)<{83O(D<5)`W`z0Et;5N&o-= literal 0 HcmV?d00001 diff --git a/vendor/phpmyadmin/motranslator/tests/data/plurals.mo b/vendor/phpmyadmin/motranslator/tests/data/plurals.mo new file mode 100644 index 0000000000000000000000000000000000000000..8885bb609083cb34d10fc95f9df51d43ce80c8f7 GIT binary patch literal 332023 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%0Aa8j(F#9K-Lw%g? z`nEU=eB9<#`K7e}eiA}!BP?}G5W8aJs%XMtmA*AM9~4fcJc1LclY$ufVSFkZNw!gS zYXw^Jp|S{QlnfiDM^N=wPIY?`Lh2T0qT4d`?v8IZB~3P>u!PSB&?xp8TJ1&?m#G(v zxjQfj^4#_!=F34!eSZ;)BVuSeOuh$Q$|Z%T%^E(pgLZXJ!k^1(lc*|7e()tg6g(t3 z`hBR_;f!V|U5?nub_Tb^*8T`ipW7GA4!3w*;= zW$VL#L)NL#)rqp-pN|eGl+kG{hJ~eo0 zyjCO?WL46YdjAvan#lohNTCwfys;T~I9m!n2p@3Jg&?B*+@vro$=Ke*NXe$SsRS^N zia>o|XgPZ&)Tb^3>xOhIhBW=eEnqnr?~Z00!|B-)=n(}n*0_M6u1tqg8{r?V$mK+v zmsBQTAnMqyiYsl8t}9oR7|08U3UYzlRIF%XEY9qQP80z04%QV+p6FQ_~< zKM$t!&R$Uu#2^^xSzZNSLVws2*v*wU=cmk+tAmIv{F#JU zp~^dOehE3i34cqM zjF54DFupfhnO!`Ds{e|O!dNre3G?|4E)(tp}@d0nM%OM2hCv z$n}G2d*$i)^}SK__S`vOqthGe;xz0D*{4s#Os|YnAYfl18_Rxy2`*oLm`vUyagl=$ zUBEB4xD$fHANh` zLcio;`7Wv_SM()`U?l}q=c`AA2Kz*?u~A5|IX$T+UY35Pm69siZIS`he&boYxxVx} zVYRTbxp*#InE7fD3`uMi=p}**vnVGVckZa>-)(h-rVo2xiq1oWq=V8TRi>C0T5On% zZ$(^i7XjkB-cw_Tj1UQJc_g39s(noamlXA#{I(nU+5Up~M z{T)Vn(hz5(8@MCm8P-?{gl5PY-w+RlCLDl~9(Be|Acd5}H2!R+v9Sxq87YONb25l| zL&0#pMk40H{7eikUL3$^1Xq=7@7MPA?3n3j2o+&kYX$l5xyUH^@iX1Dk6YpO87;@XCcShkb$)DC|`mCvIOV2Kz|`1IQbW0;P|a(V)e%)LevA#cJ9hjQNKL(@2Oa`UD1ci4rZan&TWri!c_FZ=|p=aiKBad;^G~=QaCV76t8i=OI!M>I1 z5%s7RCL$x5qA_Yss^p+|w`@-di0^%w!dfhU8EYa|k<|1M!A=PWj5yIE_9-qXTPtj; zTSo*t`unQEk#%k%$VXA=DQ%Nl$BONI7(hj&?enC^*|gOVsg??gWhlWN2^n04EPj$m$o~ju9sv zb%wukl#rAW9u?Et!cOlqwdPBj^C;3v;LaR2S8K-upsj>DASXp|+hu31tTZ>}gM)Dv ztD}G*HH$%^7_11pc1}urESg`89>a*iZk;J*_8Z(#Q~n+bx~dhNuBde5Q1BnA4m>tB zOw9Y%`~4GXQx9a?1={09u^ZuF=`w@-+fmA{am$#geHADTs;xY=fX&;4fP63Rx0C<1 z?&7{zBpA@|jlfx21~Y(yx9|u=lIA?pG$4*q#C;|6Pw0W%_gVMzqv-`nrSaWnQc5Zg zdXlm^c`&rJMnR9CBTPYul&7jWs@6xH^~=A))%7)KZmy^4$_@(09UT8S28Z*9C<)mx zC7Qv;Ge*ll@gfizDq}gl_g|fwRg_$|cAwk+*2SJ4jjc}&R>{gL5%|A9JY!4xn$Stk zqz56_k+l?)CJk_Yp;(j%0DpA)RS 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�_OymZPoaB=`R=7nNkamvbT_eo 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 literal 0 HcmV?d00001 diff --git a/vendor/psr/cache/CHANGELOG.md b/vendor/psr/cache/CHANGELOG.md new file mode 100644 index 0000000..58ddab0 --- /dev/null +++ b/vendor/psr/cache/CHANGELOG.md @@ -0,0 +1,16 @@ +# Changelog + +All notable changes to this project will be documented in this file, in reverse chronological order by release. + +## 1.0.1 - 2016-08-06 + +### Fixed + +- Make spacing consistent in phpdoc annotations php-fig/cache#9 - chalasr +- Fix grammar in phpdoc annotations php-fig/cache#10 - chalasr +- Be more specific in docblocks that `getItems()` and `deleteItems()` take an array of strings (`string[]`) compared to just `array` php-fig/cache#8 - GrahamCampbell +- For `expiresAt()` and `expiresAfter()` in CacheItemInterface fix docblock to specify null as a valid parameters as well as an implementation of DateTimeInterface php-fig/cache#7 - GrahamCampbell + +## 1.0.0 - 2015-12-11 + +Initial stable release; reflects accepted PSR-6 specification diff --git a/vendor/psr/cache/LICENSE.txt b/vendor/psr/cache/LICENSE.txt new file mode 100644 index 0000000..b1c2c97 --- /dev/null +++ b/vendor/psr/cache/LICENSE.txt @@ -0,0 +1,19 @@ +Copyright (c) 2015 PHP Framework Interoperability Group + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/psr/cache/README.md b/vendor/psr/cache/README.md new file mode 100644 index 0000000..9855a31 --- /dev/null +++ b/vendor/psr/cache/README.md @@ -0,0 +1,12 @@ +Caching Interface +============== + +This repository holds all interfaces related to [PSR-6 (Caching Interface)][psr-url]. + +Note that this is not a Caching implementation of its own. It is merely interfaces that describe the components of a Caching mechanism. + +The installable [package][package-url] and [implementations][implementation-url] are listed on Packagist. + +[psr-url]: https://www.php-fig.org/psr/psr-6/ +[package-url]: https://packagist.org/packages/psr/cache +[implementation-url]: https://packagist.org/providers/psr/cache-implementation diff --git a/vendor/psr/cache/composer.json b/vendor/psr/cache/composer.json new file mode 100644 index 0000000..4b68797 --- /dev/null +++ b/vendor/psr/cache/composer.json @@ -0,0 +1,25 @@ +{ + "name": "psr/cache", + "description": "Common interface for caching libraries", + "keywords": ["psr", "psr-6", "cache"], + "license": "MIT", + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "require": { + "php": ">=8.0.0" + }, + "autoload": { + "psr-4": { + "Psr\\Cache\\": "src/" + } + }, + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + } +} diff --git a/vendor/psr/cache/src/CacheException.php b/vendor/psr/cache/src/CacheException.php new file mode 100644 index 0000000..bb785f4 --- /dev/null +++ b/vendor/psr/cache/src/CacheException.php @@ -0,0 +1,10 @@ +=7.4.0" + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + } +} diff --git a/vendor/psr/container/src/ContainerExceptionInterface.php b/vendor/psr/container/src/ContainerExceptionInterface.php new file mode 100644 index 0000000..0f213f2 --- /dev/null +++ b/vendor/psr/container/src/ContainerExceptionInterface.php @@ -0,0 +1,12 @@ +logger = $logger; + } + + public function doSomething() + { + if ($this->logger) { + $this->logger->info('Doing work'); + } + + try { + $this->doSomethingElse(); + } catch (Exception $exception) { + $this->logger->error('Oh no!', array('exception' => $exception)); + } + + // do something useful + } +} +``` + +You can then pick one of the implementations of the interface to get a logger. + +If you want to implement the interface, you can require this package and +implement `Psr\Log\LoggerInterface` in your code. Please read the +[specification text](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md) +for details. diff --git a/vendor/psr/log/composer.json b/vendor/psr/log/composer.json new file mode 100644 index 0000000..879fc6f --- /dev/null +++ b/vendor/psr/log/composer.json @@ -0,0 +1,26 @@ +{ + "name": "psr/log", + "description": "Common interface for logging libraries", + "keywords": ["psr", "psr-3", "log"], + "homepage": "https://github.com/php-fig/log", + "license": "MIT", + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "require": { + "php": ">=8.0.0" + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "src" + } + }, + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + } +} diff --git a/vendor/psr/log/src/AbstractLogger.php b/vendor/psr/log/src/AbstractLogger.php new file mode 100644 index 0000000..d60a091 --- /dev/null +++ b/vendor/psr/log/src/AbstractLogger.php @@ -0,0 +1,15 @@ +logger = $logger; + } +} diff --git a/vendor/psr/log/src/LoggerInterface.php b/vendor/psr/log/src/LoggerInterface.php new file mode 100644 index 0000000..cb4cf64 --- /dev/null +++ b/vendor/psr/log/src/LoggerInterface.php @@ -0,0 +1,98 @@ +log(LogLevel::EMERGENCY, $message, $context); + } + + /** + * Action must be taken immediately. + * + * Example: Entire website down, database unavailable, etc. This should + * trigger the SMS alerts and wake you up. + */ + public function alert(string|\Stringable $message, array $context = []): void + { + $this->log(LogLevel::ALERT, $message, $context); + } + + /** + * Critical conditions. + * + * Example: Application component unavailable, unexpected exception. + */ + public function critical(string|\Stringable $message, array $context = []): void + { + $this->log(LogLevel::CRITICAL, $message, $context); + } + + /** + * Runtime errors that do not require immediate action but should typically + * be logged and monitored. + */ + public function error(string|\Stringable $message, array $context = []): void + { + $this->log(LogLevel::ERROR, $message, $context); + } + + /** + * Exceptional occurrences that are not errors. + * + * Example: Use of deprecated APIs, poor use of an API, undesirable things + * that are not necessarily wrong. + */ + public function warning(string|\Stringable $message, array $context = []): void + { + $this->log(LogLevel::WARNING, $message, $context); + } + + /** + * Normal but significant events. + */ + public function notice(string|\Stringable $message, array $context = []): void + { + $this->log(LogLevel::NOTICE, $message, $context); + } + + /** + * Interesting events. + * + * Example: User logs in, SQL logs. + */ + public function info(string|\Stringable $message, array $context = []): void + { + $this->log(LogLevel::INFO, $message, $context); + } + + /** + * Detailed debug information. + */ + public function debug(string|\Stringable $message, array $context = []): void + { + $this->log(LogLevel::DEBUG, $message, $context); + } + + /** + * Logs with an arbitrary level. + * + * @param mixed $level + * + * @throws \Psr\Log\InvalidArgumentException + */ + abstract public function log($level, string|\Stringable $message, array $context = []): void; +} diff --git a/vendor/psr/log/src/NullLogger.php b/vendor/psr/log/src/NullLogger.php new file mode 100644 index 0000000..de0561e --- /dev/null +++ b/vendor/psr/log/src/NullLogger.php @@ -0,0 +1,26 @@ +logger) { }` + * blocks. + */ +class NullLogger extends AbstractLogger +{ + /** + * Logs with an arbitrary level. + * + * @param mixed[] $context + * + * @throws \Psr\Log\InvalidArgumentException + */ + public function log($level, string|\Stringable $message, array $context = []): void + { + // noop + } +} diff --git a/vendor/symfony/cache-contracts/CHANGELOG.md b/vendor/symfony/cache-contracts/CHANGELOG.md new file mode 100644 index 0000000..7932e26 --- /dev/null +++ b/vendor/symfony/cache-contracts/CHANGELOG.md @@ -0,0 +1,5 @@ +CHANGELOG +========= + +The changelog is maintained for all Symfony contracts at the following URL: +https://github.com/symfony/contracts/blob/main/CHANGELOG.md diff --git a/vendor/symfony/cache-contracts/CacheInterface.php b/vendor/symfony/cache-contracts/CacheInterface.php new file mode 100644 index 0000000..3e4aaf6 --- /dev/null +++ b/vendor/symfony/cache-contracts/CacheInterface.php @@ -0,0 +1,59 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Contracts\Cache; + +use Psr\Cache\CacheItemInterface; +use Psr\Cache\InvalidArgumentException; + +/** + * Covers most simple to advanced caching needs. + * + * @author Nicolas Grekas + */ +interface CacheInterface +{ + /** + * Fetches a value from the pool or computes it if not found. + * + * On cache misses, a callback is called that should return the missing value. + * This callback is given a PSR-6 CacheItemInterface instance corresponding to the + * requested key, that could be used e.g. for expiration control. It could also + * be an ItemInterface instance when its additional features are needed. + * + * @template T + * + * @param string $key The key of the item to retrieve from the cache + * @param (callable(CacheItemInterface,bool):T)|(callable(ItemInterface,bool):T)|CallbackInterface $callback + * @param float|null $beta A float that, as it grows, controls the likeliness of triggering + * early expiration. 0 disables it, INF forces immediate expiration. + * The default (or providing null) is implementation dependent but should + * typically be 1.0, which should provide optimal stampede protection. + * See https://en.wikipedia.org/wiki/Cache_stampede#Probabilistic_early_expiration + * @param array &$metadata The metadata of the cached item {@see ItemInterface::getMetadata()} + * + * @return T + * + * @throws InvalidArgumentException When $key is not valid or when $beta is negative + */ + public function get(string $key, callable $callback, ?float $beta = null, ?array &$metadata = null): mixed; + + /** + * Removes an item from the pool. + * + * @param string $key The key to delete + * + * @return bool True if the item was successfully removed, false if there was any error + * + * @throws InvalidArgumentException When $key is not valid + */ + public function delete(string $key): bool; +} diff --git a/vendor/symfony/cache-contracts/CacheTrait.php b/vendor/symfony/cache-contracts/CacheTrait.php new file mode 100644 index 0000000..c2f6580 --- /dev/null +++ b/vendor/symfony/cache-contracts/CacheTrait.php @@ -0,0 +1,72 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Contracts\Cache; + +use Psr\Cache\CacheItemPoolInterface; +use Psr\Cache\InvalidArgumentException; +use Psr\Log\LoggerInterface; + +// Help opcache.preload discover always-needed symbols +class_exists(InvalidArgumentException::class); + +/** + * An implementation of CacheInterface for PSR-6 CacheItemPoolInterface classes. + * + * @author Nicolas Grekas + */ +trait CacheTrait +{ + public function get(string $key, callable $callback, ?float $beta = null, ?array &$metadata = null): mixed + { + return $this->doGet($this, $key, $callback, $beta, $metadata); + } + + public function delete(string $key): bool + { + return $this->deleteItem($key); + } + + private function doGet(CacheItemPoolInterface $pool, string $key, callable $callback, ?float $beta, ?array &$metadata = null, ?LoggerInterface $logger = null): mixed + { + if (0 > $beta ??= 1.0) { + throw new class(sprintf('Argument "$beta" provided to "%s::get()" must be a positive number, %f given.', static::class, $beta)) extends \InvalidArgumentException implements InvalidArgumentException {}; + } + + $item = $pool->getItem($key); + $recompute = !$item->isHit() || \INF === $beta; + $metadata = $item instanceof ItemInterface ? $item->getMetadata() : []; + + if (!$recompute && $metadata) { + $expiry = $metadata[ItemInterface::METADATA_EXPIRY] ?? false; + $ctime = $metadata[ItemInterface::METADATA_CTIME] ?? false; + + if ($recompute = $ctime && $expiry && $expiry <= ($now = microtime(true)) - $ctime / 1000 * $beta * log(random_int(1, \PHP_INT_MAX) / \PHP_INT_MAX)) { + // force applying defaultLifetime to expiry + $item->expiresAt(null); + $logger?->info('Item "{key}" elected for early recomputation {delta}s before its expiration', [ + 'key' => $key, + 'delta' => sprintf('%.1f', $expiry - $now), + ]); + } + } + + if ($recompute) { + $save = true; + $item->set($callback($item, $save)); + if ($save) { + $pool->save($item); + } + } + + return $item->get(); + } +} diff --git a/vendor/symfony/cache-contracts/CallbackInterface.php b/vendor/symfony/cache-contracts/CallbackInterface.php new file mode 100644 index 0000000..15941e9 --- /dev/null +++ b/vendor/symfony/cache-contracts/CallbackInterface.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Contracts\Cache; + +use Psr\Cache\CacheItemInterface; + +/** + * Computes and returns the cached value of an item. + * + * @author Nicolas Grekas + * + * @template T + */ +interface CallbackInterface +{ + /** + * @param CacheItemInterface|ItemInterface $item The item to compute the value for + * @param bool &$save Should be set to false when the value should not be saved in the pool + * + * @return T The computed value for the passed item + */ + public function __invoke(CacheItemInterface $item, bool &$save): mixed; +} diff --git a/vendor/symfony/cache-contracts/ItemInterface.php b/vendor/symfony/cache-contracts/ItemInterface.php new file mode 100644 index 0000000..8c4c512 --- /dev/null +++ b/vendor/symfony/cache-contracts/ItemInterface.php @@ -0,0 +1,65 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Contracts\Cache; + +use Psr\Cache\CacheException; +use Psr\Cache\CacheItemInterface; +use Psr\Cache\InvalidArgumentException; + +/** + * Augments PSR-6's CacheItemInterface with support for tags and metadata. + * + * @author Nicolas Grekas + */ +interface ItemInterface extends CacheItemInterface +{ + /** + * References the Unix timestamp stating when the item will expire. + */ + public const METADATA_EXPIRY = 'expiry'; + + /** + * References the time the item took to be created, in milliseconds. + */ + public const METADATA_CTIME = 'ctime'; + + /** + * References the list of tags that were assigned to the item, as string[]. + */ + public const METADATA_TAGS = 'tags'; + + /** + * Reserved characters that cannot be used in a key or tag. + */ + public const RESERVED_CHARACTERS = '{}()/\@:'; + + /** + * Adds a tag to a cache item. + * + * Tags are strings that follow the same validation rules as keys. + * + * @param string|string[] $tags A tag or array of tags + * + * @return $this + * + * @throws InvalidArgumentException When $tag is not valid + * @throws CacheException When the item comes from a pool that is not tag-aware + */ + public function tag(string|iterable $tags): static; + + /** + * Returns a list of metadata info that were saved alongside with the cached value. + * + * See ItemInterface::METADATA_* consts for keys potentially found in the returned array. + */ + public function getMetadata(): array; +} diff --git a/vendor/symfony/cache-contracts/LICENSE b/vendor/symfony/cache-contracts/LICENSE new file mode 100644 index 0000000..7536cae --- /dev/null +++ b/vendor/symfony/cache-contracts/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2018-present Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/symfony/cache-contracts/README.md b/vendor/symfony/cache-contracts/README.md new file mode 100644 index 0000000..ffe0833 --- /dev/null +++ b/vendor/symfony/cache-contracts/README.md @@ -0,0 +1,9 @@ +Symfony Cache Contracts +======================= + +A set of abstractions extracted out of the Symfony components. + +Can be used to build on semantics that the Symfony components proved useful and +that already have battle tested implementations. + +See https://github.com/symfony/contracts/blob/main/README.md for more information. diff --git a/vendor/symfony/cache-contracts/TagAwareCacheInterface.php b/vendor/symfony/cache-contracts/TagAwareCacheInterface.php new file mode 100644 index 0000000..8e0b6be --- /dev/null +++ b/vendor/symfony/cache-contracts/TagAwareCacheInterface.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Contracts\Cache; + +use Psr\Cache\InvalidArgumentException; + +/** + * Allows invalidating cached items using tags. + * + * @author Nicolas Grekas + */ +interface TagAwareCacheInterface extends CacheInterface +{ + /** + * Invalidates cached items using tags. + * + * When implemented on a PSR-6 pool, invalidation should not apply + * to deferred items. Instead, they should be committed as usual. + * This allows replacing old tagged values by new ones without + * race conditions. + * + * @param string[] $tags An array of tags to invalidate + * + * @return bool True on success + * + * @throws InvalidArgumentException When $tags is not valid + */ + public function invalidateTags(array $tags): bool; +} diff --git a/vendor/symfony/cache-contracts/composer.json b/vendor/symfony/cache-contracts/composer.json new file mode 100644 index 0000000..fe261d1 --- /dev/null +++ b/vendor/symfony/cache-contracts/composer.json @@ -0,0 +1,35 @@ +{ + "name": "symfony/cache-contracts", + "type": "library", + "description": "Generic abstractions related to caching", + "keywords": ["abstractions", "contracts", "decoupling", "interfaces", "interoperability", "standards"], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": ">=8.1", + "psr/cache": "^3.0" + }, + "autoload": { + "psr-4": { "Symfony\\Contracts\\Cache\\": "" } + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-main": "3.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + } +} diff --git a/vendor/symfony/cache/Adapter/AbstractAdapter.php b/vendor/symfony/cache/Adapter/AbstractAdapter.php new file mode 100644 index 0000000..c03868d --- /dev/null +++ b/vendor/symfony/cache/Adapter/AbstractAdapter.php @@ -0,0 +1,191 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Adapter; + +use Psr\Log\LoggerAwareInterface; +use Psr\Log\LoggerInterface; +use Symfony\Component\Cache\CacheItem; +use Symfony\Component\Cache\Exception\InvalidArgumentException; +use Symfony\Component\Cache\ResettableInterface; +use Symfony\Component\Cache\Traits\AbstractAdapterTrait; +use Symfony\Component\Cache\Traits\ContractsTrait; +use Symfony\Contracts\Cache\CacheInterface; + +/** + * @author Nicolas Grekas + */ +abstract class AbstractAdapter implements AdapterInterface, CacheInterface, LoggerAwareInterface, ResettableInterface +{ + use AbstractAdapterTrait; + use ContractsTrait; + + /** + * @internal + */ + protected const NS_SEPARATOR = ':'; + + private static bool $apcuSupported; + + protected function __construct(string $namespace = '', int $defaultLifetime = 0) + { + $this->namespace = '' === $namespace ? '' : CacheItem::validateKey($namespace).static::NS_SEPARATOR; + $this->defaultLifetime = $defaultLifetime; + if (null !== $this->maxIdLength && \strlen($namespace) > $this->maxIdLength - 24) { + throw new InvalidArgumentException(\sprintf('Namespace must be %d chars max, %d given ("%s").', $this->maxIdLength - 24, \strlen($namespace), $namespace)); + } + self::$createCacheItem ??= \Closure::bind( + static function ($key, $value, $isHit) { + $item = new CacheItem(); + $item->key = $key; + $item->value = $value; + $item->isHit = $isHit; + $item->unpack(); + + return $item; + }, + null, + CacheItem::class + ); + self::$mergeByLifetime ??= \Closure::bind( + static function ($deferred, $namespace, &$expiredIds, $getId, $defaultLifetime) { + $byLifetime = []; + $now = microtime(true); + $expiredIds = []; + + foreach ($deferred as $key => $item) { + $key = (string) $key; + if (null === $item->expiry) { + $ttl = 0 < $defaultLifetime ? $defaultLifetime : 0; + } elseif (!$item->expiry) { + $ttl = 0; + } elseif (0 >= $ttl = (int) (0.1 + $item->expiry - $now)) { + $expiredIds[] = $getId($key); + continue; + } + $byLifetime[$ttl][$getId($key)] = $item->pack(); + } + + return $byLifetime; + }, + null, + CacheItem::class + ); + } + + /** + * Returns the best possible adapter that your runtime supports. + * + * Using ApcuAdapter makes system caches compatible with read-only filesystems. + */ + public static function createSystemCache(string $namespace, int $defaultLifetime, string $version, string $directory, ?LoggerInterface $logger = null): AdapterInterface + { + $opcache = new PhpFilesAdapter($namespace, $defaultLifetime, $directory, true); + if (null !== $logger) { + $opcache->setLogger($logger); + } + + if (!self::$apcuSupported ??= ApcuAdapter::isSupported()) { + return $opcache; + } + + if ('cli' === \PHP_SAPI && !filter_var(\ini_get('apc.enable_cli'), \FILTER_VALIDATE_BOOL)) { + return $opcache; + } + + $apcu = new ApcuAdapter($namespace, intdiv($defaultLifetime, 5), $version); + if (null !== $logger) { + $apcu->setLogger($logger); + } + + return new ChainAdapter([$apcu, $opcache]); + } + + public static function createConnection(#[\SensitiveParameter] string $dsn, array $options = []): mixed + { + if (str_starts_with($dsn, 'redis:') || str_starts_with($dsn, 'rediss:')) { + return RedisAdapter::createConnection($dsn, $options); + } + if (str_starts_with($dsn, 'memcached:')) { + return MemcachedAdapter::createConnection($dsn, $options); + } + if (str_starts_with($dsn, 'couchbase:')) { + if (class_exists('CouchbaseBucket') && CouchbaseBucketAdapter::isSupported()) { + return CouchbaseBucketAdapter::createConnection($dsn, $options); + } + + return CouchbaseCollectionAdapter::createConnection($dsn, $options); + } + if (preg_match('/^(mysql|oci|pgsql|sqlsrv|sqlite):/', $dsn)) { + return PdoAdapter::createConnection($dsn, $options); + } + + throw new InvalidArgumentException('Unsupported DSN: it does not start with "redis[s]:", "memcached:", "couchbase:", "mysql:", "oci:", "pgsql:", "sqlsrv:" nor "sqlite:".'); + } + + public function commit(): bool + { + $ok = true; + $byLifetime = (self::$mergeByLifetime)($this->deferred, $this->namespace, $expiredIds, $this->getId(...), $this->defaultLifetime); + $retry = $this->deferred = []; + + if ($expiredIds) { + try { + $this->doDelete($expiredIds); + } catch (\Exception $e) { + $ok = false; + CacheItem::log($this->logger, 'Failed to delete expired items: '.$e->getMessage(), ['exception' => $e, 'cache-adapter' => get_debug_type($this)]); + } + } + foreach ($byLifetime as $lifetime => $values) { + try { + $e = $this->doSave($values, $lifetime); + } catch (\Exception $e) { + } + if (true === $e || [] === $e) { + continue; + } + if (\is_array($e) || 1 === \count($values)) { + foreach (\is_array($e) ? $e : array_keys($values) as $id) { + $ok = false; + $v = $values[$id]; + $type = get_debug_type($v); + $message = \sprintf('Failed to save key "{key}" of type %s%s', $type, $e instanceof \Exception ? ': '.$e->getMessage() : '.'); + CacheItem::log($this->logger, $message, ['key' => substr($id, \strlen($this->namespace)), 'exception' => $e instanceof \Exception ? $e : null, 'cache-adapter' => get_debug_type($this)]); + } + } else { + foreach ($values as $id => $v) { + $retry[$lifetime][] = $id; + } + } + } + + // When bulk-save failed, retry each item individually + foreach ($retry as $lifetime => $ids) { + foreach ($ids as $id) { + try { + $v = $byLifetime[$lifetime][$id]; + $e = $this->doSave([$id => $v], $lifetime); + } catch (\Exception $e) { + } + if (true === $e || [] === $e) { + continue; + } + $ok = false; + $type = get_debug_type($v); + $message = \sprintf('Failed to save key "{key}" of type %s%s', $type, $e instanceof \Exception ? ': '.$e->getMessage() : '.'); + CacheItem::log($this->logger, $message, ['key' => substr($id, \strlen($this->namespace)), 'exception' => $e instanceof \Exception ? $e : null, 'cache-adapter' => get_debug_type($this)]); + } + } + + return $ok; + } +} diff --git a/vendor/symfony/cache/Adapter/AbstractTagAwareAdapter.php b/vendor/symfony/cache/Adapter/AbstractTagAwareAdapter.php new file mode 100644 index 0000000..822c30f --- /dev/null +++ b/vendor/symfony/cache/Adapter/AbstractTagAwareAdapter.php @@ -0,0 +1,320 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Adapter; + +use Psr\Log\LoggerAwareInterface; +use Symfony\Component\Cache\CacheItem; +use Symfony\Component\Cache\Exception\InvalidArgumentException; +use Symfony\Component\Cache\ResettableInterface; +use Symfony\Component\Cache\Traits\AbstractAdapterTrait; +use Symfony\Component\Cache\Traits\ContractsTrait; +use Symfony\Contracts\Cache\TagAwareCacheInterface; + +/** + * Abstract for native TagAware adapters. + * + * To keep info on tags, the tags are both serialized as part of cache value and provided as tag ids + * to Adapters on operations when needed for storage to doSave(), doDelete() & doInvalidate(). + * + * @author Nicolas Grekas + * @author AndrĆ© RĆømcke + * + * @internal + */ +abstract class AbstractTagAwareAdapter implements TagAwareAdapterInterface, TagAwareCacheInterface, LoggerAwareInterface, ResettableInterface +{ + use AbstractAdapterTrait; + use ContractsTrait; + + private const TAGS_PREFIX = "\1tags\1"; + + protected function __construct(string $namespace = '', int $defaultLifetime = 0) + { + $this->namespace = '' === $namespace ? '' : CacheItem::validateKey($namespace).':'; + $this->defaultLifetime = $defaultLifetime; + if (null !== $this->maxIdLength && \strlen($namespace) > $this->maxIdLength - 24) { + throw new InvalidArgumentException(\sprintf('Namespace must be %d chars max, %d given ("%s").', $this->maxIdLength - 24, \strlen($namespace), $namespace)); + } + self::$createCacheItem ??= \Closure::bind( + static function ($key, $value, $isHit) { + $item = new CacheItem(); + $item->key = $key; + $item->isTaggable = true; + // If structure does not match what we expect return item as is (no value and not a hit) + if (!\is_array($value) || !\array_key_exists('value', $value)) { + return $item; + } + $item->isHit = $isHit; + // Extract value, tags and meta data from the cache value + $item->value = $value['value']; + $item->metadata[CacheItem::METADATA_TAGS] = isset($value['tags']) ? array_combine($value['tags'], $value['tags']) : []; + if (isset($value['meta'])) { + // For compactness these values are packed, & expiry is offset to reduce size + $v = unpack('Ve/Nc', $value['meta']); + $item->metadata[CacheItem::METADATA_EXPIRY] = $v['e'] + CacheItem::METADATA_EXPIRY_OFFSET; + $item->metadata[CacheItem::METADATA_CTIME] = $v['c']; + } + + return $item; + }, + null, + CacheItem::class + ); + self::$mergeByLifetime ??= \Closure::bind( + static function ($deferred, &$expiredIds, $getId, $tagPrefix, $defaultLifetime) { + $byLifetime = []; + $now = microtime(true); + $expiredIds = []; + + foreach ($deferred as $key => $item) { + $key = (string) $key; + if (null === $item->expiry) { + $ttl = 0 < $defaultLifetime ? $defaultLifetime : 0; + } elseif (!$item->expiry) { + $ttl = 0; + } elseif (0 >= $ttl = (int) (0.1 + $item->expiry - $now)) { + $expiredIds[] = $getId($key); + continue; + } + // Store Value and Tags on the cache value + if (isset(($metadata = $item->newMetadata)[CacheItem::METADATA_TAGS])) { + $value = ['value' => $item->value, 'tags' => $metadata[CacheItem::METADATA_TAGS]]; + unset($metadata[CacheItem::METADATA_TAGS]); + } else { + $value = ['value' => $item->value, 'tags' => []]; + } + + if ($metadata) { + // For compactness, expiry and creation duration are packed, using magic numbers as separators + $value['meta'] = pack('VN', (int) (0.1 + $metadata[CacheItem::METADATA_EXPIRY] - CacheItem::METADATA_EXPIRY_OFFSET), $metadata[CacheItem::METADATA_CTIME]); + } + + // Extract tag changes, these should be removed from values in doSave() + $value['tag-operations'] = ['add' => [], 'remove' => []]; + $oldTags = $item->metadata[CacheItem::METADATA_TAGS] ?? []; + foreach (array_diff_key($value['tags'], $oldTags) as $addedTag) { + $value['tag-operations']['add'][] = $getId($tagPrefix.$addedTag); + } + foreach (array_diff_key($oldTags, $value['tags']) as $removedTag) { + $value['tag-operations']['remove'][] = $getId($tagPrefix.$removedTag); + } + $value['tags'] = array_keys($value['tags']); + + $byLifetime[$ttl][$getId($key)] = $value; + $item->metadata = $item->newMetadata; + } + + return $byLifetime; + }, + null, + CacheItem::class + ); + } + + /** + * Persists several cache items immediately. + * + * @param array $values The values to cache, indexed by their cache identifier + * @param int $lifetime The lifetime of the cached values, 0 for persisting until manual cleaning + * @param array[] $addTagData Hash where key is tag id, and array value is list of cache id's to add to tag + * @param array[] $removeTagData Hash where key is tag id, and array value is list of cache id's to remove to tag + * + * @return array The identifiers that failed to be cached or a boolean stating if caching succeeded or not + */ + abstract protected function doSave(array $values, int $lifetime, array $addTagData = [], array $removeTagData = []): array; + + /** + * Removes multiple items from the pool and their corresponding tags. + * + * @param array $ids An array of identifiers that should be removed from the pool + */ + abstract protected function doDelete(array $ids): bool; + + /** + * Removes relations between tags and deleted items. + * + * @param array $tagData Array of tag => key identifiers that should be removed from the pool + */ + abstract protected function doDeleteTagRelations(array $tagData): bool; + + /** + * Invalidates cached items using tags. + * + * @param string[] $tagIds An array of tags to invalidate, key is tag and value is tag id + */ + abstract protected function doInvalidate(array $tagIds): bool; + + /** + * Delete items and yields the tags they were bound to. + */ + protected function doDeleteYieldTags(array $ids): iterable + { + foreach ($this->doFetch($ids) as $id => $value) { + yield $id => \is_array($value) && \is_array($value['tags'] ?? null) ? $value['tags'] : []; + } + + $this->doDelete($ids); + } + + public function commit(): bool + { + $ok = true; + $byLifetime = (self::$mergeByLifetime)($this->deferred, $expiredIds, $this->getId(...), self::TAGS_PREFIX, $this->defaultLifetime); + $retry = $this->deferred = []; + + if ($expiredIds) { + // Tags are not cleaned up in this case, however that is done on invalidateTags(). + try { + $this->doDelete($expiredIds); + } catch (\Exception $e) { + $ok = false; + CacheItem::log($this->logger, 'Failed to delete expired items: '.$e->getMessage(), ['exception' => $e, 'cache-adapter' => get_debug_type($this)]); + } + } + foreach ($byLifetime as $lifetime => $values) { + try { + $values = $this->extractTagData($values, $addTagData, $removeTagData); + $e = $this->doSave($values, $lifetime, $addTagData, $removeTagData); + } catch (\Exception $e) { + } + if ([] === $e) { + continue; + } + if (\is_array($e) || 1 === \count($values)) { + foreach (\is_array($e) ? $e : array_keys($values) as $id) { + $ok = false; + $v = $values[$id]; + $type = get_debug_type($v); + $message = \sprintf('Failed to save key "{key}" of type %s%s', $type, $e instanceof \Exception ? ': '.$e->getMessage() : '.'); + CacheItem::log($this->logger, $message, ['key' => substr($id, \strlen($this->namespace)), 'exception' => $e instanceof \Exception ? $e : null, 'cache-adapter' => get_debug_type($this)]); + } + } else { + foreach ($values as $id => $v) { + $retry[$lifetime][] = $id; + } + } + } + + // When bulk-save failed, retry each item individually + foreach ($retry as $lifetime => $ids) { + foreach ($ids as $id) { + try { + $v = $byLifetime[$lifetime][$id]; + $values = $this->extractTagData([$id => $v], $addTagData, $removeTagData); + $e = $this->doSave($values, $lifetime, $addTagData, $removeTagData); + } catch (\Exception $e) { + } + if ([] === $e) { + continue; + } + $ok = false; + $type = get_debug_type($v); + $message = \sprintf('Failed to save key "{key}" of type %s%s', $type, $e instanceof \Exception ? ': '.$e->getMessage() : '.'); + CacheItem::log($this->logger, $message, ['key' => substr($id, \strlen($this->namespace)), 'exception' => $e instanceof \Exception ? $e : null, 'cache-adapter' => get_debug_type($this)]); + } + } + + return $ok; + } + + public function deleteItems(array $keys): bool + { + if (!$keys) { + return true; + } + + $ok = true; + $ids = []; + $tagData = []; + + foreach ($keys as $key) { + $ids[$key] = $this->getId($key); + unset($this->deferred[$key]); + } + + try { + foreach ($this->doDeleteYieldTags(array_values($ids)) as $id => $tags) { + foreach ($tags as $tag) { + $tagData[$this->getId(self::TAGS_PREFIX.$tag)][] = $id; + } + } + } catch (\Exception) { + $ok = false; + } + + try { + if ((!$tagData || $this->doDeleteTagRelations($tagData)) && $ok) { + return true; + } + } catch (\Exception) { + } + + // When bulk-delete failed, retry each item individually + foreach ($ids as $key => $id) { + try { + $e = null; + if ($this->doDelete([$id])) { + continue; + } + } catch (\Exception $e) { + } + $message = 'Failed to delete key "{key}"'.($e instanceof \Exception ? ': '.$e->getMessage() : '.'); + CacheItem::log($this->logger, $message, ['key' => $key, 'exception' => $e, 'cache-adapter' => get_debug_type($this)]); + $ok = false; + } + + return $ok; + } + + public function invalidateTags(array $tags): bool + { + if (!$tags) { + return false; + } + + $tagIds = []; + foreach (array_unique($tags) as $tag) { + $tagIds[] = $this->getId(self::TAGS_PREFIX.$tag); + } + + try { + if ($this->doInvalidate($tagIds)) { + return true; + } + } catch (\Exception $e) { + CacheItem::log($this->logger, 'Failed to invalidate tags: '.$e->getMessage(), ['exception' => $e, 'cache-adapter' => get_debug_type($this)]); + } + + return false; + } + + /** + * Extracts tags operation data from $values set in mergeByLifetime, and returns values without it. + */ + private function extractTagData(array $values, ?array &$addTagData, ?array &$removeTagData): array + { + $addTagData = $removeTagData = []; + foreach ($values as $id => $value) { + foreach ($value['tag-operations']['add'] as $tag => $tagId) { + $addTagData[$tagId][] = $id; + } + + foreach ($value['tag-operations']['remove'] as $tag => $tagId) { + $removeTagData[$tagId][] = $id; + } + + unset($values[$id]['tag-operations']); + } + + return $values; + } +} diff --git a/vendor/symfony/cache/Adapter/AdapterInterface.php b/vendor/symfony/cache/Adapter/AdapterInterface.php new file mode 100644 index 0000000..e556720 --- /dev/null +++ b/vendor/symfony/cache/Adapter/AdapterInterface.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Adapter; + +use Psr\Cache\CacheItemPoolInterface; +use Symfony\Component\Cache\CacheItem; + +// Help opcache.preload discover always-needed symbols +class_exists(CacheItem::class); + +/** + * Interface for adapters managing instances of Symfony's CacheItem. + * + * @author KĆ©vin Dunglas + */ +interface AdapterInterface extends CacheItemPoolInterface +{ + public function getItem(mixed $key): CacheItem; + + /** + * @return iterable + */ + public function getItems(array $keys = []): iterable; + + public function clear(string $prefix = ''): bool; +} diff --git a/vendor/symfony/cache/Adapter/ApcuAdapter.php b/vendor/symfony/cache/Adapter/ApcuAdapter.php new file mode 100644 index 0000000..ddb7210 --- /dev/null +++ b/vendor/symfony/cache/Adapter/ApcuAdapter.php @@ -0,0 +1,116 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Adapter; + +use Symfony\Component\Cache\CacheItem; +use Symfony\Component\Cache\Exception\CacheException; +use Symfony\Component\Cache\Marshaller\MarshallerInterface; + +/** + * @author Nicolas Grekas + */ +class ApcuAdapter extends AbstractAdapter +{ + /** + * @throws CacheException if APCu is not enabled + */ + public function __construct( + string $namespace = '', + int $defaultLifetime = 0, + ?string $version = null, + private ?MarshallerInterface $marshaller = null, + ) { + if (!static::isSupported()) { + throw new CacheException('APCu is not enabled.'); + } + if ('cli' === \PHP_SAPI) { + ini_set('apc.use_request_time', 0); + } + parent::__construct($namespace, $defaultLifetime); + + if (null !== $version) { + CacheItem::validateKey($version); + + if (!apcu_exists($version.'@'.$namespace)) { + $this->doClear($namespace); + apcu_add($version.'@'.$namespace, null); + } + } + } + + public static function isSupported(): bool + { + return \function_exists('apcu_fetch') && filter_var(\ini_get('apc.enabled'), \FILTER_VALIDATE_BOOL); + } + + protected function doFetch(array $ids): iterable + { + $unserializeCallbackHandler = ini_set('unserialize_callback_func', __CLASS__.'::handleUnserializeCallback'); + try { + $values = []; + foreach (apcu_fetch($ids, $ok) ?: [] as $k => $v) { + if (null !== $v || $ok) { + $values[$k] = null !== $this->marshaller ? $this->marshaller->unmarshall($v) : $v; + } + } + + return $values; + } catch (\Error $e) { + throw new \ErrorException($e->getMessage(), $e->getCode(), \E_ERROR, $e->getFile(), $e->getLine()); + } finally { + ini_set('unserialize_callback_func', $unserializeCallbackHandler); + } + } + + protected function doHave(string $id): bool + { + return apcu_exists($id); + } + + protected function doClear(string $namespace): bool + { + return isset($namespace[0]) && class_exists(\APCUIterator::class, false) && ('cli' !== \PHP_SAPI || filter_var(\ini_get('apc.enable_cli'), \FILTER_VALIDATE_BOOL)) + ? apcu_delete(new \APCUIterator(\sprintf('/^%s/', preg_quote($namespace, '/')), \APC_ITER_KEY)) + : apcu_clear_cache(); + } + + protected function doDelete(array $ids): bool + { + foreach ($ids as $id) { + apcu_delete($id); + } + + return true; + } + + protected function doSave(array $values, int $lifetime): array|bool + { + if (null !== $this->marshaller && (!$values = $this->marshaller->marshall($values, $failed))) { + return $failed; + } + + try { + if (false === $failures = apcu_store($values, null, $lifetime)) { + $failures = $values; + } + + return array_keys($failures); + } catch (\Throwable $e) { + if (1 === \count($values)) { + // Workaround https://github.com/krakjoe/apcu/issues/170 + apcu_delete(array_key_first($values)); + } + + throw $e; + } + } +} diff --git a/vendor/symfony/cache/Adapter/ArrayAdapter.php b/vendor/symfony/cache/Adapter/ArrayAdapter.php new file mode 100644 index 0000000..7b92387 --- /dev/null +++ b/vendor/symfony/cache/Adapter/ArrayAdapter.php @@ -0,0 +1,366 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Adapter; + +use Psr\Cache\CacheItemInterface; +use Psr\Clock\ClockInterface; +use Psr\Log\LoggerAwareInterface; +use Psr\Log\LoggerAwareTrait; +use Symfony\Component\Cache\CacheItem; +use Symfony\Component\Cache\Exception\InvalidArgumentException; +use Symfony\Component\Cache\ResettableInterface; +use Symfony\Contracts\Cache\CacheInterface; + +/** + * An in-memory cache storage. + * + * Acts as a least-recently-used (LRU) storage when configured with a maximum number of items. + * + * @author Nicolas Grekas + */ +class ArrayAdapter implements AdapterInterface, CacheInterface, LoggerAwareInterface, ResettableInterface +{ + use LoggerAwareTrait; + + private array $values = []; + private array $tags = []; + private array $expiries = []; + + private static \Closure $createCacheItem; + + /** + * @param bool $storeSerialized Disabling serialization can lead to cache corruptions when storing mutable values but increases performance otherwise + */ + public function __construct( + private int $defaultLifetime = 0, + private bool $storeSerialized = true, + private float $maxLifetime = 0, + private int $maxItems = 0, + private ?ClockInterface $clock = null, + ) { + if (0 > $maxLifetime) { + throw new InvalidArgumentException(\sprintf('Argument $maxLifetime must be positive, %F passed.', $maxLifetime)); + } + + if (0 > $maxItems) { + throw new InvalidArgumentException(\sprintf('Argument $maxItems must be a positive integer, %d passed.', $maxItems)); + } + + self::$createCacheItem ??= \Closure::bind( + static function ($key, $value, $isHit, $tags) { + $item = new CacheItem(); + $item->key = $key; + $item->value = $value; + $item->isHit = $isHit; + if (null !== $tags) { + $item->metadata[CacheItem::METADATA_TAGS] = $tags; + } + + return $item; + }, + null, + CacheItem::class + ); + } + + public function get(string $key, callable $callback, ?float $beta = null, ?array &$metadata = null): mixed + { + $item = $this->getItem($key); + $metadata = $item->getMetadata(); + + // ArrayAdapter works in memory, we don't care about stampede protection + if (\INF === $beta || !$item->isHit()) { + $save = true; + $item->set($callback($item, $save)); + if ($save) { + $this->save($item); + } + } + + return $item->get(); + } + + public function delete(string $key): bool + { + return $this->deleteItem($key); + } + + public function hasItem(mixed $key): bool + { + if (\is_string($key) && isset($this->expiries[$key]) && $this->expiries[$key] > $this->getCurrentTime()) { + if ($this->maxItems) { + // Move the item last in the storage + $value = $this->values[$key]; + unset($this->values[$key]); + $this->values[$key] = $value; + } + + return true; + } + \assert('' !== CacheItem::validateKey($key)); + + return isset($this->expiries[$key]) && !$this->deleteItem($key); + } + + public function getItem(mixed $key): CacheItem + { + if (!$isHit = $this->hasItem($key)) { + $value = null; + + if (!$this->maxItems) { + // Track misses in non-LRU mode only + $this->values[$key] = null; + } + } else { + $value = $this->storeSerialized ? $this->unfreeze($key, $isHit) : $this->values[$key]; + } + + return (self::$createCacheItem)($key, $value, $isHit, $this->tags[$key] ?? null); + } + + public function getItems(array $keys = []): iterable + { + \assert(self::validateKeys($keys)); + + return $this->generateItems($keys, $this->getCurrentTime(), self::$createCacheItem); + } + + public function deleteItem(mixed $key): bool + { + \assert('' !== CacheItem::validateKey($key)); + unset($this->values[$key], $this->tags[$key], $this->expiries[$key]); + + return true; + } + + public function deleteItems(array $keys): bool + { + foreach ($keys as $key) { + $this->deleteItem($key); + } + + return true; + } + + public function save(CacheItemInterface $item): bool + { + if (!$item instanceof CacheItem) { + return false; + } + $item = (array) $item; + $key = $item["\0*\0key"]; + $value = $item["\0*\0value"]; + $expiry = $item["\0*\0expiry"]; + + $now = $this->getCurrentTime(); + + if (null !== $expiry) { + if (!$expiry) { + $expiry = \PHP_INT_MAX; + } elseif ($expiry <= $now) { + $this->deleteItem($key); + + return true; + } + } + if ($this->storeSerialized && null === $value = $this->freeze($value, $key)) { + return false; + } + if (null === $expiry && 0 < $this->defaultLifetime) { + $expiry = $this->defaultLifetime; + $expiry = $now + ($expiry > ($this->maxLifetime ?: $expiry) ? $this->maxLifetime : $expiry); + } elseif ($this->maxLifetime && (null === $expiry || $expiry > $now + $this->maxLifetime)) { + $expiry = $now + $this->maxLifetime; + } + + if ($this->maxItems) { + unset($this->values[$key], $this->tags[$key]); + + // Iterate items and vacuum expired ones while we are at it + foreach ($this->values as $k => $v) { + if ($this->expiries[$k] > $now && \count($this->values) < $this->maxItems) { + break; + } + + unset($this->values[$k], $this->tags[$k], $this->expiries[$k]); + } + } + + $this->values[$key] = $value; + $this->expiries[$key] = $expiry ?? \PHP_INT_MAX; + + if (null === $this->tags[$key] = $item["\0*\0newMetadata"][CacheItem::METADATA_TAGS] ?? null) { + unset($this->tags[$key]); + } + + return true; + } + + public function saveDeferred(CacheItemInterface $item): bool + { + return $this->save($item); + } + + public function commit(): bool + { + return true; + } + + public function clear(string $prefix = ''): bool + { + if ('' !== $prefix) { + $now = $this->getCurrentTime(); + + foreach ($this->values as $key => $value) { + if (!isset($this->expiries[$key]) || $this->expiries[$key] <= $now || str_starts_with($key, $prefix)) { + unset($this->values[$key], $this->tags[$key], $this->expiries[$key]); + } + } + + if ($this->values) { + return true; + } + } + + $this->values = $this->tags = $this->expiries = []; + + return true; + } + + /** + * Returns all cached values, with cache miss as null. + */ + public function getValues(): array + { + if (!$this->storeSerialized) { + return $this->values; + } + + $values = $this->values; + foreach ($values as $k => $v) { + if (null === $v || 'N;' === $v) { + continue; + } + if (!\is_string($v) || !isset($v[2]) || ':' !== $v[1]) { + $values[$k] = serialize($v); + } + } + + return $values; + } + + public function reset(): void + { + $this->clear(); + } + + private function generateItems(array $keys, float $now, \Closure $f): \Generator + { + foreach ($keys as $i => $key) { + if (!$isHit = isset($this->expiries[$key]) && ($this->expiries[$key] > $now || !$this->deleteItem($key))) { + $value = null; + + if (!$this->maxItems) { + // Track misses in non-LRU mode only + $this->values[$key] = null; + } + } else { + if ($this->maxItems) { + // Move the item last in the storage + $value = $this->values[$key]; + unset($this->values[$key]); + $this->values[$key] = $value; + } + + $value = $this->storeSerialized ? $this->unfreeze($key, $isHit) : $this->values[$key]; + } + unset($keys[$i]); + + yield $key => $f($key, $value, $isHit, $this->tags[$key] ?? null); + } + + foreach ($keys as $key) { + yield $key => $f($key, null, false); + } + } + + private function freeze($value, string $key): string|int|float|bool|array|\UnitEnum|null + { + if (null === $value) { + return 'N;'; + } + if (\is_string($value)) { + // Serialize strings if they could be confused with serialized objects or arrays + if ('N;' === $value || (isset($value[2]) && ':' === $value[1])) { + return serialize($value); + } + } elseif (!\is_scalar($value)) { + try { + $serialized = serialize($value); + } catch (\Exception $e) { + unset($this->values[$key], $this->tags[$key]); + $type = get_debug_type($value); + $message = \sprintf('Failed to save key "{key}" of type %s: %s', $type, $e->getMessage()); + CacheItem::log($this->logger, $message, ['key' => $key, 'exception' => $e, 'cache-adapter' => get_debug_type($this)]); + + return null; + } + // Keep value serialized if it contains any objects or any internal references + if ('C' === $serialized[0] || 'O' === $serialized[0] || preg_match('/;[OCRr]:[1-9]/', $serialized)) { + return $serialized; + } + } + + return $value; + } + + private function unfreeze(string $key, bool &$isHit): mixed + { + if ('N;' === $value = $this->values[$key]) { + return null; + } + if (\is_string($value) && isset($value[2]) && ':' === $value[1]) { + try { + $value = unserialize($value); + } catch (\Exception $e) { + CacheItem::log($this->logger, 'Failed to unserialize key "{key}": '.$e->getMessage(), ['key' => $key, 'exception' => $e, 'cache-adapter' => get_debug_type($this)]); + $value = false; + } + if (false === $value) { + $value = null; + $isHit = false; + + if (!$this->maxItems) { + $this->values[$key] = null; + } + } + } + + return $value; + } + + private function validateKeys(array $keys): bool + { + foreach ($keys as $key) { + if (!\is_string($key) || !isset($this->expiries[$key])) { + CacheItem::validateKey($key); + } + } + + return true; + } + + private function getCurrentTime(): float + { + return $this->clock?->now()->format('U.u') ?? microtime(true); + } +} diff --git a/vendor/symfony/cache/Adapter/ChainAdapter.php b/vendor/symfony/cache/Adapter/ChainAdapter.php new file mode 100644 index 0000000..09fcfdc --- /dev/null +++ b/vendor/symfony/cache/Adapter/ChainAdapter.php @@ -0,0 +1,291 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Adapter; + +use Psr\Cache\CacheItemInterface; +use Psr\Cache\CacheItemPoolInterface; +use Symfony\Component\Cache\CacheItem; +use Symfony\Component\Cache\Exception\InvalidArgumentException; +use Symfony\Component\Cache\PruneableInterface; +use Symfony\Component\Cache\ResettableInterface; +use Symfony\Component\Cache\Traits\ContractsTrait; +use Symfony\Contracts\Cache\CacheInterface; +use Symfony\Contracts\Service\ResetInterface; + +/** + * Chains several adapters together. + * + * Cached items are fetched from the first adapter having them in its data store. + * They are saved and deleted in all adapters at once. + * + * @author KĆ©vin Dunglas + */ +class ChainAdapter implements AdapterInterface, CacheInterface, PruneableInterface, ResettableInterface +{ + use ContractsTrait; + + private array $adapters = []; + private int $adapterCount; + + private static \Closure $syncItem; + + /** + * @param CacheItemPoolInterface[] $adapters The ordered list of adapters used to fetch cached items + * @param int $defaultLifetime The default lifetime of items propagated from lower adapters to upper ones + */ + public function __construct( + array $adapters, + private int $defaultLifetime = 0, + ) { + if (!$adapters) { + throw new InvalidArgumentException('At least one adapter must be specified.'); + } + + foreach ($adapters as $adapter) { + if (!$adapter instanceof CacheItemPoolInterface) { + throw new InvalidArgumentException(\sprintf('The class "%s" does not implement the "%s" interface.', get_debug_type($adapter), CacheItemPoolInterface::class)); + } + if ('cli' === \PHP_SAPI && $adapter instanceof ApcuAdapter && !filter_var(\ini_get('apc.enable_cli'), \FILTER_VALIDATE_BOOL)) { + continue; // skip putting APCu in the chain when the backend is disabled + } + + if ($adapter instanceof AdapterInterface) { + $this->adapters[] = $adapter; + } else { + $this->adapters[] = new ProxyAdapter($adapter); + } + } + $this->adapterCount = \count($this->adapters); + + self::$syncItem ??= \Closure::bind( + static function ($sourceItem, $item, $defaultLifetime, $sourceMetadata = null) { + $sourceItem->isTaggable = false; + $sourceMetadata ??= $sourceItem->metadata; + + $item->value = $sourceItem->value; + $item->isHit = $sourceItem->isHit; + $item->metadata = $item->newMetadata = $sourceItem->metadata = $sourceMetadata; + + if (isset($item->metadata[CacheItem::METADATA_EXPIRY])) { + $item->expiresAt(\DateTimeImmutable::createFromFormat('U.u', \sprintf('%.6F', $item->metadata[CacheItem::METADATA_EXPIRY]))); + } elseif (0 < $defaultLifetime) { + $item->expiresAfter($defaultLifetime); + } + + return $item; + }, + null, + CacheItem::class + ); + } + + public function get(string $key, callable $callback, ?float $beta = null, ?array &$metadata = null): mixed + { + $doSave = true; + $callback = static function (CacheItem $item, bool &$save) use ($callback, &$doSave) { + $value = $callback($item, $save); + $doSave = $save; + + return $value; + }; + + $wrap = function (?CacheItem $item = null, bool &$save = true) use ($key, $callback, $beta, &$wrap, &$doSave, &$metadata) { + static $lastItem; + static $i = 0; + $adapter = $this->adapters[$i]; + if (isset($this->adapters[++$i])) { + $callback = $wrap; + $beta = \INF === $beta ? \INF : 0; + } + if ($adapter instanceof CacheInterface) { + $value = $adapter->get($key, $callback, $beta, $metadata); + } else { + $value = $this->doGet($adapter, $key, $callback, $beta, $metadata); + } + if (null !== $item) { + (self::$syncItem)($lastItem ??= $item, $item, $this->defaultLifetime, $metadata); + } + $save = $doSave; + + return $value; + }; + + return $wrap(); + } + + public function getItem(mixed $key): CacheItem + { + $syncItem = self::$syncItem; + $misses = []; + + foreach ($this->adapters as $i => $adapter) { + $item = $adapter->getItem($key); + + if ($item->isHit()) { + while (0 <= --$i) { + $this->adapters[$i]->save($syncItem($item, $misses[$i], $this->defaultLifetime)); + } + + return $item; + } + + $misses[$i] = $item; + } + + return $item; + } + + public function getItems(array $keys = []): iterable + { + return $this->generateItems($this->adapters[0]->getItems($keys), 0); + } + + private function generateItems(iterable $items, int $adapterIndex): \Generator + { + $missing = []; + $misses = []; + $nextAdapterIndex = $adapterIndex + 1; + $nextAdapter = $this->adapters[$nextAdapterIndex] ?? null; + + foreach ($items as $k => $item) { + if (!$nextAdapter || $item->isHit()) { + yield $k => $item; + } else { + $missing[] = $k; + $misses[$k] = $item; + } + } + + if ($missing) { + $syncItem = self::$syncItem; + $adapter = $this->adapters[$adapterIndex]; + $items = $this->generateItems($nextAdapter->getItems($missing), $nextAdapterIndex); + + foreach ($items as $k => $item) { + if ($item->isHit()) { + $adapter->save($syncItem($item, $misses[$k], $this->defaultLifetime)); + } + + yield $k => $item; + } + } + } + + public function hasItem(mixed $key): bool + { + foreach ($this->adapters as $adapter) { + if ($adapter->hasItem($key)) { + return true; + } + } + + return false; + } + + public function clear(string $prefix = ''): bool + { + $cleared = true; + $i = $this->adapterCount; + + while ($i--) { + if ($this->adapters[$i] instanceof AdapterInterface) { + $cleared = $this->adapters[$i]->clear($prefix) && $cleared; + } else { + $cleared = $this->adapters[$i]->clear() && $cleared; + } + } + + return $cleared; + } + + public function deleteItem(mixed $key): bool + { + $deleted = true; + $i = $this->adapterCount; + + while ($i--) { + $deleted = $this->adapters[$i]->deleteItem($key) && $deleted; + } + + return $deleted; + } + + public function deleteItems(array $keys): bool + { + $deleted = true; + $i = $this->adapterCount; + + while ($i--) { + $deleted = $this->adapters[$i]->deleteItems($keys) && $deleted; + } + + return $deleted; + } + + public function save(CacheItemInterface $item): bool + { + $saved = true; + $i = $this->adapterCount; + + while ($i--) { + $saved = $this->adapters[$i]->save($item) && $saved; + } + + return $saved; + } + + public function saveDeferred(CacheItemInterface $item): bool + { + $saved = true; + $i = $this->adapterCount; + + while ($i--) { + $saved = $this->adapters[$i]->saveDeferred($item) && $saved; + } + + return $saved; + } + + public function commit(): bool + { + $committed = true; + $i = $this->adapterCount; + + while ($i--) { + $committed = $this->adapters[$i]->commit() && $committed; + } + + return $committed; + } + + public function prune(): bool + { + $pruned = true; + + foreach ($this->adapters as $adapter) { + if ($adapter instanceof PruneableInterface) { + $pruned = $adapter->prune() && $pruned; + } + } + + return $pruned; + } + + public function reset(): void + { + foreach ($this->adapters as $adapter) { + if ($adapter instanceof ResetInterface) { + $adapter->reset(); + } + } + } +} diff --git a/vendor/symfony/cache/Adapter/CouchbaseBucketAdapter.php b/vendor/symfony/cache/Adapter/CouchbaseBucketAdapter.php new file mode 100644 index 0000000..106d7fd --- /dev/null +++ b/vendor/symfony/cache/Adapter/CouchbaseBucketAdapter.php @@ -0,0 +1,237 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Adapter; + +use Symfony\Component\Cache\Exception\CacheException; +use Symfony\Component\Cache\Exception\InvalidArgumentException; +use Symfony\Component\Cache\Marshaller\DefaultMarshaller; +use Symfony\Component\Cache\Marshaller\MarshallerInterface; + +trigger_deprecation('symfony/cache', '7.1', 'The "%s" class is deprecated, use "%s" instead.', CouchbaseBucketAdapter::class, CouchbaseCollectionAdapter::class); + +/** + * @author Antonio Jose Cerezo Aranda + * + * @deprecated since Symfony 7.1, use {@see CouchbaseCollectionAdapter} instead + */ +class CouchbaseBucketAdapter extends AbstractAdapter +{ + private const THIRTY_DAYS_IN_SECONDS = 2592000; + private const MAX_KEY_LENGTH = 250; + private const KEY_NOT_FOUND = 13; + private const VALID_DSN_OPTIONS = [ + 'operationTimeout', + 'configTimeout', + 'configNodeTimeout', + 'n1qlTimeout', + 'httpTimeout', + 'configDelay', + 'htconfigIdleTimeout', + 'durabilityInterval', + 'durabilityTimeout', + ]; + + private MarshallerInterface $marshaller; + + public function __construct( + private \CouchbaseBucket $bucket, + string $namespace = '', + int $defaultLifetime = 0, + ?MarshallerInterface $marshaller = null, + ) { + if (!static::isSupported()) { + throw new CacheException('Couchbase >= 2.6.0 < 3.0.0 is required.'); + } + + $this->maxIdLength = static::MAX_KEY_LENGTH; + + parent::__construct($namespace, $defaultLifetime); + $this->enableVersioning(); + $this->marshaller = $marshaller ?? new DefaultMarshaller(); + } + + public static function createConnection(#[\SensitiveParameter] array|string $servers, array $options = []): \CouchbaseBucket + { + if (\is_string($servers)) { + $servers = [$servers]; + } + + if (!static::isSupported()) { + throw new CacheException('Couchbase >= 2.6.0 < 3.0.0 is required.'); + } + + set_error_handler(static fn ($type, $msg, $file, $line) => throw new \ErrorException($msg, 0, $type, $file, $line)); + + $dsnPattern = '/^(?couchbase(?:s)?)\:\/\/(?:(?[^\:]+)\:(?[^\@]{6,})@)?' + .'(?[^\:]+(?:\:\d+)?)(?:\/(?[^\?]+))(?:\?(?.*))?$/i'; + + $newServers = []; + $protocol = 'couchbase'; + try { + $options = self::initOptions($options); + $username = $options['username']; + $password = $options['password']; + + foreach ($servers as $dsn) { + if (!str_starts_with($dsn, 'couchbase:')) { + throw new InvalidArgumentException('Invalid Couchbase DSN: it does not start with "couchbase:".'); + } + + preg_match($dsnPattern, $dsn, $matches); + + $username = $matches['username'] ?: $username; + $password = $matches['password'] ?: $password; + $protocol = $matches['protocol'] ?: $protocol; + + if (isset($matches['options'])) { + $optionsInDsn = self::getOptions($matches['options']); + + foreach ($optionsInDsn as $parameter => $value) { + $options[$parameter] = $value; + } + } + + $newServers[] = $matches['host']; + } + + $connectionString = $protocol.'://'.implode(',', $newServers); + + $client = new \CouchbaseCluster($connectionString); + $client->authenticateAs($username, $password); + + $bucket = $client->openBucket($matches['bucketName']); + + unset($options['username'], $options['password']); + foreach ($options as $option => $value) { + if ($value) { + $bucket->$option = $value; + } + } + + return $bucket; + } finally { + restore_error_handler(); + } + } + + public static function isSupported(): bool + { + return \extension_loaded('couchbase') && version_compare(phpversion('couchbase'), '2.6.0', '>=') && version_compare(phpversion('couchbase'), '3.0', '<'); + } + + private static function getOptions(string $options): array + { + $results = []; + $optionsInArray = explode('&', $options); + + foreach ($optionsInArray as $option) { + [$key, $value] = explode('=', $option); + + if (\in_array($key, static::VALID_DSN_OPTIONS, true)) { + $results[$key] = $value; + } + } + + return $results; + } + + private static function initOptions(array $options): array + { + $options['username'] ??= ''; + $options['password'] ??= ''; + $options['operationTimeout'] ??= 0; + $options['configTimeout'] ??= 0; + $options['configNodeTimeout'] ??= 0; + $options['n1qlTimeout'] ??= 0; + $options['httpTimeout'] ??= 0; + $options['configDelay'] ??= 0; + $options['htconfigIdleTimeout'] ??= 0; + $options['durabilityInterval'] ??= 0; + $options['durabilityTimeout'] ??= 0; + + return $options; + } + + protected function doFetch(array $ids): iterable + { + $resultsCouchbase = $this->bucket->get($ids); + + $results = []; + foreach ($resultsCouchbase as $key => $value) { + if (null !== $value->error) { + continue; + } + $results[$key] = $this->marshaller->unmarshall($value->value); + } + + return $results; + } + + protected function doHave(string $id): bool + { + return false !== $this->bucket->get($id); + } + + protected function doClear(string $namespace): bool + { + if ('' === $namespace) { + $this->bucket->manager()->flush(); + + return true; + } + + return false; + } + + protected function doDelete(array $ids): bool + { + $results = $this->bucket->remove(array_values($ids)); + + foreach ($results as $key => $result) { + if (null !== $result->error && static::KEY_NOT_FOUND !== $result->error->getCode()) { + continue; + } + unset($results[$key]); + } + + return 0 === \count($results); + } + + protected function doSave(array $values, int $lifetime): array|bool + { + if (!$values = $this->marshaller->marshall($values, $failed)) { + return $failed; + } + + $lifetime = $this->normalizeExpiry($lifetime); + + $ko = []; + foreach ($values as $key => $value) { + $result = $this->bucket->upsert($key, $value, ['expiry' => $lifetime]); + + if (null !== $result->error) { + $ko[$key] = $result; + } + } + + return [] === $ko ? true : $ko; + } + + private function normalizeExpiry(int $expiry): int + { + if ($expiry && $expiry > static::THIRTY_DAYS_IN_SECONDS) { + $expiry += time(); + } + + return $expiry; + } +} diff --git a/vendor/symfony/cache/Adapter/CouchbaseCollectionAdapter.php b/vendor/symfony/cache/Adapter/CouchbaseCollectionAdapter.php new file mode 100644 index 0000000..9646bc3 --- /dev/null +++ b/vendor/symfony/cache/Adapter/CouchbaseCollectionAdapter.php @@ -0,0 +1,198 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Adapter; + +use Couchbase\Bucket; +use Couchbase\Cluster; +use Couchbase\ClusterOptions; +use Couchbase\Collection; +use Couchbase\DocumentNotFoundException; +use Couchbase\UpsertOptions; +use Symfony\Component\Cache\Exception\CacheException; +use Symfony\Component\Cache\Exception\InvalidArgumentException; +use Symfony\Component\Cache\Marshaller\DefaultMarshaller; +use Symfony\Component\Cache\Marshaller\MarshallerInterface; + +/** + * @author Antonio Jose Cerezo Aranda + */ +class CouchbaseCollectionAdapter extends AbstractAdapter +{ + private const MAX_KEY_LENGTH = 250; + + private MarshallerInterface $marshaller; + + public function __construct( + private Collection $connection, + string $namespace = '', + int $defaultLifetime = 0, + ?MarshallerInterface $marshaller = null, + ) { + if (!static::isSupported()) { + throw new CacheException('Couchbase >= 3.0.5 < 4.0.0 is required.'); + } + + $this->maxIdLength = static::MAX_KEY_LENGTH; + + parent::__construct($namespace, $defaultLifetime); + $this->enableVersioning(); + $this->marshaller = $marshaller ?? new DefaultMarshaller(); + } + + public static function createConnection(#[\SensitiveParameter] array|string $dsn, array $options = []): Bucket|Collection + { + if (\is_string($dsn)) { + $dsn = [$dsn]; + } + + if (!static::isSupported()) { + throw new CacheException('Couchbase >= 3.0.5 < 4.0.0 is required.'); + } + + set_error_handler(static fn ($type, $msg, $file, $line) => throw new \ErrorException($msg, 0, $type, $file, $line)); + + $pathPattern = '/^(?:\/(?[^\/\?]+))(?:(?:\/(?[^\/]+))(?:\/(?[^\/\?]+)))?(?:\/)?$/'; + $newServers = []; + $protocol = 'couchbase'; + try { + $username = $options['username'] ?? ''; + $password = $options['password'] ?? ''; + + foreach ($dsn as $server) { + if (!str_starts_with($server, 'couchbase:')) { + throw new InvalidArgumentException('Invalid Couchbase DSN: it does not start with "couchbase:".'); + } + + $params = parse_url($server); + + $username = isset($params['user']) ? rawurldecode($params['user']) : $username; + $password = isset($params['pass']) ? rawurldecode($params['pass']) : $password; + $protocol = $params['scheme'] ?? $protocol; + + if (isset($params['query'])) { + $optionsInDsn = self::getOptions($params['query']); + + foreach ($optionsInDsn as $parameter => $value) { + $options[$parameter] = $value; + } + } + + $newServers[] = $params['host']; + } + + $option = isset($params['query']) ? '?'.$params['query'] : ''; + $connectionString = $protocol.'://'.implode(',', $newServers).$option; + + $clusterOptions = new ClusterOptions(); + $clusterOptions->credentials($username, $password); + + $client = new Cluster($connectionString, $clusterOptions); + + preg_match($pathPattern, $params['path'] ?? '', $matches); + $bucket = $client->bucket($matches['bucketName']); + $collection = $bucket->defaultCollection(); + if (!empty($matches['scopeName'])) { + $scope = $bucket->scope($matches['scopeName']); + $collection = $scope->collection($matches['collectionName']); + } + + return $collection; + } finally { + restore_error_handler(); + } + } + + public static function isSupported(): bool + { + return \extension_loaded('couchbase') && version_compare(phpversion('couchbase'), '3.0.5', '>=') && version_compare(phpversion('couchbase'), '4.0', '<'); + } + + private static function getOptions(string $options): array + { + $results = []; + $optionsInArray = explode('&', $options); + + foreach ($optionsInArray as $option) { + [$key, $value] = explode('=', $option); + + $results[$key] = $value; + } + + return $results; + } + + protected function doFetch(array $ids): array + { + $results = []; + foreach ($ids as $id) { + try { + $resultCouchbase = $this->connection->get($id); + } catch (DocumentNotFoundException) { + continue; + } + + $content = $resultCouchbase->value ?? $resultCouchbase->content(); + + $results[$id] = $this->marshaller->unmarshall($content); + } + + return $results; + } + + protected function doHave($id): bool + { + return $this->connection->exists($id)->exists(); + } + + protected function doClear($namespace): bool + { + return false; + } + + protected function doDelete(array $ids): bool + { + $idsErrors = []; + foreach ($ids as $id) { + try { + $result = $this->connection->remove($id); + + if (null === $result->mutationToken()) { + $idsErrors[] = $id; + } + } catch (DocumentNotFoundException) { + } + } + + return 0 === \count($idsErrors); + } + + protected function doSave(array $values, $lifetime): array|bool + { + if (!$values = $this->marshaller->marshall($values, $failed)) { + return $failed; + } + + $upsertOptions = new UpsertOptions(); + $upsertOptions->expiry($lifetime); + + $ko = []; + foreach ($values as $key => $value) { + try { + $this->connection->upsert($key, $value, $upsertOptions); + } catch (\Exception) { + $ko[$key] = ''; + } + } + + return [] === $ko ? true : $ko; + } +} diff --git a/vendor/symfony/cache/Adapter/DoctrineDbalAdapter.php b/vendor/symfony/cache/Adapter/DoctrineDbalAdapter.php new file mode 100644 index 0000000..c69c777 --- /dev/null +++ b/vendor/symfony/cache/Adapter/DoctrineDbalAdapter.php @@ -0,0 +1,383 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Adapter; + +use Doctrine\DBAL\ArrayParameterType; +use Doctrine\DBAL\Configuration; +use Doctrine\DBAL\Connection; +use Doctrine\DBAL\DriverManager; +use Doctrine\DBAL\Exception as DBALException; +use Doctrine\DBAL\Exception\TableNotFoundException; +use Doctrine\DBAL\ParameterType; +use Doctrine\DBAL\Schema\DefaultSchemaManagerFactory; +use Doctrine\DBAL\Schema\Schema; +use Doctrine\DBAL\Tools\DsnParser; +use Symfony\Component\Cache\Exception\InvalidArgumentException; +use Symfony\Component\Cache\Marshaller\DefaultMarshaller; +use Symfony\Component\Cache\Marshaller\MarshallerInterface; +use Symfony\Component\Cache\PruneableInterface; + +class DoctrineDbalAdapter extends AbstractAdapter implements PruneableInterface +{ + private const MAX_KEY_LENGTH = 255; + + private MarshallerInterface $marshaller; + private Connection $conn; + private string $platformName; + private string $table = 'cache_items'; + private string $idCol = 'item_id'; + private string $dataCol = 'item_data'; + private string $lifetimeCol = 'item_lifetime'; + private string $timeCol = 'item_time'; + + /** + * You can either pass an existing database Doctrine DBAL Connection or + * a DSN string that will be used to connect to the database. + * + * The cache table is created automatically when possible. + * Otherwise, use the createTable() method. + * + * List of available options: + * * db_table: The name of the table [default: cache_items] + * * db_id_col: The column where to store the cache id [default: item_id] + * * db_data_col: The column where to store the cache data [default: item_data] + * * db_lifetime_col: The column where to store the lifetime [default: item_lifetime] + * * db_time_col: The column where to store the timestamp [default: item_time] + * + * @throws InvalidArgumentException When namespace contains invalid characters + */ + public function __construct( + Connection|string $connOrDsn, + private string $namespace = '', + int $defaultLifetime = 0, + array $options = [], + ?MarshallerInterface $marshaller = null, + ) { + if (isset($namespace[0]) && preg_match('#[^-+.A-Za-z0-9]#', $namespace, $match)) { + throw new InvalidArgumentException(\sprintf('Namespace contains "%s" but only characters in [-+.A-Za-z0-9] are allowed.', $match[0])); + } + + if ($connOrDsn instanceof Connection) { + $this->conn = $connOrDsn; + } else { + if (!class_exists(DriverManager::class)) { + throw new InvalidArgumentException('Failed to parse DSN. Try running "composer require doctrine/dbal".'); + } + $params = (new DsnParser([ + 'db2' => 'ibm_db2', + 'mssql' => 'pdo_sqlsrv', + 'mysql' => 'pdo_mysql', + 'mysql2' => 'pdo_mysql', + 'postgres' => 'pdo_pgsql', + 'postgresql' => 'pdo_pgsql', + 'pgsql' => 'pdo_pgsql', + 'sqlite' => 'pdo_sqlite', + 'sqlite3' => 'pdo_sqlite', + ]))->parse($connOrDsn); + + $config = new Configuration(); + $config->setSchemaManagerFactory(new DefaultSchemaManagerFactory()); + + $this->conn = DriverManager::getConnection($params, $config); + } + + $this->maxIdLength = self::MAX_KEY_LENGTH; + $this->table = $options['db_table'] ?? $this->table; + $this->idCol = $options['db_id_col'] ?? $this->idCol; + $this->dataCol = $options['db_data_col'] ?? $this->dataCol; + $this->lifetimeCol = $options['db_lifetime_col'] ?? $this->lifetimeCol; + $this->timeCol = $options['db_time_col'] ?? $this->timeCol; + $this->marshaller = $marshaller ?? new DefaultMarshaller(); + + parent::__construct($namespace, $defaultLifetime); + } + + /** + * Creates the table to store cache items which can be called once for setup. + * + * Cache ID are saved in a column of maximum length 255. Cache data is + * saved in a BLOB. + * + * @throws DBALException When the table already exists + */ + public function createTable(): void + { + $schema = new Schema(); + $this->addTableToSchema($schema); + + foreach ($schema->toSql($this->conn->getDatabasePlatform()) as $sql) { + $this->conn->executeStatement($sql); + } + } + + public function configureSchema(Schema $schema, Connection $forConnection, \Closure $isSameDatabase): void + { + if ($schema->hasTable($this->table)) { + return; + } + + if ($forConnection !== $this->conn && !$isSameDatabase($this->conn->executeStatement(...))) { + return; + } + + $this->addTableToSchema($schema); + } + + public function prune(): bool + { + $deleteSql = "DELETE FROM $this->table WHERE $this->lifetimeCol + $this->timeCol <= ?"; + $params = [time()]; + $paramTypes = [ParameterType::INTEGER]; + + if ('' !== $this->namespace) { + $deleteSql .= " AND $this->idCol LIKE ?"; + $params[] = \sprintf('%s%%', $this->namespace); + $paramTypes[] = ParameterType::STRING; + } + + try { + $this->conn->executeStatement($deleteSql, $params, $paramTypes); + } catch (TableNotFoundException) { + } + + return true; + } + + protected function doFetch(array $ids): iterable + { + $now = time(); + $expired = []; + + $sql = "SELECT $this->idCol, CASE WHEN $this->lifetimeCol IS NULL OR $this->lifetimeCol + $this->timeCol > ? THEN $this->dataCol ELSE NULL END FROM $this->table WHERE $this->idCol IN (?)"; + $result = $this->conn->executeQuery($sql, [ + $now, + $ids, + ], [ + ParameterType::INTEGER, + ArrayParameterType::STRING, + ])->iterateNumeric(); + + foreach ($result as $row) { + if (null === $row[1]) { + $expired[] = $row[0]; + } else { + yield $row[0] => $this->marshaller->unmarshall(\is_resource($row[1]) ? stream_get_contents($row[1]) : $row[1]); + } + } + + if ($expired) { + $sql = "DELETE FROM $this->table WHERE $this->lifetimeCol + $this->timeCol <= ? AND $this->idCol IN (?)"; + $this->conn->executeStatement($sql, [ + $now, + $expired, + ], [ + ParameterType::INTEGER, + ArrayParameterType::STRING, + ]); + } + } + + protected function doHave(string $id): bool + { + $sql = "SELECT 1 FROM $this->table WHERE $this->idCol = ? AND ($this->lifetimeCol IS NULL OR $this->lifetimeCol + $this->timeCol > ?)"; + $result = $this->conn->executeQuery($sql, [ + $id, + time(), + ], [ + ParameterType::STRING, + ParameterType::INTEGER, + ]); + + return (bool) $result->fetchOne(); + } + + protected function doClear(string $namespace): bool + { + if ('' === $namespace) { + $sql = $this->conn->getDatabasePlatform()->getTruncateTableSQL($this->table); + } else { + $sql = "DELETE FROM $this->table WHERE $this->idCol LIKE '$namespace%'"; + } + + try { + $this->conn->executeStatement($sql); + } catch (TableNotFoundException) { + } + + return true; + } + + protected function doDelete(array $ids): bool + { + $sql = "DELETE FROM $this->table WHERE $this->idCol IN (?)"; + try { + $this->conn->executeStatement($sql, [array_values($ids)], [ArrayParameterType::STRING]); + } catch (TableNotFoundException) { + } + + return true; + } + + protected function doSave(array $values, int $lifetime): array|bool + { + if (!$values = $this->marshaller->marshall($values, $failed)) { + return $failed; + } + + $platformName = $this->getPlatformName(); + $insertSql = "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (?, ?, ?, ?)"; + + switch ($platformName) { + case 'mysql': + $sql = $insertSql." ON DUPLICATE KEY UPDATE $this->dataCol = VALUES($this->dataCol), $this->lifetimeCol = VALUES($this->lifetimeCol), $this->timeCol = VALUES($this->timeCol)"; + break; + case 'oci': + // DUAL is Oracle specific dummy table + $sql = "MERGE INTO $this->table USING DUAL ON ($this->idCol = ?) ". + "WHEN NOT MATCHED THEN INSERT ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (?, ?, ?, ?) ". + "WHEN MATCHED THEN UPDATE SET $this->dataCol = ?, $this->lifetimeCol = ?, $this->timeCol = ?"; + break; + case 'sqlsrv': + // MERGE is only available since SQL Server 2008 and must be terminated by semicolon + // It also requires HOLDLOCK according to http://weblogs.sqlteam.com/dang/archive/2009/01/31/UPSERT-Race-Condition-With-MERGE.aspx + $sql = "MERGE INTO $this->table WITH (HOLDLOCK) USING (SELECT 1 AS dummy) AS src ON ($this->idCol = ?) ". + "WHEN NOT MATCHED THEN INSERT ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (?, ?, ?, ?) ". + "WHEN MATCHED THEN UPDATE SET $this->dataCol = ?, $this->lifetimeCol = ?, $this->timeCol = ?;"; + break; + case 'sqlite': + $sql = 'INSERT OR REPLACE'.substr($insertSql, 6); + break; + case 'pgsql': + $sql = $insertSql." ON CONFLICT ($this->idCol) DO UPDATE SET ($this->dataCol, $this->lifetimeCol, $this->timeCol) = (EXCLUDED.$this->dataCol, EXCLUDED.$this->lifetimeCol, EXCLUDED.$this->timeCol)"; + break; + default: + $platformName = null; + $sql = "UPDATE $this->table SET $this->dataCol = ?, $this->lifetimeCol = ?, $this->timeCol = ? WHERE $this->idCol = ?"; + break; + } + + $now = time(); + $lifetime = $lifetime ?: null; + try { + $stmt = $this->conn->prepare($sql); + } catch (TableNotFoundException) { + if (!$this->conn->isTransactionActive() || \in_array($platformName, ['pgsql', 'sqlite', 'sqlsrv'], true)) { + $this->createTable(); + } + $stmt = $this->conn->prepare($sql); + } + + if ('sqlsrv' === $platformName || 'oci' === $platformName) { + $bind = static function ($id, $data) use ($stmt) { + $stmt->bindValue(1, $id); + $stmt->bindValue(2, $id); + $stmt->bindValue(3, $data, ParameterType::LARGE_OBJECT); + $stmt->bindValue(6, $data, ParameterType::LARGE_OBJECT); + }; + $stmt->bindValue(4, $lifetime, ParameterType::INTEGER); + $stmt->bindValue(5, $now, ParameterType::INTEGER); + $stmt->bindValue(7, $lifetime, ParameterType::INTEGER); + $stmt->bindValue(8, $now, ParameterType::INTEGER); + } elseif (null !== $platformName) { + $bind = static function ($id, $data) use ($stmt) { + $stmt->bindValue(1, $id); + $stmt->bindValue(2, $data, ParameterType::LARGE_OBJECT); + }; + $stmt->bindValue(3, $lifetime, ParameterType::INTEGER); + $stmt->bindValue(4, $now, ParameterType::INTEGER); + } else { + $stmt->bindValue(2, $lifetime, ParameterType::INTEGER); + $stmt->bindValue(3, $now, ParameterType::INTEGER); + + $insertStmt = $this->conn->prepare($insertSql); + $insertStmt->bindValue(3, $lifetime, ParameterType::INTEGER); + $insertStmt->bindValue(4, $now, ParameterType::INTEGER); + + $bind = static function ($id, $data) use ($stmt, $insertStmt) { + $stmt->bindValue(1, $data, ParameterType::LARGE_OBJECT); + $stmt->bindValue(4, $id); + $insertStmt->bindValue(1, $id); + $insertStmt->bindValue(2, $data, ParameterType::LARGE_OBJECT); + }; + } + + foreach ($values as $id => $data) { + $bind($id, $data); + try { + $rowCount = $stmt->executeStatement(); + } catch (TableNotFoundException) { + if (!$this->conn->isTransactionActive() || \in_array($platformName, ['pgsql', 'sqlite', 'sqlsrv'], true)) { + $this->createTable(); + } + $rowCount = $stmt->executeStatement(); + } + if (null === $platformName && 0 === $rowCount) { + try { + $insertStmt->executeStatement(); + } catch (DBALException) { + // A concurrent write won, let it be + } + } + } + + return $failed; + } + + /** + * @internal + */ + protected function getId(mixed $key): string + { + if ('pgsql' !== $this->platformName ??= $this->getPlatformName()) { + return parent::getId($key); + } + + if (str_contains($key, "\0") || str_contains($key, '%') || !preg_match('//u', $key)) { + $key = rawurlencode($key); + } + + return parent::getId($key); + } + + private function getPlatformName(): string + { + if (isset($this->platformName)) { + return $this->platformName; + } + + $platform = $this->conn->getDatabasePlatform(); + + return $this->platformName = match (true) { + $platform instanceof \Doctrine\DBAL\Platforms\AbstractMySQLPlatform => 'mysql', + $platform instanceof \Doctrine\DBAL\Platforms\SqlitePlatform => 'sqlite', + $platform instanceof \Doctrine\DBAL\Platforms\PostgreSQLPlatform => 'pgsql', + $platform instanceof \Doctrine\DBAL\Platforms\OraclePlatform => 'oci', + $platform instanceof \Doctrine\DBAL\Platforms\SQLServerPlatform => 'sqlsrv', + default => $platform::class, + }; + } + + private function addTableToSchema(Schema $schema): void + { + $types = [ + 'mysql' => 'binary', + 'sqlite' => 'text', + ]; + + $table = $schema->createTable($this->table); + $table->addColumn($this->idCol, $types[$this->getPlatformName()] ?? 'string', ['length' => 255]); + $table->addColumn($this->dataCol, 'blob', ['length' => 16777215]); + $table->addColumn($this->lifetimeCol, 'integer', ['unsigned' => true, 'notnull' => false]); + $table->addColumn($this->timeCol, 'integer', ['unsigned' => true]); + $table->setPrimaryKey([$this->idCol]); + } +} diff --git a/vendor/symfony/cache/Adapter/FilesystemAdapter.php b/vendor/symfony/cache/Adapter/FilesystemAdapter.php new file mode 100644 index 0000000..13daa56 --- /dev/null +++ b/vendor/symfony/cache/Adapter/FilesystemAdapter.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Adapter; + +use Symfony\Component\Cache\Marshaller\DefaultMarshaller; +use Symfony\Component\Cache\Marshaller\MarshallerInterface; +use Symfony\Component\Cache\PruneableInterface; +use Symfony\Component\Cache\Traits\FilesystemTrait; + +class FilesystemAdapter extends AbstractAdapter implements PruneableInterface +{ + use FilesystemTrait; + + public function __construct(string $namespace = '', int $defaultLifetime = 0, ?string $directory = null, ?MarshallerInterface $marshaller = null) + { + $this->marshaller = $marshaller ?? new DefaultMarshaller(); + parent::__construct('', $defaultLifetime); + $this->init($namespace, $directory); + } +} diff --git a/vendor/symfony/cache/Adapter/FilesystemTagAwareAdapter.php b/vendor/symfony/cache/Adapter/FilesystemTagAwareAdapter.php new file mode 100644 index 0000000..80edee4 --- /dev/null +++ b/vendor/symfony/cache/Adapter/FilesystemTagAwareAdapter.php @@ -0,0 +1,267 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Adapter; + +use Symfony\Component\Cache\Marshaller\MarshallerInterface; +use Symfony\Component\Cache\Marshaller\TagAwareMarshaller; +use Symfony\Component\Cache\PruneableInterface; +use Symfony\Component\Cache\Traits\FilesystemTrait; + +/** + * Stores tag id <> cache id relationship as a symlink, and lookup on invalidation calls. + * + * @author Nicolas Grekas + * @author AndrĆ© RĆømcke + */ +class FilesystemTagAwareAdapter extends AbstractTagAwareAdapter implements PruneableInterface +{ + use FilesystemTrait { + prune as private doPrune; + doClear as private doClearCache; + doSave as private doSaveCache; + } + + /** + * Folder used for tag symlinks. + */ + private const TAG_FOLDER = 'tags'; + + public function __construct(string $namespace = '', int $defaultLifetime = 0, ?string $directory = null, ?MarshallerInterface $marshaller = null) + { + $this->marshaller = new TagAwareMarshaller($marshaller); + parent::__construct('', $defaultLifetime); + $this->init($namespace, $directory); + } + + public function prune(): bool + { + $ok = $this->doPrune(); + + set_error_handler(static function () {}); + $chars = '+-ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; + + try { + foreach ($this->scanHashDir($this->directory.self::TAG_FOLDER.\DIRECTORY_SEPARATOR) as $dir) { + $dir .= \DIRECTORY_SEPARATOR; + $keepDir = false; + for ($i = 0; $i < 38; ++$i) { + if (!is_dir($dir.$chars[$i])) { + continue; + } + for ($j = 0; $j < 38; ++$j) { + if (!is_dir($d = $dir.$chars[$i].\DIRECTORY_SEPARATOR.$chars[$j])) { + continue; + } + foreach (scandir($d, \SCANDIR_SORT_NONE) ?: [] as $link) { + if ('.' === $link || '..' === $link) { + continue; + } + if ('_' !== $dir[-2] && realpath($d.\DIRECTORY_SEPARATOR.$link)) { + $keepDir = true; + } else { + unlink($d.\DIRECTORY_SEPARATOR.$link); + } + } + $keepDir ?: rmdir($d); + } + $keepDir ?: rmdir($dir.$chars[$i]); + } + $keepDir ?: rmdir($dir); + } + } finally { + restore_error_handler(); + } + + return $ok; + } + + protected function doClear(string $namespace): bool + { + $ok = $this->doClearCache($namespace); + + if ('' !== $namespace) { + return $ok; + } + + set_error_handler(static function () {}); + $chars = '+-ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; + + $this->tmpSuffix ??= str_replace('/', '-', base64_encode(random_bytes(6))); + + try { + foreach ($this->scanHashDir($this->directory.self::TAG_FOLDER.\DIRECTORY_SEPARATOR) as $dir) { + if (rename($dir, $renamed = substr_replace($dir, $this->tmpSuffix.'_', -9))) { + $dir = $renamed.\DIRECTORY_SEPARATOR; + } else { + $dir .= \DIRECTORY_SEPARATOR; + $renamed = null; + } + + for ($i = 0; $i < 38; ++$i) { + if (!is_dir($dir.$chars[$i])) { + continue; + } + for ($j = 0; $j < 38; ++$j) { + if (!is_dir($d = $dir.$chars[$i].\DIRECTORY_SEPARATOR.$chars[$j])) { + continue; + } + foreach (scandir($d, \SCANDIR_SORT_NONE) ?: [] as $link) { + if ('.' !== $link && '..' !== $link && (null !== $renamed || !realpath($d.\DIRECTORY_SEPARATOR.$link))) { + unlink($d.\DIRECTORY_SEPARATOR.$link); + } + } + null === $renamed ?: rmdir($d); + } + null === $renamed ?: rmdir($dir.$chars[$i]); + } + null === $renamed ?: rmdir($renamed); + } + } finally { + restore_error_handler(); + } + + return $ok; + } + + protected function doSave(array $values, int $lifetime, array $addTagData = [], array $removeTagData = []): array + { + $failed = $this->doSaveCache($values, $lifetime); + + // Add Tags as symlinks + foreach ($addTagData as $tagId => $ids) { + $tagFolder = $this->getTagFolder($tagId); + foreach ($ids as $id) { + if ($failed && \in_array($id, $failed, true)) { + continue; + } + + $file = $this->getFile($id); + + if (!@symlink($file, $tagLink = $this->getFile($id, true, $tagFolder)) && !is_link($tagLink)) { + @unlink($file); + $failed[] = $id; + } + } + } + + // Unlink removed Tags + foreach ($removeTagData as $tagId => $ids) { + $tagFolder = $this->getTagFolder($tagId); + foreach ($ids as $id) { + if ($failed && \in_array($id, $failed, true)) { + continue; + } + + @unlink($this->getFile($id, false, $tagFolder)); + } + } + + return $failed; + } + + protected function doDeleteYieldTags(array $ids): iterable + { + foreach ($ids as $id) { + $file = $this->getFile($id); + if (!is_file($file) || !$h = @fopen($file, 'r')) { + continue; + } + + if (!@unlink($file)) { + fclose($h); + continue; + } + + $meta = explode("\n", fread($h, 4096), 3)[2] ?? ''; + + // detect the compact format used in marshall() using magic numbers in the form 9D-..-..-..-..-00-..-..-..-5F + if (13 < \strlen($meta) && "\x9D" === $meta[0] && "\0" === $meta[5] && "\x5F" === $meta[9]) { + $meta[9] = "\0"; + $tagLen = unpack('Nlen', $meta, 9)['len']; + $meta = substr($meta, 13, $tagLen); + + if (0 < $tagLen -= \strlen($meta)) { + $meta .= fread($h, $tagLen); + } + + try { + yield $id => '' === $meta ? [] : $this->marshaller->unmarshall($meta); + } catch (\Exception) { + yield $id => []; + } + } + + fclose($h); + } + } + + protected function doDeleteTagRelations(array $tagData): bool + { + foreach ($tagData as $tagId => $idList) { + $tagFolder = $this->getTagFolder($tagId); + foreach ($idList as $id) { + @unlink($this->getFile($id, false, $tagFolder)); + } + } + + return true; + } + + protected function doInvalidate(array $tagIds): bool + { + foreach ($tagIds as $tagId) { + if (!is_dir($tagFolder = $this->getTagFolder($tagId))) { + continue; + } + + $this->tmpSuffix ??= str_replace('/', '-', base64_encode(random_bytes(6))); + + set_error_handler(static function () {}); + + try { + if (rename($tagFolder, $renamed = substr_replace($tagFolder, $this->tmpSuffix.'_', -10))) { + $tagFolder = $renamed.\DIRECTORY_SEPARATOR; + } else { + $renamed = null; + } + + foreach ($this->scanHashDir($tagFolder) as $itemLink) { + unlink(realpath($itemLink) ?: $itemLink); + unlink($itemLink); + } + + if (null === $renamed) { + continue; + } + + $chars = '+-ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; + + for ($i = 0; $i < 38; ++$i) { + for ($j = 0; $j < 38; ++$j) { + rmdir($tagFolder.$chars[$i].\DIRECTORY_SEPARATOR.$chars[$j]); + } + rmdir($tagFolder.$chars[$i]); + } + rmdir($renamed); + } finally { + restore_error_handler(); + } + } + + return true; + } + + private function getTagFolder(string $tagId): string + { + return $this->getFile($tagId, false, $this->directory.self::TAG_FOLDER.\DIRECTORY_SEPARATOR).\DIRECTORY_SEPARATOR; + } +} diff --git a/vendor/symfony/cache/Adapter/MemcachedAdapter.php b/vendor/symfony/cache/Adapter/MemcachedAdapter.php new file mode 100644 index 0000000..d882ef1 --- /dev/null +++ b/vendor/symfony/cache/Adapter/MemcachedAdapter.php @@ -0,0 +1,329 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Adapter; + +use Symfony\Component\Cache\Exception\CacheException; +use Symfony\Component\Cache\Exception\InvalidArgumentException; +use Symfony\Component\Cache\Marshaller\DefaultMarshaller; +use Symfony\Component\Cache\Marshaller\MarshallerInterface; + +/** + * @author Rob Frawley 2nd + * @author Nicolas Grekas + */ +class MemcachedAdapter extends AbstractAdapter +{ + /** + * We are replacing characters that are illegal in Memcached keys with reserved characters from + * {@see \Symfony\Contracts\Cache\ItemInterface::RESERVED_CHARACTERS} that are legal in Memcached. + * Note: don’t use {@see AbstractAdapter::NS_SEPARATOR}. + */ + private const RESERVED_MEMCACHED = " \n\r\t\v\f\0"; + private const RESERVED_PSR6 = '@()\{}/'; + private const MAX_KEY_LENGTH = 250; + + private MarshallerInterface $marshaller; + private \Memcached $client; + private \Memcached $lazyClient; + + /** + * Using a MemcachedAdapter with a TagAwareAdapter for storing tags is discouraged. + * Using a RedisAdapter is recommended instead. If you cannot do otherwise, be aware that: + * - the Memcached::OPT_BINARY_PROTOCOL must be enabled + * (that's the default when using MemcachedAdapter::createConnection()); + * - tags eviction by Memcached's LRU algorithm will break by-tags invalidation; + * your Memcached memory should be large enough to never trigger LRU. + * + * Using a MemcachedAdapter as a pure items store is fine. + */ + public function __construct(\Memcached $client, string $namespace = '', int $defaultLifetime = 0, ?MarshallerInterface $marshaller = null) + { + if (!static::isSupported()) { + throw new CacheException('Memcached > 3.1.5 is required.'); + } + $this->maxIdLength = self::MAX_KEY_LENGTH; + + if ('Memcached' === $client::class) { + $opt = $client->getOption(\Memcached::OPT_SERIALIZER); + if (\Memcached::SERIALIZER_PHP !== $opt && \Memcached::SERIALIZER_IGBINARY !== $opt) { + throw new CacheException('MemcachedAdapter: "serializer" option must be "php" or "igbinary".'); + } + $this->maxIdLength -= \strlen($client->getOption(\Memcached::OPT_PREFIX_KEY)); + $this->client = $client; + } else { + $this->lazyClient = $client; + } + + parent::__construct($namespace, $defaultLifetime); + $this->enableVersioning(); + $this->marshaller = $marshaller ?? new DefaultMarshaller(); + } + + public static function isSupported(): bool + { + return \extension_loaded('memcached') && version_compare(phpversion('memcached'), '3.1.6', '>='); + } + + /** + * Creates a Memcached instance. + * + * By default, the binary protocol, no block, and libketama compatible options are enabled. + * + * Examples for servers: + * - 'memcached://user:pass@localhost?weight=33' + * - [['localhost', 11211, 33]] + * + * @param array[]|string|string[] $servers An array of servers, a DSN, or an array of DSNs + * + * @throws \ErrorException When invalid options or servers are provided + */ + public static function createConnection(#[\SensitiveParameter] array|string $servers, array $options = []): \Memcached + { + if (\is_string($servers)) { + $servers = [$servers]; + } + if (!static::isSupported()) { + throw new CacheException('Memcached > 3.1.5 is required.'); + } + set_error_handler(static fn ($type, $msg, $file, $line) => throw new \ErrorException($msg, 0, $type, $file, $line)); + try { + $client = new \Memcached($options['persistent_id'] ?? null); + $username = $options['username'] ?? null; + $password = $options['password'] ?? null; + + // parse any DSN in $servers + foreach ($servers as $i => $dsn) { + if (\is_array($dsn)) { + continue; + } + if (!str_starts_with($dsn, 'memcached:')) { + throw new InvalidArgumentException('Invalid Memcached DSN: it does not start with "memcached:".'); + } + $params = preg_replace_callback('#^memcached:(//)?(?:([^@]*+)@)?#', function ($m) use (&$username, &$password) { + if (!empty($m[2])) { + [$username, $password] = explode(':', $m[2], 2) + [1 => null]; + $username = rawurldecode($username); + $password = null !== $password ? rawurldecode($password) : null; + } + + return 'file:'.($m[1] ?? ''); + }, $dsn); + if (false === $params = parse_url($params)) { + throw new InvalidArgumentException('Invalid Memcached DSN.'); + } + $query = $hosts = []; + if (isset($params['query'])) { + parse_str($params['query'], $query); + + if (isset($query['host'])) { + if (!\is_array($hosts = $query['host'])) { + throw new InvalidArgumentException('Invalid Memcached DSN: query parameter "host" must be an array.'); + } + foreach ($hosts as $host => $weight) { + if (false === $port = strrpos($host, ':')) { + $hosts[$host] = [$host, 11211, (int) $weight]; + } else { + $hosts[$host] = [substr($host, 0, $port), (int) substr($host, 1 + $port), (int) $weight]; + } + } + $hosts = array_values($hosts); + unset($query['host']); + } + if ($hosts && !isset($params['host']) && !isset($params['path'])) { + unset($servers[$i]); + $servers = array_merge($servers, $hosts); + continue; + } + } + if (!isset($params['host']) && !isset($params['path'])) { + throw new InvalidArgumentException('Invalid Memcached DSN: missing host or path.'); + } + if (isset($params['path']) && preg_match('#/(\d+)$#', $params['path'], $m)) { + $params['weight'] = $m[1]; + $params['path'] = substr($params['path'], 0, -\strlen($m[0])); + } + $params += [ + 'host' => $params['host'] ?? $params['path'], + 'port' => isset($params['host']) ? 11211 : null, + 'weight' => 0, + ]; + if ($query) { + $params += $query; + $options = $query + $options; + } + + $servers[$i] = [$params['host'], $params['port'], $params['weight']]; + + if ($hosts) { + $servers = array_merge($servers, $hosts); + } + } + + // set client's options + unset($options['persistent_id'], $options['username'], $options['password'], $options['weight'], $options['lazy']); + $options = array_change_key_case($options, \CASE_UPPER); + $client->setOption(\Memcached::OPT_BINARY_PROTOCOL, true); + $client->setOption(\Memcached::OPT_NO_BLOCK, true); + $client->setOption(\Memcached::OPT_TCP_NODELAY, true); + if (!\array_key_exists('LIBKETAMA_COMPATIBLE', $options) && !\array_key_exists(\Memcached::OPT_LIBKETAMA_COMPATIBLE, $options)) { + $client->setOption(\Memcached::OPT_LIBKETAMA_COMPATIBLE, true); + } + foreach ($options as $name => $value) { + if (\is_int($name)) { + continue; + } + if ('HASH' === $name || 'SERIALIZER' === $name || 'DISTRIBUTION' === $name) { + $value = \constant('Memcached::'.$name.'_'.strtoupper($value)); + } + unset($options[$name]); + + if (\defined('Memcached::OPT_'.$name)) { + $options[\constant('Memcached::OPT_'.$name)] = $value; + } + } + $client->setOptions($options + [\Memcached::OPT_SERIALIZER => \Memcached::SERIALIZER_PHP]); + + // set client's servers, taking care of persistent connections + if (!$client->isPristine()) { + $oldServers = []; + foreach ($client->getServerList() as $server) { + $oldServers[] = [$server['host'], $server['port']]; + } + + $newServers = []; + foreach ($servers as $server) { + if (1 < \count($server)) { + $server = array_values($server); + unset($server[2]); + $server[1] = (int) $server[1]; + } + $newServers[] = $server; + } + + if ($oldServers !== $newServers) { + $client->resetServerList(); + $client->addServers($servers); + } + } else { + $client->addServers($servers); + } + + if (null !== $username || null !== $password) { + if (!method_exists($client, 'setSaslAuthData')) { + trigger_error('Missing SASL support: the memcached extension must be compiled with --enable-memcached-sasl.'); + } + $client->setSaslAuthData($username, $password); + } + + return $client; + } finally { + restore_error_handler(); + } + } + + protected function doSave(array $values, int $lifetime): array|bool + { + if (!$values = $this->marshaller->marshall($values, $failed)) { + return $failed; + } + + if ($lifetime && $lifetime > 30 * 86400) { + $lifetime += time(); + } + + $encodedValues = []; + foreach ($values as $key => $value) { + $encodedValues[self::encodeKey($key)] = $value; + } + + return $this->checkResultCode($this->getClient()->setMulti($encodedValues, $lifetime)) ? $failed : false; + } + + protected function doFetch(array $ids): iterable + { + try { + $encodedIds = array_map([__CLASS__, 'encodeKey'], $ids); + + $encodedResult = $this->checkResultCode($this->getClient()->getMulti($encodedIds)); + + $result = []; + foreach ($encodedResult as $key => $value) { + $result[self::decodeKey($key)] = $this->marshaller->unmarshall($value); + } + + return $result; + } catch (\Error $e) { + throw new \ErrorException($e->getMessage(), $e->getCode(), \E_ERROR, $e->getFile(), $e->getLine()); + } + } + + protected function doHave(string $id): bool + { + return false !== $this->getClient()->get(self::encodeKey($id)) || $this->checkResultCode(\Memcached::RES_SUCCESS === $this->client->getResultCode()); + } + + protected function doDelete(array $ids): bool + { + $ok = true; + $encodedIds = array_map([__CLASS__, 'encodeKey'], $ids); + foreach ($this->checkResultCode($this->getClient()->deleteMulti($encodedIds)) as $result) { + if (\Memcached::RES_SUCCESS !== $result && \Memcached::RES_NOTFOUND !== $result) { + $ok = false; + } + } + + return $ok; + } + + protected function doClear(string $namespace): bool + { + return '' === $namespace && $this->getClient()->flush(); + } + + private function checkResultCode(mixed $result): mixed + { + $code = $this->client->getResultCode(); + + if (\Memcached::RES_SUCCESS === $code || \Memcached::RES_NOTFOUND === $code) { + return $result; + } + + throw new CacheException('MemcachedAdapter client error: '.strtolower($this->client->getResultMessage())); + } + + private function getClient(): \Memcached + { + if (isset($this->client)) { + return $this->client; + } + + $opt = $this->lazyClient->getOption(\Memcached::OPT_SERIALIZER); + if (\Memcached::SERIALIZER_PHP !== $opt && \Memcached::SERIALIZER_IGBINARY !== $opt) { + throw new CacheException('MemcachedAdapter: "serializer" option must be "php" or "igbinary".'); + } + if ('' !== $prefix = (string) $this->lazyClient->getOption(\Memcached::OPT_PREFIX_KEY)) { + throw new CacheException(\sprintf('MemcachedAdapter: "prefix_key" option must be empty when using proxified connections, "%s" given.', $prefix)); + } + + return $this->client = $this->lazyClient; + } + + private static function encodeKey(string $key): string + { + return strtr($key, self::RESERVED_MEMCACHED, self::RESERVED_PSR6); + } + + private static function decodeKey(string $key): string + { + return strtr($key, self::RESERVED_PSR6, self::RESERVED_MEMCACHED); + } +} diff --git a/vendor/symfony/cache/Adapter/NullAdapter.php b/vendor/symfony/cache/Adapter/NullAdapter.php new file mode 100644 index 0000000..d5d2ef6 --- /dev/null +++ b/vendor/symfony/cache/Adapter/NullAdapter.php @@ -0,0 +1,105 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Adapter; + +use Psr\Cache\CacheItemInterface; +use Symfony\Component\Cache\CacheItem; +use Symfony\Contracts\Cache\CacheInterface; + +/** + * @author Titouan Galopin + */ +class NullAdapter implements AdapterInterface, CacheInterface +{ + private static \Closure $createCacheItem; + + public function __construct() + { + self::$createCacheItem ??= \Closure::bind( + static function ($key) { + $item = new CacheItem(); + $item->key = $key; + $item->isHit = false; + + return $item; + }, + null, + CacheItem::class + ); + } + + public function get(string $key, callable $callback, ?float $beta = null, ?array &$metadata = null): mixed + { + $save = true; + + return $callback((self::$createCacheItem)($key), $save); + } + + public function getItem(mixed $key): CacheItem + { + return (self::$createCacheItem)($key); + } + + public function getItems(array $keys = []): iterable + { + return $this->generateItems($keys); + } + + public function hasItem(mixed $key): bool + { + return false; + } + + public function clear(string $prefix = ''): bool + { + return true; + } + + public function deleteItem(mixed $key): bool + { + return true; + } + + public function deleteItems(array $keys): bool + { + return true; + } + + public function save(CacheItemInterface $item): bool + { + return true; + } + + public function saveDeferred(CacheItemInterface $item): bool + { + return true; + } + + public function commit(): bool + { + return true; + } + + public function delete(string $key): bool + { + return $this->deleteItem($key); + } + + private function generateItems(array $keys): \Generator + { + $f = self::$createCacheItem; + + foreach ($keys as $key) { + yield $key => $f($key); + } + } +} diff --git a/vendor/symfony/cache/Adapter/ParameterNormalizer.php b/vendor/symfony/cache/Adapter/ParameterNormalizer.php new file mode 100644 index 0000000..483df1c --- /dev/null +++ b/vendor/symfony/cache/Adapter/ParameterNormalizer.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Adapter; + +/** + * @author Lars Strojny + */ +final class ParameterNormalizer +{ + public static function normalizeDuration(string $duration): int + { + if (is_numeric($duration)) { + return $duration; + } + + if (false !== $time = strtotime($duration, 0)) { + return $time; + } + + try { + return \DateTimeImmutable::createFromFormat('U', 0)->add(new \DateInterval($duration))->getTimestamp(); + } catch (\Exception $e) { + throw new \InvalidArgumentException(\sprintf('Cannot parse date interval "%s".', $duration), 0, $e); + } + } +} diff --git a/vendor/symfony/cache/Adapter/PdoAdapter.php b/vendor/symfony/cache/Adapter/PdoAdapter.php new file mode 100644 index 0000000..525e2c6 --- /dev/null +++ b/vendor/symfony/cache/Adapter/PdoAdapter.php @@ -0,0 +1,398 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Adapter; + +use Symfony\Component\Cache\Exception\InvalidArgumentException; +use Symfony\Component\Cache\Marshaller\DefaultMarshaller; +use Symfony\Component\Cache\Marshaller\MarshallerInterface; +use Symfony\Component\Cache\PruneableInterface; + +class PdoAdapter extends AbstractAdapter implements PruneableInterface +{ + private const MAX_KEY_LENGTH = 255; + + private MarshallerInterface $marshaller; + private \PDO $conn; + private string $dsn; + private string $driver; + private string $serverVersion; + private string $table = 'cache_items'; + private string $idCol = 'item_id'; + private string $dataCol = 'item_data'; + private string $lifetimeCol = 'item_lifetime'; + private string $timeCol = 'item_time'; + private ?string $username = null; + private ?string $password = null; + private array $connectionOptions = []; + private string $namespace; + + /** + * You can either pass an existing database connection as PDO instance or + * a DSN string that will be used to lazy-connect to the database when the + * cache is actually used. + * + * List of available options: + * * db_table: The name of the table [default: cache_items] + * * db_id_col: The column where to store the cache id [default: item_id] + * * db_data_col: The column where to store the cache data [default: item_data] + * * db_lifetime_col: The column where to store the lifetime [default: item_lifetime] + * * db_time_col: The column where to store the timestamp [default: item_time] + * * db_username: The username when lazy-connect [default: ''] + * * db_password: The password when lazy-connect [default: ''] + * * db_connection_options: An array of driver-specific connection options [default: []] + * + * @throws InvalidArgumentException When first argument is not PDO nor Connection nor string + * @throws InvalidArgumentException When PDO error mode is not PDO::ERRMODE_EXCEPTION + * @throws InvalidArgumentException When namespace contains invalid characters + */ + public function __construct(#[\SensitiveParameter] \PDO|string $connOrDsn, string $namespace = '', int $defaultLifetime = 0, array $options = [], ?MarshallerInterface $marshaller = null) + { + if (\is_string($connOrDsn) && str_contains($connOrDsn, '://')) { + throw new InvalidArgumentException(\sprintf('Usage of Doctrine DBAL URL with "%s" is not supported. Use a PDO DSN or "%s" instead.', __CLASS__, DoctrineDbalAdapter::class)); + } + + if (isset($namespace[0]) && preg_match('#[^-+.A-Za-z0-9]#', $namespace, $match)) { + throw new InvalidArgumentException(\sprintf('Namespace contains "%s" but only characters in [-+.A-Za-z0-9] are allowed.', $match[0])); + } + + if ($connOrDsn instanceof \PDO) { + if (\PDO::ERRMODE_EXCEPTION !== $connOrDsn->getAttribute(\PDO::ATTR_ERRMODE)) { + throw new InvalidArgumentException(\sprintf('"%s" requires PDO error mode attribute be set to throw Exceptions (i.e. $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)).', __CLASS__)); + } + + $this->conn = $connOrDsn; + } else { + $this->dsn = $connOrDsn; + } + + $this->maxIdLength = self::MAX_KEY_LENGTH; + $this->table = $options['db_table'] ?? $this->table; + $this->idCol = $options['db_id_col'] ?? $this->idCol; + $this->dataCol = $options['db_data_col'] ?? $this->dataCol; + $this->lifetimeCol = $options['db_lifetime_col'] ?? $this->lifetimeCol; + $this->timeCol = $options['db_time_col'] ?? $this->timeCol; + $this->username = $options['db_username'] ?? $this->username; + $this->password = $options['db_password'] ?? $this->password; + $this->connectionOptions = $options['db_connection_options'] ?? $this->connectionOptions; + $this->namespace = $namespace; + $this->marshaller = $marshaller ?? new DefaultMarshaller(); + + parent::__construct($namespace, $defaultLifetime); + } + + public static function createConnection(#[\SensitiveParameter] string $dsn, array $options = []): \PDO|string + { + if ($options['lazy'] ?? true) { + return $dsn; + } + + $pdo = new \PDO($dsn); + $pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); + + return $pdo; + } + + /** + * Creates the table to store cache items which can be called once for setup. + * + * Cache ID are saved in a column of maximum length 255. Cache data is + * saved in a BLOB. + * + * @throws \PDOException When the table already exists + * @throws \DomainException When an unsupported PDO driver is used + */ + public function createTable(): void + { + $sql = match ($driver = $this->getDriver()) { + // We use varbinary for the ID column because it prevents unwanted conversions: + // - character set conversions between server and client + // - trailing space removal + // - case-insensitivity + // - language processing like Ć© == e + 'mysql' => "CREATE TABLE $this->table ($this->idCol VARBINARY(255) NOT NULL PRIMARY KEY, $this->dataCol MEDIUMBLOB NOT NULL, $this->lifetimeCol INTEGER UNSIGNED, $this->timeCol INTEGER UNSIGNED NOT NULL) COLLATE utf8mb4_bin, ENGINE = InnoDB", + 'sqlite' => "CREATE TABLE $this->table ($this->idCol TEXT NOT NULL PRIMARY KEY, $this->dataCol BLOB NOT NULL, $this->lifetimeCol INTEGER, $this->timeCol INTEGER NOT NULL)", + 'pgsql' => "CREATE TABLE $this->table ($this->idCol VARCHAR(255) NOT NULL PRIMARY KEY, $this->dataCol BYTEA NOT NULL, $this->lifetimeCol INTEGER, $this->timeCol INTEGER NOT NULL)", + 'oci' => "CREATE TABLE $this->table ($this->idCol VARCHAR2(255) NOT NULL PRIMARY KEY, $this->dataCol BLOB NOT NULL, $this->lifetimeCol INTEGER, $this->timeCol INTEGER NOT NULL)", + 'sqlsrv' => "CREATE TABLE $this->table ($this->idCol VARCHAR(255) NOT NULL PRIMARY KEY, $this->dataCol VARBINARY(MAX) NOT NULL, $this->lifetimeCol INTEGER, $this->timeCol INTEGER NOT NULL)", + default => throw new \DomainException(\sprintf('Creating the cache table is currently not implemented for PDO driver "%s".', $driver)), + }; + + $this->getConnection()->exec($sql); + } + + public function prune(): bool + { + $deleteSql = "DELETE FROM $this->table WHERE $this->lifetimeCol + $this->timeCol <= :time"; + + if ('' !== $this->namespace) { + $deleteSql .= " AND $this->idCol LIKE :namespace"; + } + + $connection = $this->getConnection(); + + try { + $delete = $connection->prepare($deleteSql); + } catch (\PDOException) { + return true; + } + $delete->bindValue(':time', time(), \PDO::PARAM_INT); + + if ('' !== $this->namespace) { + $delete->bindValue(':namespace', \sprintf('%s%%', $this->namespace), \PDO::PARAM_STR); + } + try { + return $delete->execute(); + } catch (\PDOException) { + return true; + } + } + + protected function doFetch(array $ids): iterable + { + $connection = $this->getConnection(); + + $now = time(); + $expired = []; + + $sql = str_pad('', (\count($ids) << 1) - 1, '?,'); + $sql = "SELECT $this->idCol, CASE WHEN $this->lifetimeCol IS NULL OR $this->lifetimeCol + $this->timeCol > ? THEN $this->dataCol ELSE NULL END FROM $this->table WHERE $this->idCol IN ($sql)"; + $stmt = $connection->prepare($sql); + $stmt->bindValue($i = 1, $now, \PDO::PARAM_INT); + foreach ($ids as $id) { + $stmt->bindValue(++$i, $id); + } + $result = $stmt->execute(); + + if (\is_object($result)) { + $result = $result->iterateNumeric(); + } else { + $stmt->setFetchMode(\PDO::FETCH_NUM); + $result = $stmt; + } + + foreach ($result as $row) { + if (null === $row[1]) { + $expired[] = $row[0]; + } else { + yield $row[0] => $this->marshaller->unmarshall(\is_resource($row[1]) ? stream_get_contents($row[1]) : $row[1]); + } + } + + if ($expired) { + $sql = str_pad('', (\count($expired) << 1) - 1, '?,'); + $sql = "DELETE FROM $this->table WHERE $this->lifetimeCol + $this->timeCol <= ? AND $this->idCol IN ($sql)"; + $stmt = $connection->prepare($sql); + $stmt->bindValue($i = 1, $now, \PDO::PARAM_INT); + foreach ($expired as $id) { + $stmt->bindValue(++$i, $id); + } + $stmt->execute(); + } + } + + protected function doHave(string $id): bool + { + $connection = $this->getConnection(); + + $sql = "SELECT 1 FROM $this->table WHERE $this->idCol = :id AND ($this->lifetimeCol IS NULL OR $this->lifetimeCol + $this->timeCol > :time)"; + $stmt = $connection->prepare($sql); + + $stmt->bindValue(':id', $id); + $stmt->bindValue(':time', time(), \PDO::PARAM_INT); + $stmt->execute(); + + return (bool) $stmt->fetchColumn(); + } + + protected function doClear(string $namespace): bool + { + $conn = $this->getConnection(); + + if ('' === $namespace) { + if ('sqlite' === $this->getDriver()) { + $sql = "DELETE FROM $this->table"; + } else { + $sql = "TRUNCATE TABLE $this->table"; + } + } else { + $sql = "DELETE FROM $this->table WHERE $this->idCol LIKE '$namespace%'"; + } + + try { + $conn->exec($sql); + } catch (\PDOException) { + } + + return true; + } + + protected function doDelete(array $ids): bool + { + $sql = str_pad('', (\count($ids) << 1) - 1, '?,'); + $sql = "DELETE FROM $this->table WHERE $this->idCol IN ($sql)"; + try { + $stmt = $this->getConnection()->prepare($sql); + $stmt->execute(array_values($ids)); + } catch (\PDOException) { + } + + return true; + } + + protected function doSave(array $values, int $lifetime): array|bool + { + if (!$values = $this->marshaller->marshall($values, $failed)) { + return $failed; + } + + $conn = $this->getConnection(); + + $driver = $this->getDriver(); + $insertSql = "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, :data, :lifetime, :time)"; + + switch (true) { + case 'mysql' === $driver: + $sql = $insertSql." ON DUPLICATE KEY UPDATE $this->dataCol = VALUES($this->dataCol), $this->lifetimeCol = VALUES($this->lifetimeCol), $this->timeCol = VALUES($this->timeCol)"; + break; + case 'oci' === $driver: + // DUAL is Oracle specific dummy table + $sql = "MERGE INTO $this->table USING DUAL ON ($this->idCol = ?) ". + "WHEN NOT MATCHED THEN INSERT ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (?, ?, ?, ?) ". + "WHEN MATCHED THEN UPDATE SET $this->dataCol = ?, $this->lifetimeCol = ?, $this->timeCol = ?"; + break; + case 'sqlsrv' === $driver && version_compare($this->getServerVersion(), '10', '>='): + // MERGE is only available since SQL Server 2008 and must be terminated by semicolon + // It also requires HOLDLOCK according to http://weblogs.sqlteam.com/dang/archive/2009/01/31/UPSERT-Race-Condition-With-MERGE.aspx + $sql = "MERGE INTO $this->table WITH (HOLDLOCK) USING (SELECT 1 AS dummy) AS src ON ($this->idCol = ?) ". + "WHEN NOT MATCHED THEN INSERT ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (?, ?, ?, ?) ". + "WHEN MATCHED THEN UPDATE SET $this->dataCol = ?, $this->lifetimeCol = ?, $this->timeCol = ?;"; + break; + case 'sqlite' === $driver: + $sql = 'INSERT OR REPLACE'.substr($insertSql, 6); + break; + case 'pgsql' === $driver && version_compare($this->getServerVersion(), '9.5', '>='): + $sql = $insertSql." ON CONFLICT ($this->idCol) DO UPDATE SET ($this->dataCol, $this->lifetimeCol, $this->timeCol) = (EXCLUDED.$this->dataCol, EXCLUDED.$this->lifetimeCol, EXCLUDED.$this->timeCol)"; + break; + default: + $driver = null; + $sql = "UPDATE $this->table SET $this->dataCol = :data, $this->lifetimeCol = :lifetime, $this->timeCol = :time WHERE $this->idCol = :id"; + break; + } + + $now = time(); + $lifetime = $lifetime ?: null; + try { + $stmt = $conn->prepare($sql); + } catch (\PDOException $e) { + if ($this->isTableMissing($e) && (!$conn->inTransaction() || \in_array($driver, ['pgsql', 'sqlite', 'sqlsrv'], true))) { + $this->createTable(); + } + $stmt = $conn->prepare($sql); + } + + // $id and $data are defined later in the loop. Binding is done by reference, values are read on execution. + if ('sqlsrv' === $driver || 'oci' === $driver) { + $stmt->bindParam(1, $id); + $stmt->bindParam(2, $id); + $stmt->bindParam(3, $data, \PDO::PARAM_LOB); + $stmt->bindValue(4, $lifetime, \PDO::PARAM_INT); + $stmt->bindValue(5, $now, \PDO::PARAM_INT); + $stmt->bindParam(6, $data, \PDO::PARAM_LOB); + $stmt->bindValue(7, $lifetime, \PDO::PARAM_INT); + $stmt->bindValue(8, $now, \PDO::PARAM_INT); + } else { + $stmt->bindParam(':id', $id); + $stmt->bindParam(':data', $data, \PDO::PARAM_LOB); + $stmt->bindValue(':lifetime', $lifetime, \PDO::PARAM_INT); + $stmt->bindValue(':time', $now, \PDO::PARAM_INT); + } + if (null === $driver) { + $insertStmt = $conn->prepare($insertSql); + + $insertStmt->bindParam(':id', $id); + $insertStmt->bindParam(':data', $data, \PDO::PARAM_LOB); + $insertStmt->bindValue(':lifetime', $lifetime, \PDO::PARAM_INT); + $insertStmt->bindValue(':time', $now, \PDO::PARAM_INT); + } + + foreach ($values as $id => $data) { + try { + $stmt->execute(); + } catch (\PDOException $e) { + if ($this->isTableMissing($e) && (!$conn->inTransaction() || \in_array($driver, ['pgsql', 'sqlite', 'sqlsrv'], true))) { + $this->createTable(); + } + $stmt->execute(); + } + if (null === $driver && !$stmt->rowCount()) { + try { + $insertStmt->execute(); + } catch (\PDOException) { + // A concurrent write won, let it be + } + } + } + + return $failed; + } + + /** + * @internal + */ + protected function getId(mixed $key): string + { + if ('pgsql' !== $this->getDriver()) { + return parent::getId($key); + } + + if (str_contains($key, "\0") || str_contains($key, '%') || !preg_match('//u', $key)) { + $key = rawurlencode($key); + } + + return parent::getId($key); + } + + private function getConnection(): \PDO + { + if (!isset($this->conn)) { + $this->conn = new \PDO($this->dsn, $this->username, $this->password, $this->connectionOptions); + $this->conn->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); + } + + return $this->conn; + } + + private function getDriver(): string + { + return $this->driver ??= $this->getConnection()->getAttribute(\PDO::ATTR_DRIVER_NAME); + } + + private function getServerVersion(): string + { + return $this->serverVersion ??= $this->getConnection()->getAttribute(\PDO::ATTR_SERVER_VERSION); + } + + private function isTableMissing(\PDOException $exception): bool + { + $driver = $this->getDriver(); + [$sqlState, $code] = $exception->errorInfo ?? [null, $exception->getCode()]; + + return match ($driver) { + 'pgsql' => '42P01' === $sqlState, + 'sqlite' => str_contains($exception->getMessage(), 'no such table:'), + 'oci' => 942 === $code, + 'sqlsrv' => 208 === $code, + 'mysql' => 1146 === $code, + default => false, + }; + } +} diff --git a/vendor/symfony/cache/Adapter/PhpArrayAdapter.php b/vendor/symfony/cache/Adapter/PhpArrayAdapter.php new file mode 100644 index 0000000..8047a8a --- /dev/null +++ b/vendor/symfony/cache/Adapter/PhpArrayAdapter.php @@ -0,0 +1,389 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Adapter; + +use Psr\Cache\CacheItemInterface; +use Psr\Cache\CacheItemPoolInterface; +use Symfony\Component\Cache\CacheItem; +use Symfony\Component\Cache\Exception\InvalidArgumentException; +use Symfony\Component\Cache\PruneableInterface; +use Symfony\Component\Cache\ResettableInterface; +use Symfony\Component\Cache\Traits\ContractsTrait; +use Symfony\Component\Cache\Traits\ProxyTrait; +use Symfony\Component\VarExporter\VarExporter; +use Symfony\Contracts\Cache\CacheInterface; + +/** + * Caches items at warm up time using a PHP array that is stored in shared memory by OPCache since PHP 7.0. + * Warmed up items are read-only and run-time discovered items are cached using a fallback adapter. + * + * @author Titouan Galopin + * @author Nicolas Grekas + */ +class PhpArrayAdapter implements AdapterInterface, CacheInterface, PruneableInterface, ResettableInterface +{ + use ContractsTrait; + use ProxyTrait; + + private array $keys; + private array $values; + + private static \Closure $createCacheItem; + private static array $valuesCache = []; + + /** + * @param string $file The PHP file where values are cached + * @param AdapterInterface $fallbackPool A pool to fallback on when an item is not hit + */ + public function __construct( + private string $file, + AdapterInterface $fallbackPool, + ) { + $this->pool = $fallbackPool; + self::$createCacheItem ??= \Closure::bind( + static function ($key, $value, $isHit) { + $item = new CacheItem(); + $item->key = $key; + $item->value = $value; + $item->isHit = $isHit; + + return $item; + }, + null, + CacheItem::class + ); + } + + /** + * This adapter takes advantage of how PHP stores arrays in its latest versions. + * + * @param string $file The PHP file were values are cached + * @param CacheItemPoolInterface $fallbackPool A pool to fallback on when an item is not hit + */ + public static function create(string $file, CacheItemPoolInterface $fallbackPool): CacheItemPoolInterface + { + if (!$fallbackPool instanceof AdapterInterface) { + $fallbackPool = new ProxyAdapter($fallbackPool); + } + + return new static($file, $fallbackPool); + } + + public function get(string $key, callable $callback, ?float $beta = null, ?array &$metadata = null): mixed + { + if (!isset($this->values)) { + $this->initialize(); + } + if (!isset($this->keys[$key])) { + get_from_pool: + if ($this->pool instanceof CacheInterface) { + return $this->pool->get($key, $callback, $beta, $metadata); + } + + return $this->doGet($this->pool, $key, $callback, $beta, $metadata); + } + $value = $this->values[$this->keys[$key]]; + + if ('N;' === $value) { + return null; + } + try { + if ($value instanceof \Closure) { + return $value(); + } + } catch (\Throwable) { + unset($this->keys[$key]); + goto get_from_pool; + } + + return $value; + } + + public function getItem(mixed $key): CacheItem + { + if (!\is_string($key)) { + throw new InvalidArgumentException(\sprintf('Cache key must be string, "%s" given.', get_debug_type($key))); + } + if (!isset($this->values)) { + $this->initialize(); + } + if (!isset($this->keys[$key])) { + return $this->pool->getItem($key); + } + + $value = $this->values[$this->keys[$key]]; + $isHit = true; + + if ('N;' === $value) { + $value = null; + } elseif ($value instanceof \Closure) { + try { + $value = $value(); + } catch (\Throwable) { + $value = null; + $isHit = false; + } + } + + return (self::$createCacheItem)($key, $value, $isHit); + } + + public function getItems(array $keys = []): iterable + { + foreach ($keys as $key) { + if (!\is_string($key)) { + throw new InvalidArgumentException(\sprintf('Cache key must be string, "%s" given.', get_debug_type($key))); + } + } + if (!isset($this->values)) { + $this->initialize(); + } + + return $this->generateItems($keys); + } + + public function hasItem(mixed $key): bool + { + if (!\is_string($key)) { + throw new InvalidArgumentException(\sprintf('Cache key must be string, "%s" given.', get_debug_type($key))); + } + if (!isset($this->values)) { + $this->initialize(); + } + + return isset($this->keys[$key]) || $this->pool->hasItem($key); + } + + public function deleteItem(mixed $key): bool + { + if (!\is_string($key)) { + throw new InvalidArgumentException(\sprintf('Cache key must be string, "%s" given.', get_debug_type($key))); + } + if (!isset($this->values)) { + $this->initialize(); + } + + return !isset($this->keys[$key]) && $this->pool->deleteItem($key); + } + + public function deleteItems(array $keys): bool + { + $deleted = true; + $fallbackKeys = []; + + foreach ($keys as $key) { + if (!\is_string($key)) { + throw new InvalidArgumentException(\sprintf('Cache key must be string, "%s" given.', get_debug_type($key))); + } + + if (isset($this->keys[$key])) { + $deleted = false; + } else { + $fallbackKeys[] = $key; + } + } + if (!isset($this->values)) { + $this->initialize(); + } + + if ($fallbackKeys) { + $deleted = $this->pool->deleteItems($fallbackKeys) && $deleted; + } + + return $deleted; + } + + public function save(CacheItemInterface $item): bool + { + if (!isset($this->values)) { + $this->initialize(); + } + + return !isset($this->keys[$item->getKey()]) && $this->pool->save($item); + } + + public function saveDeferred(CacheItemInterface $item): bool + { + if (!isset($this->values)) { + $this->initialize(); + } + + return !isset($this->keys[$item->getKey()]) && $this->pool->saveDeferred($item); + } + + public function commit(): bool + { + return $this->pool->commit(); + } + + public function clear(string $prefix = ''): bool + { + $this->keys = $this->values = []; + + $cleared = @unlink($this->file) || !file_exists($this->file); + unset(self::$valuesCache[$this->file]); + + if ($this->pool instanceof AdapterInterface) { + return $this->pool->clear($prefix) && $cleared; + } + + return $this->pool->clear() && $cleared; + } + + /** + * Store an array of cached values. + * + * @param array $values The cached values + * + * @return string[] A list of classes to preload on PHP 7.4+ + */ + public function warmUp(array $values): array + { + if (file_exists($this->file)) { + if (!is_file($this->file)) { + throw new InvalidArgumentException(\sprintf('Cache path exists and is not a file: "%s".', $this->file)); + } + + if (!is_writable($this->file)) { + throw new InvalidArgumentException(\sprintf('Cache file is not writable: "%s".', $this->file)); + } + } else { + $directory = \dirname($this->file); + + if (!is_dir($directory) && !@mkdir($directory, 0777, true)) { + throw new InvalidArgumentException(\sprintf('Cache directory does not exist and cannot be created: "%s".', $directory)); + } + + if (!is_writable($directory)) { + throw new InvalidArgumentException(\sprintf('Cache directory is not writable: "%s".', $directory)); + } + } + + $preload = []; + $dumpedValues = ''; + $dumpedMap = []; + $dump = <<<'EOF' + $value) { + CacheItem::validateKey(\is_int($key) ? (string) $key : $key); + $isStaticValue = true; + + if (null === $value) { + $value = "'N;'"; + } elseif (\is_object($value) || \is_array($value)) { + try { + $value = VarExporter::export($value, $isStaticValue, $preload); + } catch (\Exception $e) { + throw new InvalidArgumentException(\sprintf('Cache key "%s" has non-serializable "%s" value.', $key, get_debug_type($value)), 0, $e); + } + } elseif (\is_string($value)) { + // Wrap "N;" in a closure to not confuse it with an encoded `null` + if ('N;' === $value) { + $isStaticValue = false; + } + $value = var_export($value, true); + } elseif (!\is_scalar($value)) { + throw new InvalidArgumentException(\sprintf('Cache key "%s" has non-serializable "%s" value.', $key, get_debug_type($value))); + } else { + $value = var_export($value, true); + } + + if (!$isStaticValue) { + $value = str_replace("\n", "\n ", $value); + $value = "static function () {\n return {$value};\n}"; + } + $hash = hash('xxh128', $value); + + if (null === $id = $dumpedMap[$hash] ?? null) { + $id = $dumpedMap[$hash] = \count($dumpedMap); + $dumpedValues .= "{$id} => {$value},\n"; + } + + $dump .= var_export($key, true)." => {$id},\n"; + } + + $dump .= "\n], [\n\n{$dumpedValues}\n]];\n"; + + $tmpFile = tempnam(\dirname($this->file), basename($this->file)); + + file_put_contents($tmpFile, $dump); + @chmod($tmpFile, 0666 & ~umask()); + unset($serialized, $value, $dump); + + @rename($tmpFile, $this->file); + unset(self::$valuesCache[$this->file]); + + $this->initialize(); + + return $preload; + } + + /** + * Load the cache file. + */ + private function initialize(): void + { + if (isset(self::$valuesCache[$this->file])) { + $values = self::$valuesCache[$this->file]; + } elseif (!is_file($this->file)) { + $this->keys = $this->values = []; + + return; + } else { + $values = self::$valuesCache[$this->file] = (include $this->file) ?: [[], []]; + } + + if (2 !== \count($values) || !isset($values[0], $values[1])) { + $this->keys = $this->values = []; + } else { + [$this->keys, $this->values] = $values; + } + } + + private function generateItems(array $keys): \Generator + { + $f = self::$createCacheItem; + $fallbackKeys = []; + + foreach ($keys as $key) { + if (isset($this->keys[$key])) { + $value = $this->values[$this->keys[$key]]; + + if ('N;' === $value) { + yield $key => $f($key, null, true); + } elseif ($value instanceof \Closure) { + try { + yield $key => $f($key, $value(), true); + } catch (\Throwable) { + yield $key => $f($key, null, false); + } + } else { + yield $key => $f($key, $value, true); + } + } else { + $fallbackKeys[] = $key; + } + } + + if ($fallbackKeys) { + yield from $this->pool->getItems($fallbackKeys); + } + } +} diff --git a/vendor/symfony/cache/Adapter/PhpFilesAdapter.php b/vendor/symfony/cache/Adapter/PhpFilesAdapter.php new file mode 100644 index 0000000..df0d0e7 --- /dev/null +++ b/vendor/symfony/cache/Adapter/PhpFilesAdapter.php @@ -0,0 +1,312 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Adapter; + +use Symfony\Component\Cache\Exception\CacheException; +use Symfony\Component\Cache\Exception\InvalidArgumentException; +use Symfony\Component\Cache\PruneableInterface; +use Symfony\Component\Cache\Traits\FilesystemCommonTrait; +use Symfony\Component\VarExporter\VarExporter; + +/** + * @author Piotr Stankowski + * @author Nicolas Grekas + * @author Rob Frawley 2nd + */ +class PhpFilesAdapter extends AbstractAdapter implements PruneableInterface +{ + use FilesystemCommonTrait { + doClear as private doCommonClear; + doDelete as private doCommonDelete; + } + + private \Closure $includeHandler; + private array $values = []; + private array $files = []; + + private static int $startTime; + private static array $valuesCache = []; + + /** + * @param bool $appendOnly Set to `true` to gain extra performance when the items stored in this pool never expire. + * Doing so is encouraged because it fits perfectly OPcache's memory model. + * + * @throws CacheException if OPcache is not enabled + */ + public function __construct( + string $namespace = '', + int $defaultLifetime = 0, + ?string $directory = null, + private bool $appendOnly = false, + ) { + self::$startTime ??= $_SERVER['REQUEST_TIME'] ?? time(); + parent::__construct('', $defaultLifetime); + $this->init($namespace, $directory); + $this->includeHandler = static function ($type, $msg, $file, $line) { + throw new \ErrorException($msg, 0, $type, $file, $line); + }; + } + + public static function isSupported(): bool + { + self::$startTime ??= $_SERVER['REQUEST_TIME'] ?? time(); + + return \function_exists('opcache_invalidate') && filter_var(\ini_get('opcache.enable'), \FILTER_VALIDATE_BOOL) && (!\in_array(\PHP_SAPI, ['cli', 'phpdbg', 'embed'], true) || filter_var(\ini_get('opcache.enable_cli'), \FILTER_VALIDATE_BOOL)); + } + + public function prune(): bool + { + $time = time(); + $pruned = true; + $getExpiry = true; + + set_error_handler($this->includeHandler); + try { + foreach ($this->scanHashDir($this->directory) as $file) { + try { + if (\is_array($expiresAt = include $file)) { + $expiresAt = $expiresAt[0]; + } + } catch (\ErrorException $e) { + $expiresAt = $time; + } + + if ($time >= $expiresAt) { + $pruned = ($this->doUnlink($file) || !file_exists($file)) && $pruned; + } + } + } finally { + restore_error_handler(); + } + + return $pruned; + } + + protected function doFetch(array $ids): iterable + { + if ($this->appendOnly) { + $now = 0; + $missingIds = []; + } else { + $now = time(); + $missingIds = $ids; + $ids = []; + } + $values = []; + + begin: + $getExpiry = false; + + foreach ($ids as $id) { + if (null === $value = $this->values[$id] ?? null) { + $missingIds[] = $id; + } elseif ('N;' === $value) { + $values[$id] = null; + } elseif (!\is_object($value)) { + $values[$id] = $value; + } elseif (!$value instanceof LazyValue) { + $values[$id] = $value(); + } elseif (false === $values[$id] = include $value->file) { + unset($values[$id], $this->values[$id]); + $missingIds[] = $id; + } + if (!$this->appendOnly) { + unset($this->values[$id]); + } + } + + if (!$missingIds) { + return $values; + } + + set_error_handler($this->includeHandler); + try { + $getExpiry = true; + + foreach ($missingIds as $k => $id) { + try { + $file = $this->files[$id] ??= $this->getFile($id); + + if (isset(self::$valuesCache[$file])) { + [$expiresAt, $this->values[$id]] = self::$valuesCache[$file]; + } elseif (\is_array($expiresAt = include $file)) { + if ($this->appendOnly) { + self::$valuesCache[$file] = $expiresAt; + } + + [$expiresAt, $this->values[$id]] = $expiresAt; + } elseif ($now < $expiresAt) { + $this->values[$id] = new LazyValue($file); + } + + if ($now >= $expiresAt) { + unset($this->values[$id], $missingIds[$k], self::$valuesCache[$file]); + } + } catch (\ErrorException $e) { + unset($missingIds[$k]); + } + } + } finally { + restore_error_handler(); + } + + $ids = $missingIds; + $missingIds = []; + goto begin; + } + + protected function doHave(string $id): bool + { + if ($this->appendOnly && isset($this->values[$id])) { + return true; + } + + set_error_handler($this->includeHandler); + try { + $file = $this->files[$id] ??= $this->getFile($id); + $getExpiry = true; + + if (isset(self::$valuesCache[$file])) { + [$expiresAt, $value] = self::$valuesCache[$file]; + } elseif (\is_array($expiresAt = include $file)) { + if ($this->appendOnly) { + self::$valuesCache[$file] = $expiresAt; + } + + [$expiresAt, $value] = $expiresAt; + } elseif ($this->appendOnly) { + $value = new LazyValue($file); + } + } catch (\ErrorException) { + return false; + } finally { + restore_error_handler(); + } + if ($this->appendOnly) { + $now = 0; + $this->values[$id] = $value; + } else { + $now = time(); + } + + return $now < $expiresAt; + } + + protected function doSave(array $values, int $lifetime): array|bool + { + $ok = true; + $expiry = $lifetime ? time() + $lifetime : 'PHP_INT_MAX'; + $allowCompile = self::isSupported(); + + foreach ($values as $key => $value) { + unset($this->values[$key]); + $isStaticValue = true; + if (null === $value) { + $value = "'N;'"; + } elseif (\is_object($value) || \is_array($value)) { + try { + $value = VarExporter::export($value, $isStaticValue); + } catch (\Exception $e) { + throw new InvalidArgumentException(\sprintf('Cache key "%s" has non-serializable "%s" value.', $key, get_debug_type($value)), 0, $e); + } + } elseif (\is_string($value)) { + // Wrap "N;" in a closure to not confuse it with an encoded `null` + if ('N;' === $value) { + $isStaticValue = false; + } + $value = var_export($value, true); + } elseif (!\is_scalar($value)) { + throw new InvalidArgumentException(\sprintf('Cache key "%s" has non-serializable "%s" value.', $key, get_debug_type($value))); + } else { + $value = var_export($value, true); + } + + $encodedKey = rawurlencode($key); + + if ($isStaticValue) { + $value = "return [{$expiry}, {$value}];"; + } elseif ($this->appendOnly) { + $value = "return [{$expiry}, static fn () => {$value}];"; + } else { + // We cannot use a closure here because of https://bugs.php.net/76982 + $value = str_replace('\Symfony\Component\VarExporter\Internal\\', '', $value); + $value = "namespace Symfony\Component\VarExporter\Internal;\n\nreturn \$getExpiry ? {$expiry} : {$value};"; + } + + $file = $this->files[$key] = $this->getFile($key, true); + // Since OPcache only compiles files older than the script execution start, set the file's mtime in the past + $ok = $this->write($file, "directory)) { + throw new CacheException(\sprintf('Cache directory is not writable (%s).', $this->directory)); + } + + return $ok; + } + + protected function doClear(string $namespace): bool + { + $this->values = []; + + return $this->doCommonClear($namespace); + } + + protected function doDelete(array $ids): bool + { + foreach ($ids as $id) { + unset($this->values[$id]); + } + + return $this->doCommonDelete($ids); + } + + protected function doUnlink(string $file): bool + { + unset(self::$valuesCache[$file]); + + if (self::isSupported()) { + @opcache_invalidate($file, true); + } + + return @unlink($file); + } + + private function getFileKey(string $file): string + { + if (!$h = @fopen($file, 'r')) { + return ''; + } + + $encodedKey = substr(fgets($h), 8); + fclose($h); + + return rawurldecode(rtrim($encodedKey)); + } +} + +/** + * @internal + */ +class LazyValue +{ + public function __construct( + public string $file, + ) { + } +} diff --git a/vendor/symfony/cache/Adapter/ProxyAdapter.php b/vendor/symfony/cache/Adapter/ProxyAdapter.php new file mode 100644 index 0000000..5621226 --- /dev/null +++ b/vendor/symfony/cache/Adapter/ProxyAdapter.php @@ -0,0 +1,206 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Adapter; + +use Psr\Cache\CacheItemInterface; +use Psr\Cache\CacheItemPoolInterface; +use Symfony\Component\Cache\CacheItem; +use Symfony\Component\Cache\PruneableInterface; +use Symfony\Component\Cache\ResettableInterface; +use Symfony\Component\Cache\Traits\ContractsTrait; +use Symfony\Component\Cache\Traits\ProxyTrait; +use Symfony\Contracts\Cache\CacheInterface; + +/** + * @author Nicolas Grekas + */ +class ProxyAdapter implements AdapterInterface, CacheInterface, PruneableInterface, ResettableInterface +{ + use ContractsTrait; + use ProxyTrait; + + private string $namespace = ''; + private int $namespaceLen; + private string $poolHash; + private int $defaultLifetime; + + private static \Closure $createCacheItem; + private static \Closure $setInnerItem; + + public function __construct(CacheItemPoolInterface $pool, string $namespace = '', int $defaultLifetime = 0) + { + $this->pool = $pool; + $this->poolHash = spl_object_hash($pool); + if ('' !== $namespace) { + \assert('' !== CacheItem::validateKey($namespace)); + $this->namespace = $namespace; + } + $this->namespaceLen = \strlen($namespace); + $this->defaultLifetime = $defaultLifetime; + self::$createCacheItem ??= \Closure::bind( + static function ($key, $innerItem, $poolHash) { + $item = new CacheItem(); + $item->key = $key; + + if (null === $innerItem) { + return $item; + } + + $item->value = $innerItem->get(); + $item->isHit = $innerItem->isHit(); + $item->innerItem = $innerItem; + $item->poolHash = $poolHash; + + if (!$item->unpack() && $innerItem instanceof CacheItem) { + $item->metadata = $innerItem->metadata; + } + $innerItem->set(null); + + return $item; + }, + null, + CacheItem::class + ); + self::$setInnerItem ??= \Closure::bind( + static function (CacheItemInterface $innerItem, CacheItem $item, $expiry = null) { + $innerItem->set($item->pack()); + $innerItem->expiresAt(($expiry ?? $item->expiry) ? \DateTimeImmutable::createFromFormat('U.u', \sprintf('%.6F', $expiry ?? $item->expiry)) : null); + }, + null, + CacheItem::class + ); + } + + public function get(string $key, callable $callback, ?float $beta = null, ?array &$metadata = null): mixed + { + if (!$this->pool instanceof CacheInterface) { + return $this->doGet($this, $key, $callback, $beta, $metadata); + } + + return $this->pool->get($this->getId($key), function ($innerItem, bool &$save) use ($key, $callback) { + $item = (self::$createCacheItem)($key, $innerItem, $this->poolHash); + $item->set($value = $callback($item, $save)); + (self::$setInnerItem)($innerItem, $item); + + return $value; + }, $beta, $metadata); + } + + public function getItem(mixed $key): CacheItem + { + $item = $this->pool->getItem($this->getId($key)); + + return (self::$createCacheItem)($key, $item, $this->poolHash); + } + + public function getItems(array $keys = []): iterable + { + if ($this->namespaceLen) { + foreach ($keys as $i => $key) { + $keys[$i] = $this->getId($key); + } + } + + return $this->generateItems($this->pool->getItems($keys)); + } + + public function hasItem(mixed $key): bool + { + return $this->pool->hasItem($this->getId($key)); + } + + public function clear(string $prefix = ''): bool + { + if ($this->pool instanceof AdapterInterface) { + return $this->pool->clear($this->namespace.$prefix); + } + + return $this->pool->clear(); + } + + public function deleteItem(mixed $key): bool + { + return $this->pool->deleteItem($this->getId($key)); + } + + public function deleteItems(array $keys): bool + { + if ($this->namespaceLen) { + foreach ($keys as $i => $key) { + $keys[$i] = $this->getId($key); + } + } + + return $this->pool->deleteItems($keys); + } + + public function save(CacheItemInterface $item): bool + { + return $this->doSave($item, __FUNCTION__); + } + + public function saveDeferred(CacheItemInterface $item): bool + { + return $this->doSave($item, __FUNCTION__); + } + + public function commit(): bool + { + return $this->pool->commit(); + } + + private function doSave(CacheItemInterface $item, string $method): bool + { + if (!$item instanceof CacheItem) { + return false; + } + $castItem = (array) $item; + + if (null === $castItem["\0*\0expiry"] && 0 < $this->defaultLifetime) { + $castItem["\0*\0expiry"] = microtime(true) + $this->defaultLifetime; + } + + if ($castItem["\0*\0poolHash"] === $this->poolHash && $castItem["\0*\0innerItem"]) { + $innerItem = $castItem["\0*\0innerItem"]; + } elseif ($this->pool instanceof AdapterInterface) { + // this is an optimization specific for AdapterInterface implementations + // so we can save a round-trip to the backend by just creating a new item + $innerItem = (self::$createCacheItem)($this->namespace.$castItem["\0*\0key"], null, $this->poolHash); + } else { + $innerItem = $this->pool->getItem($this->namespace.$castItem["\0*\0key"]); + } + + (self::$setInnerItem)($innerItem, $item, $castItem["\0*\0expiry"]); + + return $this->pool->$method($innerItem); + } + + private function generateItems(iterable $items): \Generator + { + $f = self::$createCacheItem; + + foreach ($items as $key => $item) { + if ($this->namespaceLen) { + $key = substr($key, $this->namespaceLen); + } + + yield $key => $f($key, $item, $this->poolHash); + } + } + + private function getId(mixed $key): string + { + \assert('' !== CacheItem::validateKey($key)); + + return $this->namespace.$key; + } +} diff --git a/vendor/symfony/cache/Adapter/Psr16Adapter.php b/vendor/symfony/cache/Adapter/Psr16Adapter.php new file mode 100644 index 0000000..a72b037 --- /dev/null +++ b/vendor/symfony/cache/Adapter/Psr16Adapter.php @@ -0,0 +1,71 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Adapter; + +use Psr\SimpleCache\CacheInterface; +use Symfony\Component\Cache\PruneableInterface; +use Symfony\Component\Cache\ResettableInterface; +use Symfony\Component\Cache\Traits\ProxyTrait; + +/** + * Turns a PSR-16 cache into a PSR-6 one. + * + * @author Nicolas Grekas + */ +class Psr16Adapter extends AbstractAdapter implements PruneableInterface, ResettableInterface +{ + use ProxyTrait; + + /** + * @internal + */ + protected const NS_SEPARATOR = '_'; + + private object $miss; + + public function __construct(CacheInterface $pool, string $namespace = '', int $defaultLifetime = 0) + { + parent::__construct($namespace, $defaultLifetime); + + $this->pool = $pool; + $this->miss = new \stdClass(); + } + + protected function doFetch(array $ids): iterable + { + foreach ($this->pool->getMultiple($ids, $this->miss) as $key => $value) { + if ($this->miss !== $value) { + yield $key => $value; + } + } + } + + protected function doHave(string $id): bool + { + return $this->pool->has($id); + } + + protected function doClear(string $namespace): bool + { + return $this->pool->clear(); + } + + protected function doDelete(array $ids): bool + { + return $this->pool->deleteMultiple($ids); + } + + protected function doSave(array $values, int $lifetime): array|bool + { + return $this->pool->setMultiple($values, 0 === $lifetime ? null : $lifetime); + } +} diff --git a/vendor/symfony/cache/Adapter/RedisAdapter.php b/vendor/symfony/cache/Adapter/RedisAdapter.php new file mode 100644 index 0000000..e33f2f6 --- /dev/null +++ b/vendor/symfony/cache/Adapter/RedisAdapter.php @@ -0,0 +1,25 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Adapter; + +use Symfony\Component\Cache\Marshaller\MarshallerInterface; +use Symfony\Component\Cache\Traits\RedisTrait; + +class RedisAdapter extends AbstractAdapter +{ + use RedisTrait; + + public function __construct(\Redis|\RedisArray|\RedisCluster|\Predis\ClientInterface|\Relay\Relay $redis, string $namespace = '', int $defaultLifetime = 0, ?MarshallerInterface $marshaller = null) + { + $this->init($redis, $namespace, $defaultLifetime, $marshaller); + } +} diff --git a/vendor/symfony/cache/Adapter/RedisTagAwareAdapter.php b/vendor/symfony/cache/Adapter/RedisTagAwareAdapter.php new file mode 100644 index 0000000..7b28237 --- /dev/null +++ b/vendor/symfony/cache/Adapter/RedisTagAwareAdapter.php @@ -0,0 +1,310 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Adapter; + +use Predis\Connection\Aggregate\ClusterInterface; +use Predis\Connection\Aggregate\PredisCluster; +use Predis\Connection\Aggregate\ReplicationInterface; +use Predis\Response\ErrorInterface; +use Predis\Response\Status; +use Relay\Relay; +use Symfony\Component\Cache\CacheItem; +use Symfony\Component\Cache\Exception\InvalidArgumentException; +use Symfony\Component\Cache\Exception\LogicException; +use Symfony\Component\Cache\Marshaller\DeflateMarshaller; +use Symfony\Component\Cache\Marshaller\MarshallerInterface; +use Symfony\Component\Cache\Marshaller\TagAwareMarshaller; +use Symfony\Component\Cache\Traits\RedisTrait; + +/** + * Stores tag id <> cache id relationship as a Redis Set. + * + * Set (tag relation info) is stored without expiry (non-volatile), while cache always gets an expiry (volatile) even + * if not set by caller. Thus if you configure redis with the right eviction policy you can be safe this tag <> cache + * relationship survives eviction (cache cleanup when Redis runs out of memory). + * + * Redis server 2.8+ with any `volatile-*` eviction policy, OR `noeviction` if you're sure memory will NEVER fill up + * + * Design limitations: + * - Max 4 billion cache keys per cache tag as limited by Redis Set datatype. + * E.g. If you use a "all" items tag for expiry instead of clear(), that limits you to 4 billion cache items also. + * + * @see https://redis.io/topics/lru-cache#eviction-policies Documentation for Redis eviction policies. + * @see https://redis.io/topics/data-types#sets Documentation for Redis Set datatype. + * + * @author Nicolas Grekas + * @author AndrĆ© RĆømcke + */ +class RedisTagAwareAdapter extends AbstractTagAwareAdapter +{ + use RedisTrait; + + /** + * On cache items without a lifetime set, we set it to 100 days. This is to make sure cache items are + * preferred to be evicted over tag Sets, if eviction policy is configured according to requirements. + */ + private const DEFAULT_CACHE_TTL = 8640000; + + /** + * detected eviction policy used on Redis server. + */ + private string $redisEvictionPolicy; + + public function __construct( + \Redis|Relay|\RedisArray|\RedisCluster|\Predis\ClientInterface $redis, + private string $namespace = '', + int $defaultLifetime = 0, + ?MarshallerInterface $marshaller = null, + ) { + if ($redis instanceof \Predis\ClientInterface && $redis->getConnection() instanceof ClusterInterface && !$redis->getConnection() instanceof PredisCluster) { + throw new InvalidArgumentException(\sprintf('Unsupported Predis cluster connection: only "%s" is, "%s" given.', PredisCluster::class, get_debug_type($redis->getConnection()))); + } + + $isRelay = $redis instanceof Relay; + if ($isRelay || \defined('Redis::OPT_COMPRESSION') && \in_array($redis::class, [\Redis::class, \RedisArray::class, \RedisCluster::class], true)) { + $compression = $redis->getOption($isRelay ? Relay::OPT_COMPRESSION : \Redis::OPT_COMPRESSION); + + foreach (\is_array($compression) ? $compression : [$compression] as $c) { + if ($isRelay ? Relay::COMPRESSION_NONE : \Redis::COMPRESSION_NONE !== $c) { + throw new InvalidArgumentException(\sprintf('redis compression must be disabled when using "%s", use "%s" instead.', static::class, DeflateMarshaller::class)); + } + } + } + + $this->init($redis, $namespace, $defaultLifetime, new TagAwareMarshaller($marshaller)); + } + + protected function doSave(array $values, int $lifetime, array $addTagData = [], array $delTagData = []): array + { + $eviction = $this->getRedisEvictionPolicy(); + if ('noeviction' !== $eviction && !str_starts_with($eviction, 'volatile-')) { + throw new LogicException(\sprintf('Redis maxmemory-policy setting "%s" is *not* supported by RedisTagAwareAdapter, use "noeviction" or "volatile-*" eviction policies.', $eviction)); + } + + // serialize values + if (!$serialized = $this->marshaller->marshall($values, $failed)) { + return $failed; + } + + // While pipeline isn't supported on RedisCluster, other setups will at least benefit from doing this in one op + $results = $this->pipeline(static function () use ($serialized, $lifetime, $addTagData, $delTagData, $failed) { + // Store cache items, force a ttl if none is set, as there is no MSETEX we need to set each one + foreach ($serialized as $id => $value) { + yield 'setEx' => [ + $id, + 0 >= $lifetime ? self::DEFAULT_CACHE_TTL : $lifetime, + $value, + ]; + } + + // Add and Remove Tags + foreach ($addTagData as $tagId => $ids) { + if (!$failed || $ids = array_diff($ids, $failed)) { + yield 'sAdd' => array_merge([$tagId], $ids); + } + } + + foreach ($delTagData as $tagId => $ids) { + if (!$failed || $ids = array_diff($ids, $failed)) { + yield 'sRem' => array_merge([$tagId], $ids); + } + } + }); + + foreach ($results as $id => $result) { + // Skip results of SADD/SREM operations, they'll be 1 or 0 depending on if set value already existed or not + if (is_numeric($result)) { + continue; + } + // setEx results + if (true !== $result && (!$result instanceof Status || Status::get('OK') !== $result)) { + $failed[] = $id; + } + } + + return $failed; + } + + protected function doDeleteYieldTags(array $ids): iterable + { + $lua = <<<'EOLUA' + local v = redis.call('GET', KEYS[1]) + local e = redis.pcall('UNLINK', KEYS[1]) + + if type(e) ~= 'number' then + redis.call('DEL', KEYS[1]) + end + + if not v or v:len() <= 13 or v:byte(1) ~= 0x9D or v:byte(6) ~= 0 or v:byte(10) ~= 0x5F then + return '' + end + + return v:sub(14, 13 + v:byte(13) + v:byte(12) * 256 + v:byte(11) * 65536) +EOLUA; + + $results = $this->pipeline(function () use ($ids, $lua) { + foreach ($ids as $id) { + yield 'eval' => $this->redis instanceof \Predis\ClientInterface ? [$lua, 1, $id] : [$lua, [$id], 1]; + } + }); + + foreach ($results as $id => $result) { + if ($result instanceof \RedisException || $result instanceof \Relay\Exception || $result instanceof ErrorInterface) { + CacheItem::log($this->logger, 'Failed to delete key "{key}": '.$result->getMessage(), ['key' => substr($id, \strlen($this->namespace)), 'exception' => $result]); + + continue; + } + + try { + yield $id => !\is_string($result) || '' === $result ? [] : $this->marshaller->unmarshall($result); + } catch (\Exception) { + yield $id => []; + } + } + } + + protected function doDeleteTagRelations(array $tagData): bool + { + $results = $this->pipeline(static function () use ($tagData) { + foreach ($tagData as $tagId => $idList) { + array_unshift($idList, $tagId); + yield 'sRem' => $idList; + } + }); + foreach ($results as $result) { + // no-op + } + + return true; + } + + protected function doInvalidate(array $tagIds): bool + { + // This script scans the set of items linked to tag: it empties the set + // and removes the linked items. When the set is still not empty after + // the scan, it means we're in cluster mode and that the linked items + // are on other nodes: we move the links to a temporary set and we + // garbage collect that set from the client side. + + $lua = <<<'EOLUA' + redis.replicate_commands() + + local cursor = '0' + local id = KEYS[1] + repeat + local result = redis.call('SSCAN', id, cursor, 'COUNT', 5000); + cursor = result[1]; + local rems = {} + + for _, v in ipairs(result[2]) do + local ok, _ = pcall(redis.call, 'DEL', ARGV[1]..v) + if ok then + table.insert(rems, v) + end + end + if 0 < #rems then + redis.call('SREM', id, unpack(rems)) + end + until '0' == cursor; + + redis.call('SUNIONSTORE', '{'..id..'}'..id, id) + redis.call('DEL', id) + + return redis.call('SSCAN', '{'..id..'}'..id, '0', 'COUNT', 5000) +EOLUA; + + $results = $this->pipeline(function () use ($tagIds, $lua) { + if ($this->redis instanceof \Predis\ClientInterface) { + $prefix = $this->redis->getOptions()->prefix ? $this->redis->getOptions()->prefix->getPrefix() : ''; + } elseif (\is_array($prefix = $this->redis->getOption($this->redis instanceof Relay ? Relay::OPT_PREFIX : \Redis::OPT_PREFIX) ?? '')) { + $prefix = current($prefix); + } + + foreach ($tagIds as $id) { + yield 'eval' => $this->redis instanceof \Predis\ClientInterface ? [$lua, 1, $id, $prefix] : [$lua, [$id, $prefix], 1]; + } + }); + + $lua = <<<'EOLUA' + redis.replicate_commands() + + local id = KEYS[1] + local cursor = table.remove(ARGV) + redis.call('SREM', '{'..id..'}'..id, unpack(ARGV)) + + return redis.call('SSCAN', '{'..id..'}'..id, cursor, 'COUNT', 5000) +EOLUA; + + $success = true; + foreach ($results as $id => $values) { + if ($values instanceof \RedisException || $values instanceof \Relay\Exception || $values instanceof ErrorInterface) { + CacheItem::log($this->logger, 'Failed to invalidate key "{key}": '.$values->getMessage(), ['key' => substr($id, \strlen($this->namespace)), 'exception' => $values]); + $success = false; + + continue; + } + + [$cursor, $ids] = $values; + + while ($ids || '0' !== $cursor) { + $this->doDelete($ids); + + $evalArgs = [$id, $cursor]; + array_splice($evalArgs, 1, 0, $ids); + + if ($this->redis instanceof \Predis\ClientInterface) { + array_unshift($evalArgs, $lua, 1); + } else { + $evalArgs = [$lua, $evalArgs, 1]; + } + + $results = $this->pipeline(function () use ($evalArgs) { + yield 'eval' => $evalArgs; + }); + + foreach ($results as [$cursor, $ids]) { + // no-op + } + } + } + + return $success; + } + + private function getRedisEvictionPolicy(): string + { + if (isset($this->redisEvictionPolicy)) { + return $this->redisEvictionPolicy; + } + + $hosts = $this->getHosts(); + $host = reset($hosts); + if ($host instanceof \Predis\Client && $host->getConnection() instanceof ReplicationInterface) { + // Predis supports info command only on the master in replication environments + $hosts = [$host->getClientFor('master')]; + } + + foreach ($hosts as $host) { + $info = $host->info('Memory'); + + if (false === $info || null === $info || $info instanceof ErrorInterface) { + continue; + } + + $info = $info['Memory'] ?? $info; + + return $this->redisEvictionPolicy = $info['maxmemory_policy'] ?? ''; + } + + return $this->redisEvictionPolicy = ''; + } +} diff --git a/vendor/symfony/cache/Adapter/TagAwareAdapter.php b/vendor/symfony/cache/Adapter/TagAwareAdapter.php new file mode 100644 index 0000000..53c9890 --- /dev/null +++ b/vendor/symfony/cache/Adapter/TagAwareAdapter.php @@ -0,0 +1,368 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Adapter; + +use Psr\Cache\CacheItemInterface; +use Psr\Cache\InvalidArgumentException; +use Psr\Log\LoggerAwareInterface; +use Psr\Log\LoggerAwareTrait; +use Symfony\Component\Cache\CacheItem; +use Symfony\Component\Cache\PruneableInterface; +use Symfony\Component\Cache\ResettableInterface; +use Symfony\Component\Cache\Traits\ContractsTrait; +use Symfony\Contracts\Cache\TagAwareCacheInterface; + +/** + * Implements simple and robust tag-based invalidation suitable for use with volatile caches. + * + * This adapter works by storing a version for each tags. When saving an item, it is stored together with its tags and + * their corresponding versions. When retrieving an item, those tag versions are compared to the current version of + * each tags. Invalidation is achieved by deleting tags, thereby ensuring that their versions change even when the + * storage is out of space. When versions of non-existing tags are requested for item commits, this adapter assigns a + * new random version to them. + * + * @author Nicolas Grekas + * @author Sergey Belyshkin + */ +class TagAwareAdapter implements TagAwareAdapterInterface, TagAwareCacheInterface, PruneableInterface, ResettableInterface, LoggerAwareInterface +{ + use ContractsTrait; + use LoggerAwareTrait; + + public const TAGS_PREFIX = "\1tags\1"; + + private array $deferred = []; + private AdapterInterface $pool; + private AdapterInterface $tags; + private array $knownTagVersions = []; + + private static \Closure $setCacheItemTags; + private static \Closure $setTagVersions; + private static \Closure $getTagsByKey; + private static \Closure $saveTags; + + public function __construct( + AdapterInterface $itemsPool, + ?AdapterInterface $tagsPool = null, + private float $knownTagVersionsTtl = 0.15, + ) { + $this->pool = $itemsPool; + $this->tags = $tagsPool ?? $itemsPool; + self::$setCacheItemTags ??= \Closure::bind( + static function (array $items, array $itemTags) { + foreach ($items as $key => $item) { + $item->isTaggable = true; + + if (isset($itemTags[$key])) { + $tags = array_keys($itemTags[$key]); + $item->metadata[CacheItem::METADATA_TAGS] = array_combine($tags, $tags); + } else { + $item->value = null; + $item->isHit = false; + $item->metadata = []; + } + } + + return $items; + }, + null, + CacheItem::class + ); + self::$setTagVersions ??= \Closure::bind( + static function (array $items, array $tagVersions) { + foreach ($items as $item) { + $item->newMetadata[CacheItem::METADATA_TAGS] = array_intersect_key($tagVersions, $item->newMetadata[CacheItem::METADATA_TAGS] ?? []); + } + }, + null, + CacheItem::class + ); + self::$getTagsByKey ??= \Closure::bind( + static function ($deferred) { + $tagsByKey = []; + foreach ($deferred as $key => $item) { + $tagsByKey[$key] = $item->newMetadata[CacheItem::METADATA_TAGS] ?? []; + $item->metadata = $item->newMetadata; + } + + return $tagsByKey; + }, + null, + CacheItem::class + ); + self::$saveTags ??= \Closure::bind( + static function (AdapterInterface $tagsAdapter, array $tags) { + ksort($tags); + + foreach ($tags as $v) { + $v->expiry = 0; + $tagsAdapter->saveDeferred($v); + } + + return $tagsAdapter->commit(); + }, + null, + CacheItem::class + ); + } + + public function invalidateTags(array $tags): bool + { + $ids = []; + foreach ($tags as $tag) { + \assert('' !== CacheItem::validateKey($tag)); + unset($this->knownTagVersions[$tag]); + $ids[] = $tag.static::TAGS_PREFIX; + } + + return !$tags || $this->tags->deleteItems($ids); + } + + public function hasItem(mixed $key): bool + { + return $this->getItem($key)->isHit(); + } + + public function getItem(mixed $key): CacheItem + { + foreach ($this->getItems([$key]) as $item) { + return $item; + } + } + + public function getItems(array $keys = []): iterable + { + $tagKeys = []; + $commit = false; + + foreach ($keys as $key) { + if ('' !== $key && \is_string($key)) { + $commit = $commit || isset($this->deferred[$key]); + } + } + + if ($commit) { + $this->commit(); + } + + try { + $items = $this->pool->getItems($keys); + } catch (InvalidArgumentException $e) { + $this->pool->getItems($keys); // Should throw an exception + + throw $e; + } + + $bufferedItems = $itemTags = []; + + foreach ($items as $key => $item) { + if (null !== $tags = $item->getMetadata()[CacheItem::METADATA_TAGS] ?? null) { + $itemTags[$key] = $tags; + } + + $bufferedItems[$key] = $item; + + if (null === $tags) { + $key = "\0tags\0".$key; + $tagKeys[$key] = $key; // BC with pools populated before v6.1 + } + } + + if ($tagKeys) { + foreach ($this->pool->getItems($tagKeys) as $key => $item) { + if ($item->isHit()) { + $itemTags[substr($key, \strlen("\0tags\0"))] = $item->get() ?: []; + } + } + } + + $tagVersions = $this->getTagVersions($itemTags, false); + foreach ($itemTags as $key => $tags) { + foreach ($tags as $tag => $version) { + if ($tagVersions[$tag] !== $version) { + unset($itemTags[$key]); + continue 2; + } + } + } + $tagVersions = null; + + return (self::$setCacheItemTags)($bufferedItems, $itemTags); + } + + public function clear(string $prefix = ''): bool + { + if ('' !== $prefix) { + foreach ($this->deferred as $key => $item) { + if (str_starts_with($key, $prefix)) { + unset($this->deferred[$key]); + } + } + + return $this->pool->clear($prefix); + } else { + $this->deferred = []; + } + + return $this->pool->clear(); + } + + public function deleteItem(mixed $key): bool + { + return $this->deleteItems([$key]); + } + + public function deleteItems(array $keys): bool + { + foreach ($keys as $key) { + if ('' !== $key && \is_string($key)) { + $keys[] = "\0tags\0".$key; // BC with pools populated before v6.1 + } + } + + return $this->pool->deleteItems($keys); + } + + public function save(CacheItemInterface $item): bool + { + if (!$item instanceof CacheItem) { + return false; + } + $this->deferred[$item->getKey()] = $item; + + return $this->commit(); + } + + public function saveDeferred(CacheItemInterface $item): bool + { + if (!$item instanceof CacheItem) { + return false; + } + $this->deferred[$item->getKey()] = $item; + + return true; + } + + public function commit(): bool + { + if (!$items = $this->deferred) { + return true; + } + + $tagVersions = $this->getTagVersions((self::$getTagsByKey)($items), true); + (self::$setTagVersions)($items, $tagVersions); + + $ok = true; + foreach ($items as $key => $item) { + if ($this->pool->saveDeferred($item)) { + unset($this->deferred[$key]); + } else { + $ok = false; + } + } + $ok = $this->pool->commit() && $ok; + + $tagVersions = array_keys($tagVersions); + (self::$setTagVersions)($items, array_combine($tagVersions, $tagVersions)); + + return $ok; + } + + public function prune(): bool + { + return $this->pool instanceof PruneableInterface && $this->pool->prune(); + } + + public function reset(): void + { + $this->commit(); + $this->knownTagVersions = []; + $this->pool instanceof ResettableInterface && $this->pool->reset(); + $this->tags instanceof ResettableInterface && $this->tags->reset(); + } + + public function __sleep(): array + { + throw new \BadMethodCallException('Cannot serialize '.__CLASS__); + } + + public function __wakeup(): void + { + throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); + } + + public function __destruct() + { + $this->commit(); + } + + private function getTagVersions(array $tagsByKey, bool $persistTags): array + { + $tagVersions = []; + $fetchTagVersions = $persistTags; + + foreach ($tagsByKey as $tags) { + $tagVersions += $tags; + if ($fetchTagVersions) { + continue; + } + foreach ($tags as $tag => $version) { + if ($tagVersions[$tag] !== $version) { + $fetchTagVersions = true; + } + } + } + + if (!$tagVersions) { + return []; + } + + $now = microtime(true); + $tags = []; + foreach ($tagVersions as $tag => $version) { + $tags[$tag.static::TAGS_PREFIX] = $tag; + $knownTagVersion = $this->knownTagVersions[$tag] ?? [0, null]; + if ($fetchTagVersions || $now > $knownTagVersion[0] || $knownTagVersion[1] !== $version) { + // reuse previously fetched tag versions until the expiration + $fetchTagVersions = true; + } + } + + if (!$fetchTagVersions) { + return $tagVersions; + } + + $newTags = []; + $newVersion = null; + $expiration = $now + $this->knownTagVersionsTtl; + foreach ($this->tags->getItems(array_keys($tags)) as $tag => $version) { + unset($this->knownTagVersions[$tag = $tags[$tag]]); // update FIFO + if (null !== $tagVersions[$tag] = $version->get()) { + $this->knownTagVersions[$tag] = [$expiration, $tagVersions[$tag]]; + } elseif ($persistTags) { + $newTags[$tag] = $version->set($newVersion ??= random_bytes(6)); + $tagVersions[$tag] = $newVersion; + $this->knownTagVersions[$tag] = [$expiration, $newVersion]; + } + } + + if ($newTags) { + (self::$saveTags)($this->tags, $newTags); + } + + while ($now > ($this->knownTagVersions[$tag = array_key_first($this->knownTagVersions)][0] ?? \INF)) { + unset($this->knownTagVersions[$tag]); + } + + return $tagVersions; + } +} diff --git a/vendor/symfony/cache/Adapter/TagAwareAdapterInterface.php b/vendor/symfony/cache/Adapter/TagAwareAdapterInterface.php new file mode 100644 index 0000000..9242779 --- /dev/null +++ b/vendor/symfony/cache/Adapter/TagAwareAdapterInterface.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Adapter; + +use Psr\Cache\InvalidArgumentException; + +/** + * Interface for invalidating cached items using tags. + * + * @author Nicolas Grekas + */ +interface TagAwareAdapterInterface extends AdapterInterface +{ + /** + * Invalidates cached items using tags. + * + * @param string[] $tags An array of tags to invalidate + * + * @throws InvalidArgumentException When $tags is not valid + */ + public function invalidateTags(array $tags): bool; +} diff --git a/vendor/symfony/cache/Adapter/TraceableAdapter.php b/vendor/symfony/cache/Adapter/TraceableAdapter.php new file mode 100644 index 0000000..8fe6cf3 --- /dev/null +++ b/vendor/symfony/cache/Adapter/TraceableAdapter.php @@ -0,0 +1,249 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Adapter; + +use Psr\Cache\CacheItemInterface; +use Symfony\Component\Cache\CacheItem; +use Symfony\Component\Cache\PruneableInterface; +use Symfony\Component\Cache\ResettableInterface; +use Symfony\Contracts\Cache\CacheInterface; +use Symfony\Contracts\Service\ResetInterface; + +/** + * An adapter that collects data about all cache calls. + * + * @author Aaron Scherer + * @author Tobias Nyholm + * @author Nicolas Grekas + */ +class TraceableAdapter implements AdapterInterface, CacheInterface, PruneableInterface, ResettableInterface +{ + private array $calls = []; + + public function __construct( + protected AdapterInterface $pool, + ) { + } + + public function get(string $key, callable $callback, ?float $beta = null, ?array &$metadata = null): mixed + { + if (!$this->pool instanceof CacheInterface) { + throw new \BadMethodCallException(\sprintf('Cannot call "%s::get()": this class doesn\'t implement "%s".', get_debug_type($this->pool), CacheInterface::class)); + } + + $isHit = true; + $callback = function (CacheItem $item, bool &$save) use ($callback, &$isHit) { + $isHit = $item->isHit(); + + return $callback($item, $save); + }; + + $event = $this->start(__FUNCTION__); + try { + $value = $this->pool->get($key, $callback, $beta, $metadata); + $event->result[$key] = get_debug_type($value); + } finally { + $event->end = microtime(true); + } + if ($isHit) { + ++$event->hits; + } else { + ++$event->misses; + } + + return $value; + } + + public function getItem(mixed $key): CacheItem + { + $event = $this->start(__FUNCTION__); + try { + $item = $this->pool->getItem($key); + } finally { + $event->end = microtime(true); + } + if ($event->result[$key] = $item->isHit()) { + ++$event->hits; + } else { + ++$event->misses; + } + + return $item; + } + + public function hasItem(mixed $key): bool + { + $event = $this->start(__FUNCTION__); + try { + return $event->result[$key] = $this->pool->hasItem($key); + } finally { + $event->end = microtime(true); + } + } + + public function deleteItem(mixed $key): bool + { + $event = $this->start(__FUNCTION__); + try { + return $event->result[$key] = $this->pool->deleteItem($key); + } finally { + $event->end = microtime(true); + } + } + + public function save(CacheItemInterface $item): bool + { + $event = $this->start(__FUNCTION__); + try { + return $event->result[$item->getKey()] = $this->pool->save($item); + } finally { + $event->end = microtime(true); + } + } + + public function saveDeferred(CacheItemInterface $item): bool + { + $event = $this->start(__FUNCTION__); + try { + return $event->result[$item->getKey()] = $this->pool->saveDeferred($item); + } finally { + $event->end = microtime(true); + } + } + + public function getItems(array $keys = []): iterable + { + $event = $this->start(__FUNCTION__); + try { + $result = $this->pool->getItems($keys); + } finally { + $event->end = microtime(true); + } + $f = function () use ($result, $event) { + $event->result = []; + foreach ($result as $key => $item) { + if ($event->result[$key] = $item->isHit()) { + ++$event->hits; + } else { + ++$event->misses; + } + yield $key => $item; + } + }; + + return $f(); + } + + public function clear(string $prefix = ''): bool + { + $event = $this->start(__FUNCTION__); + try { + if ($this->pool instanceof AdapterInterface) { + return $event->result = $this->pool->clear($prefix); + } + + return $event->result = $this->pool->clear(); + } finally { + $event->end = microtime(true); + } + } + + public function deleteItems(array $keys): bool + { + $event = $this->start(__FUNCTION__); + $event->result['keys'] = $keys; + try { + return $event->result['result'] = $this->pool->deleteItems($keys); + } finally { + $event->end = microtime(true); + } + } + + public function commit(): bool + { + $event = $this->start(__FUNCTION__); + try { + return $event->result = $this->pool->commit(); + } finally { + $event->end = microtime(true); + } + } + + public function prune(): bool + { + if (!$this->pool instanceof PruneableInterface) { + return false; + } + $event = $this->start(__FUNCTION__); + try { + return $event->result = $this->pool->prune(); + } finally { + $event->end = microtime(true); + } + } + + public function reset(): void + { + if ($this->pool instanceof ResetInterface) { + $this->pool->reset(); + } + + $this->clearCalls(); + } + + public function delete(string $key): bool + { + $event = $this->start(__FUNCTION__); + try { + return $event->result[$key] = $this->pool->deleteItem($key); + } finally { + $event->end = microtime(true); + } + } + + public function getCalls(): array + { + return $this->calls; + } + + public function clearCalls(): void + { + $this->calls = []; + } + + public function getPool(): AdapterInterface + { + return $this->pool; + } + + protected function start(string $name): TraceableAdapterEvent + { + $this->calls[] = $event = new TraceableAdapterEvent(); + $event->name = $name; + $event->start = microtime(true); + + return $event; + } +} + +/** + * @internal + */ +class TraceableAdapterEvent +{ + public string $name; + public float $start; + public float $end; + public array|bool $result; + public int $hits = 0; + public int $misses = 0; +} diff --git a/vendor/symfony/cache/Adapter/TraceableTagAwareAdapter.php b/vendor/symfony/cache/Adapter/TraceableTagAwareAdapter.php new file mode 100644 index 0000000..c85d199 --- /dev/null +++ b/vendor/symfony/cache/Adapter/TraceableTagAwareAdapter.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Adapter; + +use Symfony\Contracts\Cache\TagAwareCacheInterface; + +/** + * @author Robin Chalas + */ +class TraceableTagAwareAdapter extends TraceableAdapter implements TagAwareAdapterInterface, TagAwareCacheInterface +{ + public function __construct(TagAwareAdapterInterface $pool) + { + parent::__construct($pool); + } + + public function invalidateTags(array $tags): bool + { + $event = $this->start(__FUNCTION__); + try { + return $event->result = $this->pool->invalidateTags($tags); + } finally { + $event->end = microtime(true); + } + } +} diff --git a/vendor/symfony/cache/CHANGELOG.md b/vendor/symfony/cache/CHANGELOG.md new file mode 100644 index 0000000..038915c --- /dev/null +++ b/vendor/symfony/cache/CHANGELOG.md @@ -0,0 +1,154 @@ +CHANGELOG +========= + +7.2 +--- + + * `igbinary_serialize()` is no longer used instead of `serialize()` by default when the igbinary extension is installed, + due to behavior compatibilities between the two + * Add optional `Psr\Clock\ClockInterface` parameter to `ArrayAdapter` + +7.1 +--- + + * Add option `sentinel_master` as an alias for `redis_sentinel` + * Deprecate `CouchbaseBucketAdapter`, use `CouchbaseCollectionAdapter` + * Add support for URL encoded characters in Couchbase DSN + * Add support for using DSN with PDOAdapter + * The algorithm for the default cache namespace changed from SHA256 to XXH128 + +7.0 +--- + + * Add parameter `$isSameDatabase` to `DoctrineDbalAdapter::configureSchema()` + * Drop support for Postgres < 9.5 and SQL Server < 2008 in `DoctrineDbalAdapter` + +6.4 +--- + + * `EarlyExpirationHandler` no longer implements `MessageHandlerInterface`, rely on `AsMessageHandler` instead + +6.3 +--- + + * Add support for Relay PHP extension for Redis + * Updates to allow Redis cluster connections using predis/predis:^2.0 + * Add optional parameter `$isSameDatabase` to `DoctrineDbalAdapter::configureSchema()` + +6.1 +--- + + * Add support for ACL auth in RedisAdapter + * Improve reliability and performance of `TagAwareAdapter` by making tag versions an integral part of item value + +6.0 +--- + + * Remove `DoctrineProvider` and `DoctrineAdapter` + * Remove support of Doctrine DBAL in `PdoAdapter` + +5.4 +--- + + * Deprecate `DoctrineProvider` and `DoctrineAdapter` because these classes have been added to the `doctrine/cache` package + * Add `DoctrineDbalAdapter` identical to `PdoAdapter` for `Doctrine\DBAL\Connection` or DBAL URL + * Deprecate usage of `PdoAdapter` with `Doctrine\DBAL\Connection` or DBAL URL + +5.3 +--- + + * added support for connecting to Redis Sentinel clusters when using the Redis PHP extension + * add support for a custom serializer to the `ApcuAdapter` class + +5.2.0 +----- + + * added integration with Messenger to allow computing cached values in a worker + * allow ISO 8601 time intervals to specify default lifetime + +5.1.0 +----- + + * added max-items + LRU + max-lifetime capabilities to `ArrayCache` + * added `CouchbaseBucketAdapter` + * added context `cache-adapter` to log messages + +5.0.0 +----- + + * removed all PSR-16 implementations in the `Simple` namespace + * removed `SimpleCacheAdapter` + * removed `AbstractAdapter::unserialize()` + * removed `CacheItem::getPreviousTags()` + +4.4.0 +----- + + * added support for connecting to Redis Sentinel clusters + * added argument `$prefix` to `AdapterInterface::clear()` + * improved `RedisTagAwareAdapter` to support Redis server >= 2.8 and up to 4B items per tag + * added `TagAwareMarshaller` for optimized data storage when using `AbstractTagAwareAdapter` + * added `DeflateMarshaller` to compress serialized values + * removed support for phpredis 4 `compression` + * [BC BREAK] `RedisTagAwareAdapter` is not compatible with `RedisCluster` from `Predis` anymore, use `phpredis` instead + * Marked the `CacheDataCollector` class as `@final`. + * added `SodiumMarshaller` to encrypt/decrypt values using libsodium + +4.3.0 +----- + + * removed `psr/simple-cache` dependency, run `composer require psr/simple-cache` if you need it + * deprecated all PSR-16 adapters, use `Psr16Cache` or `Symfony\Contracts\Cache\CacheInterface` implementations instead + * deprecated `SimpleCacheAdapter`, use `Psr16Adapter` instead + +4.2.0 +----- + + * added support for connecting to Redis clusters via DSN + * added support for configuring multiple Memcached servers via DSN + * added `MarshallerInterface` and `DefaultMarshaller` to allow changing the serializer and provide one that automatically uses igbinary when available + * implemented `CacheInterface`, which provides stampede protection via probabilistic early expiration and should become the preferred way to use a cache + * added sub-second expiry accuracy for backends that support it + * added support for phpredis 4 `compression` and `tcp_keepalive` options + * added automatic table creation when using Doctrine DBAL with PDO-based backends + * throw `LogicException` when `CacheItem::tag()` is called on an item coming from a non tag-aware pool + * deprecated `CacheItem::getPreviousTags()`, use `CacheItem::getMetadata()` instead + * deprecated the `AbstractAdapter::unserialize()` and `AbstractCache::unserialize()` methods + * added `CacheCollectorPass` (originally in `FrameworkBundle`) + * added `CachePoolClearerPass` (originally in `FrameworkBundle`) + * added `CachePoolPass` (originally in `FrameworkBundle`) + * added `CachePoolPrunerPass` (originally in `FrameworkBundle`) + +3.4.0 +----- + + * added using options from Memcached DSN + * added PruneableInterface so PSR-6 or PSR-16 cache implementations can declare support for manual stale cache pruning + * added prune logic to FilesystemTrait, PhpFilesTrait, PdoTrait, TagAwareAdapter and ChainTrait + * now FilesystemAdapter, PhpFilesAdapter, FilesystemCache, PhpFilesCache, PdoAdapter, PdoCache, ChainAdapter, and + ChainCache implement PruneableInterface and support manual stale cache pruning + +3.3.0 +----- + + * added CacheItem::getPreviousTags() to get bound tags coming from the pool storage if any + * added PSR-16 "Simple Cache" implementations for all existing PSR-6 adapters + * added Psr6Cache and SimpleCacheAdapter for bidirectional interoperability between PSR-6 and PSR-16 + * added MemcachedAdapter (PSR-6) and MemcachedCache (PSR-16) + * added TraceableAdapter (PSR-6) and TraceableCache (PSR-16) + +3.2.0 +----- + + * added TagAwareAdapter for tags-based invalidation + * added PdoAdapter with PDO and Doctrine DBAL support + * added PhpArrayAdapter and PhpFilesAdapter for OPcache-backed shared memory storage (PHP 7+ only) + * added NullAdapter + +3.1.0 +----- + + * added the component with strict PSR-6 implementations + * added ApcuAdapter, ArrayAdapter, FilesystemAdapter and RedisAdapter + * added AbstractAdapter, ChainAdapter and ProxyAdapter + * added DoctrineAdapter and DoctrineProvider for bidirectional interoperability with Doctrine Cache diff --git a/vendor/symfony/cache/CacheItem.php b/vendor/symfony/cache/CacheItem.php new file mode 100644 index 0000000..ec2c0c5 --- /dev/null +++ b/vendor/symfony/cache/CacheItem.php @@ -0,0 +1,198 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache; + +use Psr\Log\LoggerInterface; +use Symfony\Component\Cache\Exception\InvalidArgumentException; +use Symfony\Component\Cache\Exception\LogicException; +use Symfony\Contracts\Cache\ItemInterface; + +/** + * @author Nicolas Grekas + */ +final class CacheItem implements ItemInterface +{ + private const METADATA_EXPIRY_OFFSET = 1527506807; + private const VALUE_WRAPPER = "\xA9"; + + protected string $key; + protected mixed $value = null; + protected bool $isHit = false; + protected float|int|null $expiry = null; + protected array $metadata = []; + protected array $newMetadata = []; + protected ?ItemInterface $innerItem = null; + protected ?string $poolHash = null; + protected bool $isTaggable = false; + + public function getKey(): string + { + return $this->key; + } + + public function get(): mixed + { + return $this->value; + } + + public function isHit(): bool + { + return $this->isHit; + } + + /** + * @return $this + */ + public function set($value): static + { + $this->value = $value; + + return $this; + } + + /** + * @return $this + */ + public function expiresAt(?\DateTimeInterface $expiration): static + { + $this->expiry = null !== $expiration ? (float) $expiration->format('U.u') : null; + + return $this; + } + + /** + * @return $this + */ + public function expiresAfter(mixed $time): static + { + if (null === $time) { + $this->expiry = null; + } elseif ($time instanceof \DateInterval) { + $this->expiry = microtime(true) + \DateTimeImmutable::createFromFormat('U', 0)->add($time)->format('U.u'); + } elseif (\is_int($time)) { + $this->expiry = $time + microtime(true); + } else { + throw new InvalidArgumentException(\sprintf('Expiration date must be an integer, a DateInterval or null, "%s" given.', get_debug_type($time))); + } + + return $this; + } + + public function tag(mixed $tags): static + { + if (!$this->isTaggable) { + throw new LogicException(\sprintf('Cache item "%s" comes from a non tag-aware pool: you cannot tag it.', $this->key)); + } + if (!\is_array($tags) && !$tags instanceof \Traversable) { // don't use is_iterable(), it's slow + $tags = [$tags]; + } + foreach ($tags as $tag) { + if (!\is_string($tag) && !$tag instanceof \Stringable) { + throw new InvalidArgumentException(\sprintf('Cache tag must be string or object that implements __toString(), "%s" given.', get_debug_type($tag))); + } + $tag = (string) $tag; + if (isset($this->newMetadata[self::METADATA_TAGS][$tag])) { + continue; + } + if ('' === $tag) { + throw new InvalidArgumentException('Cache tag length must be greater than zero.'); + } + if (false !== strpbrk($tag, self::RESERVED_CHARACTERS)) { + throw new InvalidArgumentException(\sprintf('Cache tag "%s" contains reserved characters "%s".', $tag, self::RESERVED_CHARACTERS)); + } + $this->newMetadata[self::METADATA_TAGS][$tag] = $tag; + } + + return $this; + } + + public function getMetadata(): array + { + return $this->metadata; + } + + /** + * Validates a cache key according to PSR-6. + * + * @param mixed $key The key to validate + * + * @throws InvalidArgumentException When $key is not valid + */ + public static function validateKey($key): string + { + if (!\is_string($key)) { + throw new InvalidArgumentException(\sprintf('Cache key must be string, "%s" given.', get_debug_type($key))); + } + if ('' === $key) { + throw new InvalidArgumentException('Cache key length must be greater than zero.'); + } + if (false !== strpbrk($key, self::RESERVED_CHARACTERS)) { + throw new InvalidArgumentException(\sprintf('Cache key "%s" contains reserved characters "%s".', $key, self::RESERVED_CHARACTERS)); + } + + return $key; + } + + /** + * Internal logging helper. + * + * @internal + */ + public static function log(?LoggerInterface $logger, string $message, array $context = []): void + { + if ($logger) { + $logger->warning($message, $context); + } else { + $replace = []; + foreach ($context as $k => $v) { + if (\is_scalar($v)) { + $replace['{'.$k.'}'] = $v; + } + } + @trigger_error(strtr($message, $replace), \E_USER_WARNING); + } + } + + private function pack(): mixed + { + if (!$m = $this->newMetadata) { + return $this->value; + } + $valueWrapper = self::VALUE_WRAPPER; + + return new $valueWrapper($this->value, $m + ['expiry' => $this->expiry]); + } + + private function unpack(): bool + { + $v = $this->value; + $valueWrapper = self::VALUE_WRAPPER; + + if ($v instanceof $valueWrapper) { + $this->value = $v->value; + $this->metadata = $v->metadata; + + return true; + } + + if (!\is_array($v) || 1 !== \count($v) || 10 !== \strlen($k = (string) array_key_first($v)) || "\x9D" !== $k[0] || "\0" !== $k[5] || "\x5F" !== $k[9]) { + return false; + } + + // BC with pools populated before v6.1 + $this->value = $v[$k]; + $this->metadata = unpack('Vexpiry/Nctime', substr($k, 1, -1)); + $this->metadata['expiry'] += self::METADATA_EXPIRY_OFFSET; + + return true; + } +} diff --git a/vendor/symfony/cache/DataCollector/CacheDataCollector.php b/vendor/symfony/cache/DataCollector/CacheDataCollector.php new file mode 100644 index 0000000..b9bcdaf --- /dev/null +++ b/vendor/symfony/cache/DataCollector/CacheDataCollector.php @@ -0,0 +1,184 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\DataCollector; + +use Symfony\Component\Cache\Adapter\TraceableAdapter; +use Symfony\Component\Cache\Adapter\TraceableAdapterEvent; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\DataCollector\DataCollector; +use Symfony\Component\HttpKernel\DataCollector\LateDataCollectorInterface; + +/** + * @author Aaron Scherer + * @author Tobias Nyholm + * + * @final + */ +class CacheDataCollector extends DataCollector implements LateDataCollectorInterface +{ + /** + * @var TraceableAdapter[] + */ + private array $instances = []; + + public function addInstance(string $name, TraceableAdapter $instance): void + { + $this->instances[$name] = $instance; + } + + public function collect(Request $request, Response $response, ?\Throwable $exception = null): void + { + $empty = ['calls' => [], 'adapters' => [], 'config' => [], 'options' => [], 'statistics' => []]; + $this->data = ['instances' => $empty, 'total' => $empty]; + foreach ($this->instances as $name => $instance) { + $this->data['instances']['calls'][$name] = $instance->getCalls(); + $this->data['instances']['adapters'][$name] = get_debug_type($instance->getPool()); + } + + $this->data['instances']['statistics'] = $this->calculateStatistics(); + $this->data['total']['statistics'] = $this->calculateTotalStatistics(); + } + + public function reset(): void + { + $this->data = []; + foreach ($this->instances as $instance) { + $instance->clearCalls(); + } + } + + public function lateCollect(): void + { + $this->data['instances']['calls'] = $this->cloneVar($this->data['instances']['calls']); + } + + public function getName(): string + { + return 'cache'; + } + + /** + * Method returns amount of logged Cache reads: "get" calls. + */ + public function getStatistics(): array + { + return $this->data['instances']['statistics']; + } + + /** + * Method returns the statistic totals. + */ + public function getTotals(): array + { + return $this->data['total']['statistics']; + } + + /** + * Method returns all logged Cache call objects. + */ + public function getCalls(): mixed + { + return $this->data['instances']['calls']; + } + + /** + * Method returns all logged Cache adapter classes. + */ + public function getAdapters(): array + { + return $this->data['instances']['adapters']; + } + + private function calculateStatistics(): array + { + $statistics = []; + foreach ($this->data['instances']['calls'] as $name => $calls) { + $statistics[$name] = [ + 'calls' => 0, + 'time' => 0, + 'reads' => 0, + 'writes' => 0, + 'deletes' => 0, + 'hits' => 0, + 'misses' => 0, + ]; + /** @var TraceableAdapterEvent $call */ + foreach ($calls as $call) { + ++$statistics[$name]['calls']; + $statistics[$name]['time'] += ($call->end ?? microtime(true)) - $call->start; + if ('get' === $call->name) { + ++$statistics[$name]['reads']; + if ($call->hits) { + ++$statistics[$name]['hits']; + } else { + ++$statistics[$name]['misses']; + ++$statistics[$name]['writes']; + } + } elseif ('getItem' === $call->name) { + ++$statistics[$name]['reads']; + if ($call->hits) { + ++$statistics[$name]['hits']; + } else { + ++$statistics[$name]['misses']; + } + } elseif ('getItems' === $call->name) { + $statistics[$name]['reads'] += $call->hits + $call->misses; + $statistics[$name]['hits'] += $call->hits; + $statistics[$name]['misses'] += $call->misses; + } elseif ('hasItem' === $call->name) { + ++$statistics[$name]['reads']; + foreach ($call->result ?? [] as $result) { + ++$statistics[$name][$result ? 'hits' : 'misses']; + } + } elseif ('save' === $call->name) { + ++$statistics[$name]['writes']; + } elseif ('deleteItem' === $call->name) { + ++$statistics[$name]['deletes']; + } + } + if ($statistics[$name]['reads']) { + $statistics[$name]['hit_read_ratio'] = round(100 * $statistics[$name]['hits'] / $statistics[$name]['reads'], 2); + } else { + $statistics[$name]['hit_read_ratio'] = null; + } + } + + return $statistics; + } + + private function calculateTotalStatistics(): array + { + $statistics = $this->getStatistics(); + $totals = [ + 'calls' => 0, + 'time' => 0, + 'reads' => 0, + 'writes' => 0, + 'deletes' => 0, + 'hits' => 0, + 'misses' => 0, + ]; + foreach ($statistics as $name => $values) { + foreach ($totals as $key => $value) { + $totals[$key] += $statistics[$name][$key]; + } + } + if ($totals['reads']) { + $totals['hit_read_ratio'] = round(100 * $totals['hits'] / $totals['reads'], 2); + } else { + $totals['hit_read_ratio'] = null; + } + + return $totals; + } +} diff --git a/vendor/symfony/cache/DependencyInjection/CacheCollectorPass.php b/vendor/symfony/cache/DependencyInjection/CacheCollectorPass.php new file mode 100644 index 0000000..ed95740 --- /dev/null +++ b/vendor/symfony/cache/DependencyInjection/CacheCollectorPass.php @@ -0,0 +1,75 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\DependencyInjection; + +use Symfony\Component\Cache\Adapter\TagAwareAdapterInterface; +use Symfony\Component\Cache\Adapter\TraceableAdapter; +use Symfony\Component\Cache\Adapter\TraceableTagAwareAdapter; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Inject a data collector to all the cache services to be able to get detailed statistics. + * + * @author Tobias Nyholm + */ +class CacheCollectorPass implements CompilerPassInterface +{ + public function process(ContainerBuilder $container): void + { + if (!$container->hasDefinition('data_collector.cache')) { + return; + } + + foreach ($container->findTaggedServiceIds('cache.pool') as $id => $attributes) { + $poolName = $attributes[0]['name'] ?? $id; + + $this->addToCollector($id, $poolName, $container); + } + } + + private function addToCollector(string $id, string $name, ContainerBuilder $container): void + { + $definition = $container->getDefinition($id); + if ($definition->isAbstract()) { + return; + } + + $collectorDefinition = $container->getDefinition('data_collector.cache'); + $recorder = new Definition(is_subclass_of($definition->getClass(), TagAwareAdapterInterface::class) ? TraceableTagAwareAdapter::class : TraceableAdapter::class); + $recorder->setTags($definition->getTags()); + if (!$definition->isPublic() || !$definition->isPrivate()) { + $recorder->setPublic($definition->isPublic()); + } + $recorder->setArguments([new Reference($innerId = $id.'.recorder_inner')]); + + foreach ($definition->getMethodCalls() as [$method, $args]) { + if ('setCallbackWrapper' !== $method || !$args[0] instanceof Definition || !($args[0]->getArguments()[2] ?? null) instanceof Definition) { + continue; + } + if ([new Reference($id), 'setCallbackWrapper'] == $args[0]->getArguments()[2]->getFactory()) { + $args[0]->getArguments()[2]->setFactory([new Reference($innerId), 'setCallbackWrapper']); + } + } + + $definition->setTags([]); + $definition->setPublic(false); + + $container->setDefinition($innerId, $definition); + $container->setDefinition($id, $recorder); + + // Tell the collector to add the new instance + $collectorDefinition->addMethodCall('addInstance', [$name, new Reference($id)]); + } +} diff --git a/vendor/symfony/cache/DependencyInjection/CachePoolClearerPass.php b/vendor/symfony/cache/DependencyInjection/CachePoolClearerPass.php new file mode 100644 index 0000000..5449720 --- /dev/null +++ b/vendor/symfony/cache/DependencyInjection/CachePoolClearerPass.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\DependencyInjection; + +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; + +/** + * @author Nicolas Grekas + */ +class CachePoolClearerPass implements CompilerPassInterface +{ + public function process(ContainerBuilder $container): void + { + $container->getParameterBag()->remove('cache.prefix.seed'); + + foreach ($container->findTaggedServiceIds('cache.pool.clearer') as $id => $attr) { + $clearer = $container->getDefinition($id); + $pools = []; + foreach ($clearer->getArgument(0) as $name => $ref) { + if ($container->hasDefinition($ref)) { + $pools[$name] = new Reference($ref); + } + } + $clearer->replaceArgument(0, $pools); + } + } +} diff --git a/vendor/symfony/cache/DependencyInjection/CachePoolPass.php b/vendor/symfony/cache/DependencyInjection/CachePoolPass.php new file mode 100644 index 0000000..e62febb --- /dev/null +++ b/vendor/symfony/cache/DependencyInjection/CachePoolPass.php @@ -0,0 +1,243 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\DependencyInjection; + +use Symfony\Component\Cache\Adapter\AbstractAdapter; +use Symfony\Component\Cache\Adapter\ArrayAdapter; +use Symfony\Component\Cache\Adapter\ChainAdapter; +use Symfony\Component\Cache\Adapter\NullAdapter; +use Symfony\Component\Cache\Adapter\ParameterNormalizer; +use Symfony\Component\Cache\Messenger\EarlyExpirationDispatcher; +use Symfony\Component\DependencyInjection\ChildDefinition; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use Symfony\Component\DependencyInjection\Reference; + +/** + * @author Nicolas Grekas + */ +class CachePoolPass implements CompilerPassInterface +{ + public function process(ContainerBuilder $container): void + { + if ($container->hasParameter('cache.prefix.seed')) { + $seed = $container->getParameterBag()->resolveValue($container->getParameter('cache.prefix.seed')); + } else { + $seed = '_'.$container->getParameter('kernel.project_dir'); + $seed .= '.'.$container->getParameter('kernel.container_class'); + } + + $needsMessageHandler = false; + $allPools = []; + $clearers = []; + $attributes = [ + 'provider', + 'name', + 'namespace', + 'default_lifetime', + 'early_expiration_message_bus', + 'reset', + ]; + foreach ($container->findTaggedServiceIds('cache.pool') as $id => $tags) { + $adapter = $pool = $container->getDefinition($id); + if ($pool->isAbstract()) { + continue; + } + $class = $adapter->getClass(); + while ($adapter instanceof ChildDefinition) { + $adapter = $container->findDefinition($adapter->getParent()); + $class = $class ?: $adapter->getClass(); + if ($t = $adapter->getTag('cache.pool')) { + $tags[0] += $t[0]; + } + } + $name = $tags[0]['name'] ?? $id; + if (!isset($tags[0]['namespace'])) { + $namespaceSeed = $seed; + if (null !== $class) { + $namespaceSeed .= '.'.$class; + } + + $tags[0]['namespace'] = $this->getNamespace($namespaceSeed, $name); + } + if (isset($tags[0]['clearer'])) { + $clearer = $tags[0]['clearer']; + while ($container->hasAlias($clearer)) { + $clearer = (string) $container->getAlias($clearer); + } + } else { + $clearer = null; + } + unset($tags[0]['clearer'], $tags[0]['name']); + + if (isset($tags[0]['provider'])) { + $tags[0]['provider'] = new Reference(static::getServiceProvider($container, $tags[0]['provider'])); + } + + if (ChainAdapter::class === $class) { + $adapters = []; + foreach ($adapter->getArgument(0) as $provider => $adapter) { + if ($adapter instanceof ChildDefinition) { + $chainedPool = $adapter; + } else { + $chainedPool = $adapter = new ChildDefinition($adapter); + } + + $chainedTags = [\is_int($provider) ? [] : ['provider' => $provider]]; + $chainedClass = ''; + + while ($adapter instanceof ChildDefinition) { + $adapter = $container->findDefinition($adapter->getParent()); + $chainedClass = $chainedClass ?: $adapter->getClass(); + if ($t = $adapter->getTag('cache.pool')) { + $chainedTags[0] += $t[0]; + } + } + + if (ChainAdapter::class === $chainedClass) { + throw new InvalidArgumentException(\sprintf('Invalid service "%s": chain of adapters cannot reference another chain, found "%s".', $id, $chainedPool->getParent())); + } + + $i = 0; + + if (isset($chainedTags[0]['provider'])) { + $chainedPool->replaceArgument($i++, new Reference(static::getServiceProvider($container, $chainedTags[0]['provider']))); + } + + if (isset($tags[0]['namespace']) && !\in_array($adapter->getClass(), [ArrayAdapter::class, NullAdapter::class], true)) { + $chainedPool->replaceArgument($i++, $tags[0]['namespace']); + } + + if (isset($tags[0]['default_lifetime'])) { + $chainedPool->replaceArgument($i++, $tags[0]['default_lifetime']); + } + + $adapters[] = $chainedPool; + } + + $pool->replaceArgument(0, $adapters); + unset($tags[0]['provider'], $tags[0]['namespace']); + $i = 1; + } else { + $i = 0; + } + + foreach ($attributes as $attr) { + if (!isset($tags[0][$attr])) { + // no-op + } elseif ('reset' === $attr) { + if ($tags[0][$attr]) { + $pool->addTag('kernel.reset', ['method' => $tags[0][$attr]]); + } + } elseif ('early_expiration_message_bus' === $attr) { + $needsMessageHandler = true; + $pool->addMethodCall('setCallbackWrapper', [(new Definition(EarlyExpirationDispatcher::class)) + ->addArgument(new Reference($tags[0]['early_expiration_message_bus'])) + ->addArgument(new Reference('reverse_container')) + ->addArgument((new Definition('callable')) + ->setFactory([new Reference($id), 'setCallbackWrapper']) + ->addArgument(null) + ), + ]); + $pool->addTag('container.reversible'); + } elseif ('namespace' !== $attr || !\in_array($class, [ArrayAdapter::class, NullAdapter::class], true)) { + $argument = $tags[0][$attr]; + + if ('default_lifetime' === $attr && !is_numeric($argument)) { + $argument = (new Definition('int', [$argument])) + ->setFactory([ParameterNormalizer::class, 'normalizeDuration']); + } + + $pool->replaceArgument($i++, $argument); + } + unset($tags[0][$attr]); + } + if (!empty($tags[0])) { + throw new InvalidArgumentException(\sprintf('Invalid "cache.pool" tag for service "%s": accepted attributes are "clearer", "provider", "name", "namespace", "default_lifetime", "early_expiration_message_bus" and "reset", found "%s".', $id, implode('", "', array_keys($tags[0])))); + } + + if (null !== $clearer) { + $clearers[$clearer][$name] = new Reference($id, $container::IGNORE_ON_UNINITIALIZED_REFERENCE); + } + + $allPools[$name] = new Reference($id, $container::IGNORE_ON_UNINITIALIZED_REFERENCE); + } + + if (!$needsMessageHandler) { + $container->removeDefinition('cache.early_expiration_handler'); + } + + $notAliasedCacheClearerId = 'cache.global_clearer'; + while ($container->hasAlias($notAliasedCacheClearerId)) { + $notAliasedCacheClearerId = (string) $container->getAlias($notAliasedCacheClearerId); + } + if ($container->hasDefinition($notAliasedCacheClearerId)) { + $clearers[$notAliasedCacheClearerId] = $allPools; + } + + foreach ($clearers as $id => $pools) { + $clearer = $container->getDefinition($id); + if ($clearer instanceof ChildDefinition) { + $clearer->replaceArgument(0, $pools); + } else { + $clearer->setArgument(0, $pools); + } + $clearer->addTag('cache.pool.clearer'); + + if ('cache.system_clearer' === $id) { + $clearer->addTag('kernel.cache_clearer'); + } + } + + $allPoolsKeys = array_keys($allPools); + + if ($container->hasDefinition('console.command.cache_pool_list')) { + $container->getDefinition('console.command.cache_pool_list')->replaceArgument(0, $allPoolsKeys); + } + + if ($container->hasDefinition('console.command.cache_pool_clear')) { + $container->getDefinition('console.command.cache_pool_clear')->addArgument($allPoolsKeys); + } + + if ($container->hasDefinition('console.command.cache_pool_delete')) { + $container->getDefinition('console.command.cache_pool_delete')->addArgument($allPoolsKeys); + } + } + + private function getNamespace(string $seed, string $id): string + { + return substr(str_replace('/', '-', base64_encode(hash('xxh128', $id.$seed, true))), 0, 10); + } + + /** + * @internal + */ + public static function getServiceProvider(ContainerBuilder $container, string $name): string + { + $container->resolveEnvPlaceholders($name, null, $usedEnvs); + + if ($usedEnvs || preg_match('#^[a-z]++:#', $name)) { + $dsn = $name; + + if (!$container->hasDefinition($name = '.cache_connection.'.ContainerBuilder::hash($dsn))) { + $definition = new Definition(AbstractAdapter::class); + $definition->setFactory([AbstractAdapter::class, 'createConnection']); + $definition->setArguments([$dsn, ['lazy' => true]]); + $container->setDefinition($name, $definition); + } + } + + return $name; + } +} diff --git a/vendor/symfony/cache/DependencyInjection/CachePoolPrunerPass.php b/vendor/symfony/cache/DependencyInjection/CachePoolPrunerPass.php new file mode 100644 index 0000000..68386f5 --- /dev/null +++ b/vendor/symfony/cache/DependencyInjection/CachePoolPrunerPass.php @@ -0,0 +1,48 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\DependencyInjection; + +use Symfony\Component\Cache\PruneableInterface; +use Symfony\Component\DependencyInjection\Argument\IteratorArgument; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use Symfony\Component\DependencyInjection\Reference; + +/** + * @author Rob Frawley 2nd + */ +class CachePoolPrunerPass implements CompilerPassInterface +{ + public function process(ContainerBuilder $container): void + { + if (!$container->hasDefinition('console.command.cache_pool_prune')) { + return; + } + + $services = []; + + foreach ($container->findTaggedServiceIds('cache.pool') as $id => $tags) { + $class = $container->getParameterBag()->resolveValue($container->getDefinition($id)->getClass()); + + if (!$reflection = $container->getReflectionClass($class)) { + throw new InvalidArgumentException(\sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id)); + } + + if ($reflection->implementsInterface(PruneableInterface::class)) { + $services[$id] = new Reference($id); + } + } + + $container->getDefinition('console.command.cache_pool_prune')->replaceArgument(0, new IteratorArgument($services)); + } +} diff --git a/vendor/symfony/cache/Exception/CacheException.php b/vendor/symfony/cache/Exception/CacheException.php new file mode 100644 index 0000000..d2e975b --- /dev/null +++ b/vendor/symfony/cache/Exception/CacheException.php @@ -0,0 +1,25 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Exception; + +use Psr\Cache\CacheException as Psr6CacheInterface; +use Psr\SimpleCache\CacheException as SimpleCacheInterface; + +if (interface_exists(SimpleCacheInterface::class)) { + class CacheException extends \Exception implements Psr6CacheInterface, SimpleCacheInterface + { + } +} else { + class CacheException extends \Exception implements Psr6CacheInterface + { + } +} diff --git a/vendor/symfony/cache/Exception/InvalidArgumentException.php b/vendor/symfony/cache/Exception/InvalidArgumentException.php new file mode 100644 index 0000000..7f9584a --- /dev/null +++ b/vendor/symfony/cache/Exception/InvalidArgumentException.php @@ -0,0 +1,25 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Exception; + +use Psr\Cache\InvalidArgumentException as Psr6CacheInterface; +use Psr\SimpleCache\InvalidArgumentException as SimpleCacheInterface; + +if (interface_exists(SimpleCacheInterface::class)) { + class InvalidArgumentException extends \InvalidArgumentException implements Psr6CacheInterface, SimpleCacheInterface + { + } +} else { + class InvalidArgumentException extends \InvalidArgumentException implements Psr6CacheInterface + { + } +} diff --git a/vendor/symfony/cache/Exception/LogicException.php b/vendor/symfony/cache/Exception/LogicException.php new file mode 100644 index 0000000..9ffa7ed --- /dev/null +++ b/vendor/symfony/cache/Exception/LogicException.php @@ -0,0 +1,25 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Exception; + +use Psr\Cache\CacheException as Psr6CacheInterface; +use Psr\SimpleCache\CacheException as SimpleCacheInterface; + +if (interface_exists(SimpleCacheInterface::class)) { + class LogicException extends \LogicException implements Psr6CacheInterface, SimpleCacheInterface + { + } +} else { + class LogicException extends \LogicException implements Psr6CacheInterface + { + } +} diff --git a/vendor/symfony/cache/LICENSE b/vendor/symfony/cache/LICENSE new file mode 100644 index 0000000..0223acd --- /dev/null +++ b/vendor/symfony/cache/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2016-present Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/symfony/cache/LockRegistry.php b/vendor/symfony/cache/LockRegistry.php new file mode 100644 index 0000000..6923b40 --- /dev/null +++ b/vendor/symfony/cache/LockRegistry.php @@ -0,0 +1,166 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache; + +use Psr\Log\LoggerInterface; +use Symfony\Contracts\Cache\CacheInterface; +use Symfony\Contracts\Cache\ItemInterface; + +/** + * LockRegistry is used internally by existing adapters to protect against cache stampede. + * + * It does so by wrapping the computation of items in a pool of locks. + * Foreach each apps, there can be at most 20 concurrent processes that + * compute items at the same time and only one per cache-key. + * + * @author Nicolas Grekas + */ +final class LockRegistry +{ + private static array $openedFiles = []; + private static ?array $lockedFiles = null; + private static \Exception $signalingException; + private static \Closure $signalingCallback; + + /** + * The number of items in this list controls the max number of concurrent processes. + */ + private static array $files = [ + __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'AbstractAdapter.php', + __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'AbstractTagAwareAdapter.php', + __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'AdapterInterface.php', + __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'ApcuAdapter.php', + __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'ArrayAdapter.php', + __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'ChainAdapter.php', + __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'CouchbaseBucketAdapter.php', + __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'CouchbaseCollectionAdapter.php', + __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'DoctrineDbalAdapter.php', + __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'FilesystemAdapter.php', + __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'FilesystemTagAwareAdapter.php', + __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'MemcachedAdapter.php', + __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'NullAdapter.php', + __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'ParameterNormalizer.php', + __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'PdoAdapter.php', + __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'PhpArrayAdapter.php', + __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'PhpFilesAdapter.php', + __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'ProxyAdapter.php', + __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'Psr16Adapter.php', + __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'RedisAdapter.php', + __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'RedisTagAwareAdapter.php', + __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'TagAwareAdapter.php', + __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'TagAwareAdapterInterface.php', + __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'TraceableAdapter.php', + __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'TraceableTagAwareAdapter.php', + ]; + + /** + * Defines a set of existing files that will be used as keys to acquire locks. + * + * @return array The previously defined set of files + */ + public static function setFiles(array $files): array + { + $previousFiles = self::$files; + self::$files = $files; + + foreach (self::$openedFiles as $file) { + if ($file) { + flock($file, \LOCK_UN); + fclose($file); + } + } + self::$openedFiles = self::$lockedFiles = []; + + return $previousFiles; + } + + public static function compute(callable $callback, ItemInterface $item, bool &$save, CacheInterface $pool, ?\Closure $setMetadata = null, ?LoggerInterface $logger = null): mixed + { + if ('\\' === \DIRECTORY_SEPARATOR && null === self::$lockedFiles) { + // disable locking on Windows by default + self::$files = self::$lockedFiles = []; + } + + $key = self::$files ? abs(crc32($item->getKey())) % \count(self::$files) : -1; + + if ($key < 0 || self::$lockedFiles || !$lock = self::open($key)) { + return $callback($item, $save); + } + + self::$signalingException ??= unserialize("O:9:\"Exception\":1:{s:16:\"\0Exception\0trace\";a:0:{}}"); + self::$signalingCallback ??= fn () => throw self::$signalingException; + + while (true) { + try { + // race to get the lock in non-blocking mode + $locked = flock($lock, \LOCK_EX | \LOCK_NB, $wouldBlock); + + if ($locked || !$wouldBlock) { + $logger?->info(\sprintf('Lock %s, now computing item "{key}"', $locked ? 'acquired' : 'not supported'), ['key' => $item->getKey()]); + self::$lockedFiles[$key] = true; + + $value = $callback($item, $save); + + if ($save) { + if ($setMetadata) { + $setMetadata($item); + } + + $pool->save($item->set($value)); + $save = false; + } + + return $value; + } + // if we failed the race, retry locking in blocking mode to wait for the winner + $logger?->info('Item "{key}" is locked, waiting for it to be released', ['key' => $item->getKey()]); + flock($lock, \LOCK_SH); + } finally { + flock($lock, \LOCK_UN); + unset(self::$lockedFiles[$key]); + } + + try { + $value = $pool->get($item->getKey(), self::$signalingCallback, 0); + $logger?->info('Item "{key}" retrieved after lock was released', ['key' => $item->getKey()]); + $save = false; + + return $value; + } catch (\Exception $e) { + if (self::$signalingException !== $e) { + throw $e; + } + $logger?->info('Item "{key}" not found while lock was released, now retrying', ['key' => $item->getKey()]); + } + } + + return null; + } + + /** + * @return resource|false + */ + private static function open(int $key) + { + if (null !== $h = self::$openedFiles[$key] ?? null) { + return $h; + } + set_error_handler(static fn () => null); + try { + $h = fopen(self::$files[$key], 'r+'); + } finally { + restore_error_handler(); + } + + return self::$openedFiles[$key] = $h ?: @fopen(self::$files[$key], 'r'); + } +} diff --git a/vendor/symfony/cache/Marshaller/DefaultMarshaller.php b/vendor/symfony/cache/Marshaller/DefaultMarshaller.php new file mode 100644 index 0000000..02ebcfa --- /dev/null +++ b/vendor/symfony/cache/Marshaller/DefaultMarshaller.php @@ -0,0 +1,96 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Marshaller; + +use Symfony\Component\Cache\Exception\CacheException; + +/** + * Serializes/unserializes values using igbinary_serialize() if available, serialize() otherwise. + * + * @author Nicolas Grekas + */ +class DefaultMarshaller implements MarshallerInterface +{ + private bool $useIgbinarySerialize = false; + private bool $throwOnSerializationFailure = false; + + public function __construct(?bool $useIgbinarySerialize = null, bool $throwOnSerializationFailure = false) + { + if ($useIgbinarySerialize && (!\extension_loaded('igbinary') || version_compare('3.1.6', phpversion('igbinary'), '>'))) { + throw new CacheException(\extension_loaded('igbinary') ? 'Please upgrade the "igbinary" PHP extension to v3.1.6 or higher.' : 'The "igbinary" PHP extension is not loaded.'); + } + $this->useIgbinarySerialize = true === $useIgbinarySerialize; + $this->throwOnSerializationFailure = $throwOnSerializationFailure; + } + + public function marshall(array $values, ?array &$failed): array + { + $serialized = $failed = []; + + foreach ($values as $id => $value) { + try { + if ($this->useIgbinarySerialize) { + $serialized[$id] = igbinary_serialize($value); + } else { + $serialized[$id] = serialize($value); + } + } catch (\Exception $e) { + if ($this->throwOnSerializationFailure) { + throw new \ValueError($e->getMessage(), 0, $e); + } + $failed[] = $id; + } + } + + return $serialized; + } + + public function unmarshall(string $value): mixed + { + if ('b:0;' === $value) { + return false; + } + if ('N;' === $value) { + return null; + } + static $igbinaryNull; + if ($value === $igbinaryNull ??= \extension_loaded('igbinary') ? igbinary_serialize(null) : false) { + return null; + } + $unserializeCallbackHandler = ini_set('unserialize_callback_func', __CLASS__.'::handleUnserializeCallback'); + try { + if (':' === ($value[1] ?? ':')) { + if (false !== $value = unserialize($value)) { + return $value; + } + } elseif (false === $igbinaryNull) { + throw new \RuntimeException('Failed to unserialize values, did you forget to install the "igbinary" extension?'); + } elseif (null !== $value = igbinary_unserialize($value)) { + return $value; + } + + throw new \DomainException(error_get_last() ? error_get_last()['message'] : 'Failed to unserialize values.'); + } catch (\Error $e) { + throw new \ErrorException($e->getMessage(), $e->getCode(), \E_ERROR, $e->getFile(), $e->getLine()); + } finally { + ini_set('unserialize_callback_func', $unserializeCallbackHandler); + } + } + + /** + * @internal + */ + public static function handleUnserializeCallback(string $class): never + { + throw new \DomainException('Class not found: '.$class); + } +} diff --git a/vendor/symfony/cache/Marshaller/DeflateMarshaller.php b/vendor/symfony/cache/Marshaller/DeflateMarshaller.php new file mode 100644 index 0000000..f35241c --- /dev/null +++ b/vendor/symfony/cache/Marshaller/DeflateMarshaller.php @@ -0,0 +1,44 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Marshaller; + +use Symfony\Component\Cache\Exception\CacheException; + +/** + * Compresses values using gzdeflate(). + * + * @author Nicolas Grekas + */ +class DeflateMarshaller implements MarshallerInterface +{ + public function __construct( + private MarshallerInterface $marshaller, + ) { + if (!\function_exists('gzdeflate')) { + throw new CacheException('The "zlib" PHP extension is not loaded.'); + } + } + + public function marshall(array $values, ?array &$failed): array + { + return array_map('gzdeflate', $this->marshaller->marshall($values, $failed)); + } + + public function unmarshall(string $value): mixed + { + if (false !== $inflatedValue = @gzinflate($value)) { + $value = $inflatedValue; + } + + return $this->marshaller->unmarshall($value); + } +} diff --git a/vendor/symfony/cache/Marshaller/MarshallerInterface.php b/vendor/symfony/cache/Marshaller/MarshallerInterface.php new file mode 100644 index 0000000..5b81aad --- /dev/null +++ b/vendor/symfony/cache/Marshaller/MarshallerInterface.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Marshaller; + +/** + * Serializes/unserializes PHP values. + * + * Implementations of this interface MUST deal with errors carefully. They MUST + * also deal with forward and backward compatibility at the storage format level. + * + * @author Nicolas Grekas + */ +interface MarshallerInterface +{ + /** + * Serializes a list of values. + * + * When serialization fails for a specific value, no exception should be + * thrown. Instead, its key should be listed in $failed. + */ + public function marshall(array $values, ?array &$failed): array; + + /** + * Unserializes a single value and throws an exception if anything goes wrong. + * + * @throws \Exception Whenever unserialization fails + */ + public function unmarshall(string $value): mixed; +} diff --git a/vendor/symfony/cache/Marshaller/SodiumMarshaller.php b/vendor/symfony/cache/Marshaller/SodiumMarshaller.php new file mode 100644 index 0000000..77d16e8 --- /dev/null +++ b/vendor/symfony/cache/Marshaller/SodiumMarshaller.php @@ -0,0 +1,74 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Marshaller; + +use Symfony\Component\Cache\Exception\CacheException; +use Symfony\Component\Cache\Exception\InvalidArgumentException; + +/** + * Encrypt/decrypt values using Libsodium. + * + * @author Ahmed TAILOULOUTE + */ +class SodiumMarshaller implements MarshallerInterface +{ + private MarshallerInterface $marshaller; + + /** + * @param string[] $decryptionKeys The key at index "0" is required and is used to decrypt and encrypt values; + * more rotating keys can be provided to decrypt values; + * each key must be generated using sodium_crypto_box_keypair() + */ + public function __construct( + private array $decryptionKeys, + ?MarshallerInterface $marshaller = null, + ) { + if (!self::isSupported()) { + throw new CacheException('The "sodium" PHP extension is not loaded.'); + } + + if (!isset($decryptionKeys[0])) { + throw new InvalidArgumentException('At least one decryption key must be provided at index "0".'); + } + + $this->marshaller = $marshaller ?? new DefaultMarshaller(); + } + + public static function isSupported(): bool + { + return \function_exists('sodium_crypto_box_seal'); + } + + public function marshall(array $values, ?array &$failed): array + { + $encryptionKey = sodium_crypto_box_publickey($this->decryptionKeys[0]); + + $encryptedValues = []; + foreach ($this->marshaller->marshall($values, $failed) as $k => $v) { + $encryptedValues[$k] = sodium_crypto_box_seal($v, $encryptionKey); + } + + return $encryptedValues; + } + + public function unmarshall(string $value): mixed + { + foreach ($this->decryptionKeys as $k) { + if (false !== $decryptedValue = @sodium_crypto_box_seal_open($value, $k)) { + $value = $decryptedValue; + break; + } + } + + return $this->marshaller->unmarshall($value); + } +} diff --git a/vendor/symfony/cache/Marshaller/TagAwareMarshaller.php b/vendor/symfony/cache/Marshaller/TagAwareMarshaller.php new file mode 100644 index 0000000..825f32c --- /dev/null +++ b/vendor/symfony/cache/Marshaller/TagAwareMarshaller.php @@ -0,0 +1,83 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Marshaller; + +/** + * A marshaller optimized for data structures generated by AbstractTagAwareAdapter. + * + * @author Nicolas Grekas + */ +class TagAwareMarshaller implements MarshallerInterface +{ + private MarshallerInterface $marshaller; + + public function __construct(?MarshallerInterface $marshaller = null) + { + $this->marshaller = $marshaller ?? new DefaultMarshaller(); + } + + public function marshall(array $values, ?array &$failed): array + { + $failed = $notSerialized = $serialized = []; + + foreach ($values as $id => $value) { + if (\is_array($value) && \is_array($value['tags'] ?? null) && \array_key_exists('value', $value) && \count($value) === 2 + (\is_string($value['meta'] ?? null) && 8 === \strlen($value['meta']))) { + // if the value is an array with keys "tags", "value" and "meta", use a compact serialization format + // magic numbers in the form 9D-..-..-..-..-00-..-..-..-5F allow detecting this format quickly in unmarshall() + + $v = $this->marshaller->marshall($value, $f); + + if ($f) { + $f = []; + $failed[] = $id; + } else { + if ([] === $value['tags']) { + $v['tags'] = ''; + } + + $serialized[$id] = "\x9D".($value['meta'] ?? "\0\0\0\0\0\0\0\0").pack('N', \strlen($v['tags'])).$v['tags'].$v['value']; + $serialized[$id][9] = "\x5F"; + } + } else { + // other arbitrary values are serialized using the decorated marshaller below + $notSerialized[$id] = $value; + } + } + + if ($notSerialized) { + $serialized += $this->marshaller->marshall($notSerialized, $f); + $failed = array_merge($failed, $f); + } + + return $serialized; + } + + public function unmarshall(string $value): mixed + { + // detect the compact format used in marshall() using magic numbers in the form 9D-..-..-..-..-00-..-..-..-5F + if (13 >= \strlen($value) || "\x9D" !== $value[0] || "\0" !== $value[5] || "\x5F" !== $value[9]) { + return $this->marshaller->unmarshall($value); + } + + // data consists of value, tags and metadata which we need to unpack + $meta = substr($value, 1, 12); + $meta[8] = "\0"; + $tagLen = unpack('Nlen', $meta, 8)['len']; + $meta = substr($meta, 0, 8); + + return [ + 'value' => $this->marshaller->unmarshall(substr($value, 13 + $tagLen)), + 'tags' => $tagLen ? $this->marshaller->unmarshall(substr($value, 13, $tagLen)) : [], + 'meta' => "\0\0\0\0\0\0\0\0" === $meta ? null : $meta, + ]; + } +} diff --git a/vendor/symfony/cache/Messenger/EarlyExpirationDispatcher.php b/vendor/symfony/cache/Messenger/EarlyExpirationDispatcher.php new file mode 100644 index 0000000..d972634 --- /dev/null +++ b/vendor/symfony/cache/Messenger/EarlyExpirationDispatcher.php @@ -0,0 +1,60 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Messenger; + +use Psr\Log\LoggerInterface; +use Symfony\Component\Cache\Adapter\AdapterInterface; +use Symfony\Component\Cache\CacheItem; +use Symfony\Component\DependencyInjection\ReverseContainer; +use Symfony\Component\Messenger\MessageBusInterface; +use Symfony\Component\Messenger\Stamp\HandledStamp; + +/** + * Sends the computation of cached values to a message bus. + */ +class EarlyExpirationDispatcher +{ + private ?\Closure $callbackWrapper; + + public function __construct( + private MessageBusInterface $bus, + private ReverseContainer $reverseContainer, + ?callable $callbackWrapper = null, + ) { + $this->callbackWrapper = null === $callbackWrapper ? null : $callbackWrapper(...); + } + + public function __invoke(callable $callback, CacheItem $item, bool &$save, AdapterInterface $pool, \Closure $setMetadata, ?LoggerInterface $logger = null): mixed + { + if (!$item->isHit() || null === $message = EarlyExpirationMessage::create($this->reverseContainer, $callback, $item, $pool)) { + // The item is stale or the callback cannot be reversed: we must compute the value now + $logger?->info('Computing item "{key}" online: '.($item->isHit() ? 'callback cannot be reversed' : 'item is stale'), ['key' => $item->getKey()]); + + return null !== $this->callbackWrapper ? ($this->callbackWrapper)($callback, $item, $save, $pool, $setMetadata, $logger) : $callback($item, $save); + } + + $envelope = $this->bus->dispatch($message); + + if ($logger) { + if ($envelope->last(HandledStamp::class)) { + $logger->info('Item "{key}" was computed online', ['key' => $item->getKey()]); + } else { + $logger->info('Item "{key}" sent for recomputation', ['key' => $item->getKey()]); + } + } + + // The item's value is not stale, no need to write it to the backend + $save = false; + + return $message->getItem()->get() ?? $item->get(); + } +} diff --git a/vendor/symfony/cache/Messenger/EarlyExpirationHandler.php b/vendor/symfony/cache/Messenger/EarlyExpirationHandler.php new file mode 100644 index 0000000..adaeb5b --- /dev/null +++ b/vendor/symfony/cache/Messenger/EarlyExpirationHandler.php @@ -0,0 +1,81 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Messenger; + +use Symfony\Component\Cache\CacheItem; +use Symfony\Component\DependencyInjection\ReverseContainer; +use Symfony\Component\Messenger\Attribute\AsMessageHandler; + +/** + * Computes cached values sent to a message bus. + */ +#[AsMessageHandler] +class EarlyExpirationHandler +{ + private array $processedNonces = []; + + public function __construct( + private ReverseContainer $reverseContainer, + ) { + } + + public function __invoke(EarlyExpirationMessage $message): void + { + $item = $message->getItem(); + $metadata = $item->getMetadata(); + $expiry = $metadata[CacheItem::METADATA_EXPIRY] ?? 0; + $ctime = $metadata[CacheItem::METADATA_CTIME] ?? 0; + + if ($expiry && $ctime) { + // skip duplicate or expired messages + + $processingNonce = [$expiry, $ctime]; + $pool = $message->getPool(); + $key = $item->getKey(); + + if (($this->processedNonces[$pool][$key] ?? null) === $processingNonce) { + return; + } + + if (microtime(true) >= $expiry) { + return; + } + + $this->processedNonces[$pool] = [$key => $processingNonce] + ($this->processedNonces[$pool] ?? []); + + if (\count($this->processedNonces[$pool]) > 100) { + array_pop($this->processedNonces[$pool]); + } + } + + static $setMetadata; + + $setMetadata ??= \Closure::bind( + function (CacheItem $item, float $startTime) { + if ($item->expiry > $endTime = microtime(true)) { + $item->newMetadata[CacheItem::METADATA_EXPIRY] = $item->expiry; + $item->newMetadata[CacheItem::METADATA_CTIME] = (int) ceil(1000 * ($endTime - $startTime)); + } + }, + null, + CacheItem::class + ); + + $startTime = microtime(true); + $pool = $message->findPool($this->reverseContainer); + $callback = $message->findCallback($this->reverseContainer); + $save = true; + $value = $callback($item, $save); + $setMetadata($item, $startTime); + $pool->save($item->set($value)); + } +} diff --git a/vendor/symfony/cache/Messenger/EarlyExpirationMessage.php b/vendor/symfony/cache/Messenger/EarlyExpirationMessage.php new file mode 100644 index 0000000..de8256b --- /dev/null +++ b/vendor/symfony/cache/Messenger/EarlyExpirationMessage.php @@ -0,0 +1,96 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Messenger; + +use Symfony\Component\Cache\Adapter\AdapterInterface; +use Symfony\Component\Cache\CacheItem; +use Symfony\Component\DependencyInjection\ReverseContainer; + +/** + * Conveys a cached value that needs to be computed. + */ +final class EarlyExpirationMessage +{ + public static function create(ReverseContainer $reverseContainer, callable $callback, CacheItem $item, AdapterInterface $pool): ?self + { + try { + $item = clone $item; + $item->set(null); + } catch (\Exception) { + return null; + } + + $pool = $reverseContainer->getId($pool); + + if (\is_object($callback)) { + if (null === $id = $reverseContainer->getId($callback)) { + return null; + } + + $callback = '@'.$id; + } elseif (!\is_array($callback)) { + $callback = (string) $callback; + } elseif (!\is_object($callback[0])) { + $callback = [(string) $callback[0], (string) $callback[1]]; + } else { + if (null === $id = $reverseContainer->getId($callback[0])) { + return null; + } + + $callback = ['@'.$id, (string) $callback[1]]; + } + + return new self($item, $pool, $callback); + } + + public function getItem(): CacheItem + { + return $this->item; + } + + public function getPool(): string + { + return $this->pool; + } + + /** + * @return string|string[] + */ + public function getCallback(): string|array + { + return $this->callback; + } + + public function findPool(ReverseContainer $reverseContainer): AdapterInterface + { + return $reverseContainer->getService($this->pool); + } + + public function findCallback(ReverseContainer $reverseContainer): callable + { + if (\is_string($callback = $this->callback)) { + return '@' === $callback[0] ? $reverseContainer->getService(substr($callback, 1)) : $callback; + } + if ('@' === $callback[0][0]) { + $callback[0] = $reverseContainer->getService(substr($callback[0], 1)); + } + + return $callback; + } + + private function __construct( + private CacheItem $item, + private string $pool, + private string|array $callback, + ) { + } +} diff --git a/vendor/symfony/cache/PruneableInterface.php b/vendor/symfony/cache/PruneableInterface.php new file mode 100644 index 0000000..3095c80 --- /dev/null +++ b/vendor/symfony/cache/PruneableInterface.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache; + +/** + * Interface extends psr-6 and psr-16 caches to allow for pruning (deletion) of all expired cache items. + */ +interface PruneableInterface +{ + public function prune(): bool; +} diff --git a/vendor/symfony/cache/Psr16Cache.php b/vendor/symfony/cache/Psr16Cache.php new file mode 100644 index 0000000..01494d7 --- /dev/null +++ b/vendor/symfony/cache/Psr16Cache.php @@ -0,0 +1,240 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache; + +use Psr\Cache\CacheException as Psr6CacheException; +use Psr\Cache\CacheItemPoolInterface; +use Psr\SimpleCache\CacheException as SimpleCacheException; +use Psr\SimpleCache\CacheInterface; +use Symfony\Component\Cache\Adapter\AdapterInterface; +use Symfony\Component\Cache\Exception\InvalidArgumentException; +use Symfony\Component\Cache\Traits\ProxyTrait; + +/** + * Turns a PSR-6 cache into a PSR-16 one. + * + * @author Nicolas Grekas + */ +class Psr16Cache implements CacheInterface, PruneableInterface, ResettableInterface +{ + use ProxyTrait; + + private ?\Closure $createCacheItem = null; + private ?CacheItem $cacheItemPrototype = null; + private static \Closure $packCacheItem; + + public function __construct(CacheItemPoolInterface $pool) + { + $this->pool = $pool; + + if (!$pool instanceof AdapterInterface) { + return; + } + $cacheItemPrototype = &$this->cacheItemPrototype; + $createCacheItem = \Closure::bind( + static function ($key, $value, $allowInt = false) use (&$cacheItemPrototype) { + $item = clone $cacheItemPrototype; + $item->poolHash = $item->innerItem = null; + if ($allowInt && \is_int($key)) { + $item->key = (string) $key; + } else { + \assert('' !== CacheItem::validateKey($key)); + $item->key = $key; + } + $item->value = $value; + $item->isHit = false; + + return $item; + }, + null, + CacheItem::class + ); + $this->createCacheItem = function ($key, $value, $allowInt = false) use ($createCacheItem) { + if (null === $this->cacheItemPrototype) { + $this->get($allowInt && \is_int($key) ? (string) $key : $key); + } + $this->createCacheItem = $createCacheItem; + + return $createCacheItem($key, null, $allowInt)->set($value); + }; + self::$packCacheItem ??= \Closure::bind( + static function (CacheItem $item) { + $item->newMetadata = $item->metadata; + + return $item->pack(); + }, + null, + CacheItem::class + ); + } + + public function get($key, $default = null): mixed + { + try { + $item = $this->pool->getItem($key); + } catch (SimpleCacheException $e) { + throw $e; + } catch (Psr6CacheException $e) { + throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e); + } + if (null === $this->cacheItemPrototype) { + $this->cacheItemPrototype = clone $item; + $this->cacheItemPrototype->set(null); + } + + return $item->isHit() ? $item->get() : $default; + } + + public function set($key, $value, $ttl = null): bool + { + try { + if (null !== $f = $this->createCacheItem) { + $item = $f($key, $value); + } else { + $item = $this->pool->getItem($key)->set($value); + } + } catch (SimpleCacheException $e) { + throw $e; + } catch (Psr6CacheException $e) { + throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e); + } + if (null !== $ttl) { + $item->expiresAfter($ttl); + } + + return $this->pool->save($item); + } + + public function delete($key): bool + { + try { + return $this->pool->deleteItem($key); + } catch (SimpleCacheException $e) { + throw $e; + } catch (Psr6CacheException $e) { + throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e); + } + } + + public function clear(): bool + { + return $this->pool->clear(); + } + + public function getMultiple($keys, $default = null): iterable + { + if ($keys instanceof \Traversable) { + $keys = iterator_to_array($keys, false); + } elseif (!\is_array($keys)) { + throw new InvalidArgumentException(\sprintf('Cache keys must be array or Traversable, "%s" given.', get_debug_type($keys))); + } + + try { + $items = $this->pool->getItems($keys); + } catch (SimpleCacheException $e) { + throw $e; + } catch (Psr6CacheException $e) { + throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e); + } + $values = []; + + if (!$this->pool instanceof AdapterInterface) { + foreach ($items as $key => $item) { + $values[$key] = $item->isHit() ? $item->get() : $default; + } + + return $values; + } + + foreach ($items as $key => $item) { + $values[$key] = $item->isHit() ? (self::$packCacheItem)($item) : $default; + } + + return $values; + } + + public function setMultiple($values, $ttl = null): bool + { + $valuesIsArray = \is_array($values); + if (!$valuesIsArray && !$values instanceof \Traversable) { + throw new InvalidArgumentException(\sprintf('Cache values must be array or Traversable, "%s" given.', get_debug_type($values))); + } + $items = []; + + try { + if (null !== $f = $this->createCacheItem) { + $valuesIsArray = false; + foreach ($values as $key => $value) { + $items[$key] = $f($key, $value, true); + } + } elseif ($valuesIsArray) { + $items = []; + foreach ($values as $key => $value) { + $items[] = (string) $key; + } + $items = $this->pool->getItems($items); + } else { + foreach ($values as $key => $value) { + if (\is_int($key)) { + $key = (string) $key; + } + $items[$key] = $this->pool->getItem($key)->set($value); + } + } + } catch (SimpleCacheException $e) { + throw $e; + } catch (Psr6CacheException $e) { + throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e); + } + $ok = true; + + foreach ($items as $key => $item) { + if ($valuesIsArray) { + $item->set($values[$key]); + } + if (null !== $ttl) { + $item->expiresAfter($ttl); + } + $ok = $this->pool->saveDeferred($item) && $ok; + } + + return $this->pool->commit() && $ok; + } + + public function deleteMultiple($keys): bool + { + if ($keys instanceof \Traversable) { + $keys = iterator_to_array($keys, false); + } elseif (!\is_array($keys)) { + throw new InvalidArgumentException(\sprintf('Cache keys must be array or Traversable, "%s" given.', get_debug_type($keys))); + } + + try { + return $this->pool->deleteItems($keys); + } catch (SimpleCacheException $e) { + throw $e; + } catch (Psr6CacheException $e) { + throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e); + } + } + + public function has($key): bool + { + try { + return $this->pool->hasItem($key); + } catch (SimpleCacheException $e) { + throw $e; + } catch (Psr6CacheException $e) { + throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e); + } + } +} diff --git a/vendor/symfony/cache/README.md b/vendor/symfony/cache/README.md new file mode 100644 index 0000000..c466d57 --- /dev/null +++ b/vendor/symfony/cache/README.md @@ -0,0 +1,19 @@ +Symfony PSR-6 implementation for caching +======================================== + +The Cache component provides extended +[PSR-6](https://www.php-fig.org/psr/psr-6/) implementations for adding cache to +your applications. It is designed to have a low overhead so that caching is +fastest. It ships with adapters for the most widespread caching backends. +It also provides a [PSR-16](https://www.php-fig.org/psr/psr-16/) adapter, +and implementations for [symfony/cache-contracts](https://github.com/symfony/cache-contracts)' +`CacheInterface` and `TagAwareCacheInterface`. + +Resources +--------- + + * [Documentation](https://symfony.com/doc/current/components/cache.html) + * [Contributing](https://symfony.com/doc/current/contributing/index.html) + * [Report issues](https://github.com/symfony/symfony/issues) and + [send Pull Requests](https://github.com/symfony/symfony/pulls) + in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/vendor/symfony/cache/ResettableInterface.php b/vendor/symfony/cache/ResettableInterface.php new file mode 100644 index 0000000..7b0a853 --- /dev/null +++ b/vendor/symfony/cache/ResettableInterface.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache; + +use Symfony\Contracts\Service\ResetInterface; + +/** + * Resets a pool's local state. + */ +interface ResettableInterface extends ResetInterface +{ +} diff --git a/vendor/symfony/cache/Traits/AbstractAdapterTrait.php b/vendor/symfony/cache/Traits/AbstractAdapterTrait.php new file mode 100644 index 0000000..6a71674 --- /dev/null +++ b/vendor/symfony/cache/Traits/AbstractAdapterTrait.php @@ -0,0 +1,377 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Traits; + +use Psr\Cache\CacheItemInterface; +use Psr\Log\LoggerAwareTrait; +use Symfony\Component\Cache\CacheItem; +use Symfony\Component\Cache\Exception\InvalidArgumentException; + +/** + * @author Nicolas Grekas + * + * @internal + */ +trait AbstractAdapterTrait +{ + use LoggerAwareTrait; + + /** + * needs to be set by class, signature is function(string , mixed , bool ). + */ + private static \Closure $createCacheItem; + + /** + * needs to be set by class, signature is function(array , string , array <&expiredIds>). + */ + private static \Closure $mergeByLifetime; + + private string $namespace = ''; + private int $defaultLifetime; + private string $namespaceVersion = ''; + private bool $versioningIsEnabled = false; + private array $deferred = []; + private array $ids = []; + + /** + * The maximum length to enforce for identifiers or null when no limit applies. + */ + protected ?int $maxIdLength = null; + + /** + * Fetches several cache items. + * + * @param array $ids The cache identifiers to fetch + */ + abstract protected function doFetch(array $ids): iterable; + + /** + * Confirms if the cache contains specified cache item. + * + * @param string $id The identifier for which to check existence + */ + abstract protected function doHave(string $id): bool; + + /** + * Deletes all items in the pool. + * + * @param string $namespace The prefix used for all identifiers managed by this pool + */ + abstract protected function doClear(string $namespace): bool; + + /** + * Removes multiple items from the pool. + * + * @param array $ids An array of identifiers that should be removed from the pool + */ + abstract protected function doDelete(array $ids): bool; + + /** + * Persists several cache items immediately. + * + * @param array $values The values to cache, indexed by their cache identifier + * @param int $lifetime The lifetime of the cached values, 0 for persisting until manual cleaning + * + * @return array|bool The identifiers that failed to be cached or a boolean stating if caching succeeded or not + */ + abstract protected function doSave(array $values, int $lifetime): array|bool; + + public function hasItem(mixed $key): bool + { + $id = $this->getId($key); + + if (isset($this->deferred[$key])) { + $this->commit(); + } + + try { + return $this->doHave($id); + } catch (\Exception $e) { + CacheItem::log($this->logger, 'Failed to check if key "{key}" is cached: '.$e->getMessage(), ['key' => $key, 'exception' => $e, 'cache-adapter' => get_debug_type($this)]); + + return false; + } + } + + public function clear(string $prefix = ''): bool + { + $this->deferred = []; + if ($cleared = $this->versioningIsEnabled) { + if ('' === $namespaceVersionToClear = $this->namespaceVersion) { + foreach ($this->doFetch([static::NS_SEPARATOR.$this->namespace]) as $v) { + $namespaceVersionToClear = $v; + } + } + $namespaceToClear = $this->namespace.$namespaceVersionToClear; + $namespaceVersion = self::formatNamespaceVersion(mt_rand()); + try { + $e = $this->doSave([static::NS_SEPARATOR.$this->namespace => $namespaceVersion], 0); + } catch (\Exception $e) { + } + if (true !== $e && [] !== $e) { + $cleared = false; + $message = 'Failed to save the new namespace'.($e instanceof \Exception ? ': '.$e->getMessage() : '.'); + CacheItem::log($this->logger, $message, ['exception' => $e instanceof \Exception ? $e : null, 'cache-adapter' => get_debug_type($this)]); + } else { + $this->namespaceVersion = $namespaceVersion; + $this->ids = []; + } + } else { + $namespaceToClear = $this->namespace.$prefix; + } + + try { + return $this->doClear($namespaceToClear) || $cleared; + } catch (\Exception $e) { + CacheItem::log($this->logger, 'Failed to clear the cache: '.$e->getMessage(), ['exception' => $e, 'cache-adapter' => get_debug_type($this)]); + + return false; + } + } + + public function deleteItem(mixed $key): bool + { + return $this->deleteItems([$key]); + } + + public function deleteItems(array $keys): bool + { + $ids = []; + + foreach ($keys as $key) { + $ids[$key] = $this->getId($key); + unset($this->deferred[$key]); + } + + try { + if ($this->doDelete($ids)) { + return true; + } + } catch (\Exception) { + } + + $ok = true; + + // When bulk-delete failed, retry each item individually + foreach ($ids as $key => $id) { + try { + $e = null; + if ($this->doDelete([$id])) { + continue; + } + } catch (\Exception $e) { + } + $message = 'Failed to delete key "{key}"'.($e instanceof \Exception ? ': '.$e->getMessage() : '.'); + CacheItem::log($this->logger, $message, ['key' => $key, 'exception' => $e, 'cache-adapter' => get_debug_type($this)]); + $ok = false; + } + + return $ok; + } + + public function getItem(mixed $key): CacheItem + { + $id = $this->getId($key); + + if (isset($this->deferred[$key])) { + $this->commit(); + } + + $isHit = false; + $value = null; + + try { + foreach ($this->doFetch([$id]) as $value) { + $isHit = true; + } + + return (self::$createCacheItem)($key, $value, $isHit); + } catch (\Exception $e) { + CacheItem::log($this->logger, 'Failed to fetch key "{key}": '.$e->getMessage(), ['key' => $key, 'exception' => $e, 'cache-adapter' => get_debug_type($this)]); + } + + return (self::$createCacheItem)($key, null, false); + } + + public function getItems(array $keys = []): iterable + { + $ids = []; + $commit = false; + + foreach ($keys as $key) { + $ids[] = $this->getId($key); + $commit = $commit || isset($this->deferred[$key]); + } + + if ($commit) { + $this->commit(); + } + + try { + $items = $this->doFetch($ids); + } catch (\Exception $e) { + CacheItem::log($this->logger, 'Failed to fetch items: '.$e->getMessage(), ['keys' => $keys, 'exception' => $e, 'cache-adapter' => get_debug_type($this)]); + $items = []; + } + $ids = array_combine($ids, $keys); + + return $this->generateItems($items, $ids); + } + + public function save(CacheItemInterface $item): bool + { + if (!$item instanceof CacheItem) { + return false; + } + $this->deferred[$item->getKey()] = $item; + + return $this->commit(); + } + + public function saveDeferred(CacheItemInterface $item): bool + { + if (!$item instanceof CacheItem) { + return false; + } + $this->deferred[$item->getKey()] = $item; + + return true; + } + + /** + * Enables/disables versioning of items. + * + * When versioning is enabled, clearing the cache is atomic and doesn't require listing existing keys to proceed, + * but old keys may need garbage collection and extra round-trips to the back-end are required. + * + * Calling this method also clears the memoized namespace version and thus forces a resynchronization of it. + * + * @return bool the previous state of versioning + */ + public function enableVersioning(bool $enable = true): bool + { + $wasEnabled = $this->versioningIsEnabled; + $this->versioningIsEnabled = $enable; + $this->namespaceVersion = ''; + $this->ids = []; + + return $wasEnabled; + } + + public function reset(): void + { + if ($this->deferred) { + $this->commit(); + } + $this->namespaceVersion = ''; + $this->ids = []; + } + + public function __sleep(): array + { + throw new \BadMethodCallException('Cannot serialize '.__CLASS__); + } + + public function __wakeup(): void + { + throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); + } + + public function __destruct() + { + if ($this->deferred) { + $this->commit(); + } + } + + private function generateItems(iterable $items, array &$keys): \Generator + { + $f = self::$createCacheItem; + + try { + foreach ($items as $id => $value) { + if (!isset($keys[$id])) { + throw new InvalidArgumentException(\sprintf('Could not match value id "%s" to keys "%s".', $id, implode('", "', $keys))); + } + $key = $keys[$id]; + unset($keys[$id]); + yield $key => $f($key, $value, true); + } + } catch (\Exception $e) { + CacheItem::log($this->logger, 'Failed to fetch items: '.$e->getMessage(), ['keys' => array_values($keys), 'exception' => $e, 'cache-adapter' => get_debug_type($this)]); + } + + foreach ($keys as $key) { + yield $key => $f($key, null, false); + } + } + + /** + * @internal + */ + protected function getId(mixed $key): string + { + if ($this->versioningIsEnabled && '' === $this->namespaceVersion) { + $this->ids = []; + $this->namespaceVersion = '1'.static::NS_SEPARATOR; + try { + foreach ($this->doFetch([static::NS_SEPARATOR.$this->namespace]) as $v) { + $this->namespaceVersion = $v; + } + $e = true; + if ('1'.static::NS_SEPARATOR === $this->namespaceVersion) { + $this->namespaceVersion = self::formatNamespaceVersion(time()); + $e = $this->doSave([static::NS_SEPARATOR.$this->namespace => $this->namespaceVersion], 0); + } + } catch (\Exception $e) { + } + if (true !== $e && [] !== $e) { + $message = 'Failed to save the new namespace'.($e instanceof \Exception ? ': '.$e->getMessage() : '.'); + CacheItem::log($this->logger, $message, ['exception' => $e instanceof \Exception ? $e : null, 'cache-adapter' => get_debug_type($this)]); + } + } + + if (\is_string($key) && isset($this->ids[$key])) { + return $this->namespace.$this->namespaceVersion.$this->ids[$key]; + } + \assert('' !== CacheItem::validateKey($key)); + $this->ids[$key] = $key; + + if (\count($this->ids) > 1000) { + $this->ids = \array_slice($this->ids, 500, null, true); // stop memory leak if there are many keys + } + + if (null === $this->maxIdLength) { + return $this->namespace.$this->namespaceVersion.$key; + } + if (\strlen($id = $this->namespace.$this->namespaceVersion.$key) > $this->maxIdLength) { + // Use xxh128 to favor speed over security, which is not an issue here + $this->ids[$key] = $id = substr_replace(base64_encode(hash('xxh128', $key, true)), static::NS_SEPARATOR, -(\strlen($this->namespaceVersion) + 2)); + $id = $this->namespace.$this->namespaceVersion.$id; + } + + return $id; + } + + /** + * @internal + */ + public static function handleUnserializeCallback(string $class): never + { + throw new \DomainException('Class not found: '.$class); + } + + private static function formatNamespaceVersion(int $value): string + { + return strtr(substr_replace(base64_encode(pack('V', $value)), static::NS_SEPARATOR, 5), '/', '_'); + } +} diff --git a/vendor/symfony/cache/Traits/ContractsTrait.php b/vendor/symfony/cache/Traits/ContractsTrait.php new file mode 100644 index 0000000..d461582 --- /dev/null +++ b/vendor/symfony/cache/Traits/ContractsTrait.php @@ -0,0 +1,113 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Traits; + +use Psr\Log\LoggerInterface; +use Symfony\Component\Cache\Adapter\AdapterInterface; +use Symfony\Component\Cache\CacheItem; +use Symfony\Component\Cache\Exception\InvalidArgumentException; +use Symfony\Component\Cache\LockRegistry; +use Symfony\Contracts\Cache\CacheInterface; +use Symfony\Contracts\Cache\CacheTrait; +use Symfony\Contracts\Cache\ItemInterface; + +/** + * @author Nicolas Grekas + * + * @internal + */ +trait ContractsTrait +{ + use CacheTrait { + doGet as private contractsGet; + } + + private \Closure $callbackWrapper; + private array $computing = []; + + /** + * Wraps the callback passed to ->get() in a callable. + * + * @return callable the previous callback wrapper + */ + public function setCallbackWrapper(?callable $callbackWrapper): callable + { + if (!isset($this->callbackWrapper)) { + $this->callbackWrapper = LockRegistry::compute(...); + + if (\in_array(\PHP_SAPI, ['cli', 'phpdbg', 'embed'], true)) { + $this->setCallbackWrapper(null); + } + } + + if (null !== $callbackWrapper && !$callbackWrapper instanceof \Closure) { + $callbackWrapper = $callbackWrapper(...); + } + + $previousWrapper = $this->callbackWrapper; + $this->callbackWrapper = $callbackWrapper ?? static fn (callable $callback, ItemInterface $item, bool &$save, CacheInterface $pool, \Closure $setMetadata, ?LoggerInterface $logger) => $callback($item, $save); + + return $previousWrapper; + } + + private function doGet(AdapterInterface $pool, string $key, callable $callback, ?float $beta, ?array &$metadata = null): mixed + { + if (0 > $beta ??= 1.0) { + throw new InvalidArgumentException(\sprintf('Argument "$beta" provided to "%s::get()" must be a positive number, %f given.', static::class, $beta)); + } + + static $setMetadata; + + $setMetadata ??= \Closure::bind( + static function (CacheItem $item, float $startTime, ?array &$metadata) { + if ($item->expiry > $endTime = microtime(true)) { + $item->newMetadata[CacheItem::METADATA_EXPIRY] = $metadata[CacheItem::METADATA_EXPIRY] = $item->expiry; + $item->newMetadata[CacheItem::METADATA_CTIME] = $metadata[CacheItem::METADATA_CTIME] = (int) ceil(1000 * ($endTime - $startTime)); + } else { + unset($metadata[CacheItem::METADATA_EXPIRY], $metadata[CacheItem::METADATA_CTIME], $metadata[CacheItem::METADATA_TAGS]); + } + }, + null, + CacheItem::class + ); + + $this->callbackWrapper ??= LockRegistry::compute(...); + + return $this->contractsGet($pool, $key, function (CacheItem $item, bool &$save) use ($pool, $callback, $setMetadata, &$metadata, $key) { + // don't wrap nor save recursive calls + if (isset($this->computing[$key])) { + $value = $callback($item, $save); + $save = false; + + return $value; + } + + $this->computing[$key] = $key; + $startTime = microtime(true); + + if (!isset($this->callbackWrapper)) { + $this->setCallbackWrapper($this->setCallbackWrapper(null)); + } + + try { + $value = ($this->callbackWrapper)($callback, $item, $save, $pool, function (CacheItem $item) use ($setMetadata, $startTime, &$metadata) { + $setMetadata($item, $startTime, $metadata); + }, $this->logger ?? null); + $setMetadata($item, $startTime, $metadata); + + return $value; + } finally { + unset($this->computing[$key]); + } + }, $beta, $metadata, $this->logger ?? null); + } +} diff --git a/vendor/symfony/cache/Traits/FilesystemCommonTrait.php b/vendor/symfony/cache/Traits/FilesystemCommonTrait.php new file mode 100644 index 0000000..98e0d3e --- /dev/null +++ b/vendor/symfony/cache/Traits/FilesystemCommonTrait.php @@ -0,0 +1,190 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Traits; + +use Symfony\Component\Cache\Exception\InvalidArgumentException; + +/** + * @author Nicolas Grekas + * + * @internal + */ +trait FilesystemCommonTrait +{ + private string $directory; + private string $tmpSuffix; + + private function init(string $namespace, ?string $directory): void + { + if (!isset($directory[0])) { + $directory = sys_get_temp_dir().\DIRECTORY_SEPARATOR.'symfony-cache'; + } else { + $directory = realpath($directory) ?: $directory; + } + if (isset($namespace[0])) { + if (preg_match('#[^-+_.A-Za-z0-9]#', $namespace, $match)) { + throw new InvalidArgumentException(\sprintf('Namespace contains "%s" but only characters in [-+_.A-Za-z0-9] are allowed.', $match[0])); + } + $directory .= \DIRECTORY_SEPARATOR.$namespace; + } else { + $directory .= \DIRECTORY_SEPARATOR.'@'; + } + if (!is_dir($directory)) { + @mkdir($directory, 0777, true); + } + $directory .= \DIRECTORY_SEPARATOR; + // On Windows the whole path is limited to 258 chars + if ('\\' === \DIRECTORY_SEPARATOR && \strlen($directory) > 234) { + throw new InvalidArgumentException(\sprintf('Cache directory too long (%s).', $directory)); + } + + $this->directory = $directory; + } + + protected function doClear(string $namespace): bool + { + $ok = true; + + foreach ($this->scanHashDir($this->directory) as $file) { + if ('' !== $namespace && !str_starts_with($this->getFileKey($file), $namespace)) { + continue; + } + + $ok = ($this->doUnlink($file) || !file_exists($file)) && $ok; + } + + return $ok; + } + + protected function doDelete(array $ids): bool + { + $ok = true; + + foreach ($ids as $id) { + $file = $this->getFile($id); + $ok = (!is_file($file) || $this->doUnlink($file) || !file_exists($file)) && $ok; + } + + return $ok; + } + + protected function doUnlink(string $file): bool + { + return @unlink($file); + } + + private function write(string $file, string $data, ?int $expiresAt = null): bool + { + $unlink = false; + set_error_handler(static fn ($type, $message, $file, $line) => throw new \ErrorException($message, 0, $type, $file, $line)); + try { + $tmp = $this->directory.$this->tmpSuffix ??= str_replace('/', '-', base64_encode(random_bytes(6))); + try { + $h = fopen($tmp, 'x'); + } catch (\ErrorException $e) { + if (!str_contains($e->getMessage(), 'File exists')) { + throw $e; + } + + $tmp = $this->directory.$this->tmpSuffix = str_replace('/', '-', base64_encode(random_bytes(6))); + $h = fopen($tmp, 'x'); + } + fwrite($h, $data); + fclose($h); + $unlink = true; + + if (null !== $expiresAt) { + touch($tmp, $expiresAt ?: time() + 31556952); // 1 year in seconds + } + + if ('\\' === \DIRECTORY_SEPARATOR) { + $success = copy($tmp, $file); + } else { + $success = rename($tmp, $file); + $unlink = !$success; + } + + return $success; + } finally { + restore_error_handler(); + + if ($unlink) { + @unlink($tmp); + } + } + } + + private function getFile(string $id, bool $mkdir = false, ?string $directory = null): string + { + // Use xxh128 to favor speed over security, which is not an issue here + $hash = str_replace('/', '-', base64_encode(hash('xxh128', static::class.$id, true))); + $dir = ($directory ?? $this->directory).strtoupper($hash[0].\DIRECTORY_SEPARATOR.$hash[1].\DIRECTORY_SEPARATOR); + + if ($mkdir && !is_dir($dir)) { + @mkdir($dir, 0777, true); + } + + return $dir.substr($hash, 2, 20); + } + + private function getFileKey(string $file): string + { + return ''; + } + + private function scanHashDir(string $directory): \Generator + { + if (!is_dir($directory)) { + return; + } + + $chars = '+-ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; + + for ($i = 0; $i < 38; ++$i) { + if (!is_dir($directory.$chars[$i])) { + continue; + } + + for ($j = 0; $j < 38; ++$j) { + if (!is_dir($dir = $directory.$chars[$i].\DIRECTORY_SEPARATOR.$chars[$j])) { + continue; + } + + foreach (@scandir($dir, \SCANDIR_SORT_NONE) ?: [] as $file) { + if ('.' !== $file && '..' !== $file) { + yield $dir.\DIRECTORY_SEPARATOR.$file; + } + } + } + } + } + + public function __sleep(): array + { + throw new \BadMethodCallException('Cannot serialize '.__CLASS__); + } + + public function __wakeup(): void + { + throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); + } + + public function __destruct() + { + if (method_exists(parent::class, '__destruct')) { + parent::__destruct(); + } + if (isset($this->tmpSuffix) && is_file($this->directory.$this->tmpSuffix)) { + unlink($this->directory.$this->tmpSuffix); + } + } +} diff --git a/vendor/symfony/cache/Traits/FilesystemTrait.php b/vendor/symfony/cache/Traits/FilesystemTrait.php new file mode 100644 index 0000000..05fa10e --- /dev/null +++ b/vendor/symfony/cache/Traits/FilesystemTrait.php @@ -0,0 +1,113 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Traits; + +use Symfony\Component\Cache\Exception\CacheException; +use Symfony\Component\Cache\Marshaller\MarshallerInterface; + +/** + * @author Nicolas Grekas + * @author Rob Frawley 2nd + * + * @internal + */ +trait FilesystemTrait +{ + use FilesystemCommonTrait; + + private MarshallerInterface $marshaller; + + public function prune(): bool + { + $time = time(); + $pruned = true; + + foreach ($this->scanHashDir($this->directory) as $file) { + if (!$h = @fopen($file, 'r')) { + continue; + } + + if (($expiresAt = (int) fgets($h)) && $time >= $expiresAt) { + fclose($h); + $pruned = (@unlink($file) || !file_exists($file)) && $pruned; + } else { + fclose($h); + } + } + + return $pruned; + } + + protected function doFetch(array $ids): iterable + { + $values = []; + $now = time(); + + foreach ($ids as $id) { + $file = $this->getFile($id); + if (!is_file($file) || !$h = @fopen($file, 'r')) { + continue; + } + if (($expiresAt = (int) fgets($h)) && $now >= $expiresAt) { + fclose($h); + @unlink($file); + } else { + $i = rawurldecode(rtrim(fgets($h))); + $value = stream_get_contents($h); + fclose($h); + if ($i === $id) { + $values[$id] = $this->marshaller->unmarshall($value); + } + } + } + + return $values; + } + + protected function doHave(string $id): bool + { + $file = $this->getFile($id); + + return is_file($file) && (@filemtime($file) > time() || $this->doFetch([$id])); + } + + protected function doSave(array $values, int $lifetime): array|bool + { + $expiresAt = $lifetime ? (time() + $lifetime) : 0; + $values = $this->marshaller->marshall($values, $failed); + + foreach ($values as $id => $value) { + if (!$this->write($this->getFile($id, true), $expiresAt."\n".rawurlencode($id)."\n".$value, $expiresAt)) { + $failed[] = $id; + } + } + + if ($failed && !is_writable($this->directory)) { + throw new CacheException(\sprintf('Cache directory is not writable (%s).', $this->directory)); + } + + return $failed; + } + + private function getFileKey(string $file): string + { + if (!$h = @fopen($file, 'r')) { + return ''; + } + + fgets($h); // expiry + $encodedKey = fgets($h); + fclose($h); + + return rawurldecode(rtrim($encodedKey)); + } +} diff --git a/vendor/symfony/cache/Traits/ProxyTrait.php b/vendor/symfony/cache/Traits/ProxyTrait.php new file mode 100644 index 0000000..ba7c11f --- /dev/null +++ b/vendor/symfony/cache/Traits/ProxyTrait.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Traits; + +use Symfony\Component\Cache\PruneableInterface; +use Symfony\Contracts\Service\ResetInterface; + +/** + * @author Nicolas Grekas + * + * @internal + */ +trait ProxyTrait +{ + private object $pool; + + public function prune(): bool + { + return $this->pool instanceof PruneableInterface && $this->pool->prune(); + } + + public function reset(): void + { + if ($this->pool instanceof ResetInterface) { + $this->pool->reset(); + } + } +} diff --git a/vendor/symfony/cache/Traits/Redis5Proxy.php b/vendor/symfony/cache/Traits/Redis5Proxy.php new file mode 100644 index 0000000..b2402f2 --- /dev/null +++ b/vendor/symfony/cache/Traits/Redis5Proxy.php @@ -0,0 +1,1225 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Traits; + +use Symfony\Component\VarExporter\LazyObjectInterface; +use Symfony\Contracts\Service\ResetInterface; + +// Help opcache.preload discover always-needed symbols +class_exists(\Symfony\Component\VarExporter\Internal\Hydrator::class); +class_exists(\Symfony\Component\VarExporter\Internal\LazyObjectRegistry::class); +class_exists(\Symfony\Component\VarExporter\Internal\LazyObjectState::class); + +/** + * @internal + */ +class Redis5Proxy extends \Redis implements ResetInterface, LazyObjectInterface +{ + use RedisProxyTrait { + resetLazyObject as reset; + } + + public function __construct() + { + $this->initializeLazyObject()->__construct(...\func_get_args()); + } + + public function _prefix($key) + { + return $this->initializeLazyObject()->_prefix(...\func_get_args()); + } + + public function _serialize($value) + { + return $this->initializeLazyObject()->_serialize(...\func_get_args()); + } + + public function _unserialize($value) + { + return $this->initializeLazyObject()->_unserialize(...\func_get_args()); + } + + public function _pack($value) + { + return $this->initializeLazyObject()->_pack(...\func_get_args()); + } + + public function _unpack($value) + { + return $this->initializeLazyObject()->_unpack(...\func_get_args()); + } + + public function _compress($value) + { + return $this->initializeLazyObject()->_compress(...\func_get_args()); + } + + public function _uncompress($value) + { + return $this->initializeLazyObject()->_uncompress(...\func_get_args()); + } + + public function acl($subcmd, ...$args) + { + return $this->initializeLazyObject()->acl(...\func_get_args()); + } + + public function append($key, $value) + { + return $this->initializeLazyObject()->append(...\func_get_args()); + } + + public function auth(#[\SensitiveParameter] $auth) + { + return $this->initializeLazyObject()->auth(...\func_get_args()); + } + + public function bgSave() + { + return $this->initializeLazyObject()->bgSave(...\func_get_args()); + } + + public function bgrewriteaof() + { + return $this->initializeLazyObject()->bgrewriteaof(...\func_get_args()); + } + + public function bitcount($key) + { + return $this->initializeLazyObject()->bitcount(...\func_get_args()); + } + + public function bitop($operation, $ret_key, $key, ...$other_keys) + { + return $this->initializeLazyObject()->bitop(...\func_get_args()); + } + + public function bitpos($key, $bit, $start = null, $end = null) + { + return $this->initializeLazyObject()->bitpos(...\func_get_args()); + } + + public function blPop($key, $timeout_or_key, ...$extra_args) + { + return $this->initializeLazyObject()->blPop(...\func_get_args()); + } + + public function brPop($key, $timeout_or_key, ...$extra_args) + { + return $this->initializeLazyObject()->brPop(...\func_get_args()); + } + + public function brpoplpush($src, $dst, $timeout) + { + return $this->initializeLazyObject()->brpoplpush(...\func_get_args()); + } + + public function bzPopMax($key, $timeout_or_key, ...$extra_args) + { + return $this->initializeLazyObject()->bzPopMax(...\func_get_args()); + } + + public function bzPopMin($key, $timeout_or_key, ...$extra_args) + { + return $this->initializeLazyObject()->bzPopMin(...\func_get_args()); + } + + public function clearLastError() + { + return $this->initializeLazyObject()->clearLastError(...\func_get_args()); + } + + public function client($cmd, ...$args) + { + return $this->initializeLazyObject()->client(...\func_get_args()); + } + + public function close() + { + return $this->initializeLazyObject()->close(...\func_get_args()); + } + + public function command(...$args) + { + return $this->initializeLazyObject()->command(...\func_get_args()); + } + + public function config($cmd, $key, $value = null) + { + return $this->initializeLazyObject()->config(...\func_get_args()); + } + + public function connect($host, $port = null, $timeout = null, $retry_interval = null) + { + return $this->initializeLazyObject()->connect(...\func_get_args()); + } + + public function dbSize() + { + return $this->initializeLazyObject()->dbSize(...\func_get_args()); + } + + public function debug($key) + { + return $this->initializeLazyObject()->debug(...\func_get_args()); + } + + public function decr($key) + { + return $this->initializeLazyObject()->decr(...\func_get_args()); + } + + public function decrBy($key, $value) + { + return $this->initializeLazyObject()->decrBy(...\func_get_args()); + } + + public function del($key, ...$other_keys) + { + return $this->initializeLazyObject()->del(...\func_get_args()); + } + + public function discard() + { + return $this->initializeLazyObject()->discard(...\func_get_args()); + } + + public function dump($key) + { + return $this->initializeLazyObject()->dump(...\func_get_args()); + } + + public function echo($msg) + { + return $this->initializeLazyObject()->echo(...\func_get_args()); + } + + public function eval($script, $args = null, $num_keys = null) + { + return $this->initializeLazyObject()->eval(...\func_get_args()); + } + + public function evalsha($script_sha, $args = null, $num_keys = null) + { + return $this->initializeLazyObject()->evalsha(...\func_get_args()); + } + + public function exec() + { + return $this->initializeLazyObject()->exec(...\func_get_args()); + } + + public function exists($key, ...$other_keys) + { + return $this->initializeLazyObject()->exists(...\func_get_args()); + } + + public function expire($key, $timeout) + { + return $this->initializeLazyObject()->expire(...\func_get_args()); + } + + public function expireAt($key, $timestamp) + { + return $this->initializeLazyObject()->expireAt(...\func_get_args()); + } + + public function flushAll($async = null) + { + return $this->initializeLazyObject()->flushAll(...\func_get_args()); + } + + public function flushDB($async = null) + { + return $this->initializeLazyObject()->flushDB(...\func_get_args()); + } + + public function geoadd($key, $lng, $lat, $member, ...$other_triples) + { + return $this->initializeLazyObject()->geoadd(...\func_get_args()); + } + + public function geodist($key, $src, $dst, $unit = null) + { + return $this->initializeLazyObject()->geodist(...\func_get_args()); + } + + public function geohash($key, $member, ...$other_members) + { + return $this->initializeLazyObject()->geohash(...\func_get_args()); + } + + public function geopos($key, $member, ...$other_members) + { + return $this->initializeLazyObject()->geopos(...\func_get_args()); + } + + public function georadius($key, $lng, $lan, $radius, $unit, $opts = null) + { + return $this->initializeLazyObject()->georadius(...\func_get_args()); + } + + public function georadius_ro($key, $lng, $lan, $radius, $unit, $opts = null) + { + return $this->initializeLazyObject()->georadius_ro(...\func_get_args()); + } + + public function georadiusbymember($key, $member, $radius, $unit, $opts = null) + { + return $this->initializeLazyObject()->georadiusbymember(...\func_get_args()); + } + + public function georadiusbymember_ro($key, $member, $radius, $unit, $opts = null) + { + return $this->initializeLazyObject()->georadiusbymember_ro(...\func_get_args()); + } + + public function get($key) + { + return $this->initializeLazyObject()->get(...\func_get_args()); + } + + public function getAuth() + { + return $this->initializeLazyObject()->getAuth(...\func_get_args()); + } + + public function getBit($key, $offset) + { + return $this->initializeLazyObject()->getBit(...\func_get_args()); + } + + public function getDBNum() + { + return $this->initializeLazyObject()->getDBNum(...\func_get_args()); + } + + public function getHost() + { + return $this->initializeLazyObject()->getHost(...\func_get_args()); + } + + public function getLastError() + { + return $this->initializeLazyObject()->getLastError(...\func_get_args()); + } + + public function getMode() + { + return $this->initializeLazyObject()->getMode(...\func_get_args()); + } + + public function getOption($option) + { + return $this->initializeLazyObject()->getOption(...\func_get_args()); + } + + public function getPersistentID() + { + return $this->initializeLazyObject()->getPersistentID(...\func_get_args()); + } + + public function getPort() + { + return $this->initializeLazyObject()->getPort(...\func_get_args()); + } + + public function getRange($key, $start, $end) + { + return $this->initializeLazyObject()->getRange(...\func_get_args()); + } + + public function getReadTimeout() + { + return $this->initializeLazyObject()->getReadTimeout(...\func_get_args()); + } + + public function getSet($key, $value) + { + return $this->initializeLazyObject()->getSet(...\func_get_args()); + } + + public function getTimeout() + { + return $this->initializeLazyObject()->getTimeout(...\func_get_args()); + } + + public function hDel($key, $member, ...$other_members) + { + return $this->initializeLazyObject()->hDel(...\func_get_args()); + } + + public function hExists($key, $member) + { + return $this->initializeLazyObject()->hExists(...\func_get_args()); + } + + public function hGet($key, $member) + { + return $this->initializeLazyObject()->hGet(...\func_get_args()); + } + + public function hGetAll($key) + { + return $this->initializeLazyObject()->hGetAll(...\func_get_args()); + } + + public function hIncrBy($key, $member, $value) + { + return $this->initializeLazyObject()->hIncrBy(...\func_get_args()); + } + + public function hIncrByFloat($key, $member, $value) + { + return $this->initializeLazyObject()->hIncrByFloat(...\func_get_args()); + } + + public function hKeys($key) + { + return $this->initializeLazyObject()->hKeys(...\func_get_args()); + } + + public function hLen($key) + { + return $this->initializeLazyObject()->hLen(...\func_get_args()); + } + + public function hMget($key, $keys) + { + return $this->initializeLazyObject()->hMget(...\func_get_args()); + } + + public function hMset($key, $pairs) + { + return $this->initializeLazyObject()->hMset(...\func_get_args()); + } + + public function hSet($key, $member, $value) + { + return $this->initializeLazyObject()->hSet(...\func_get_args()); + } + + public function hSetNx($key, $member, $value) + { + return $this->initializeLazyObject()->hSetNx(...\func_get_args()); + } + + public function hStrLen($key, $member) + { + return $this->initializeLazyObject()->hStrLen(...\func_get_args()); + } + + public function hVals($key) + { + return $this->initializeLazyObject()->hVals(...\func_get_args()); + } + + public function hscan($str_key, &$i_iterator, $str_pattern = null, $i_count = null) + { + return $this->initializeLazyObject()->hscan($str_key, $i_iterator, ...\array_slice(\func_get_args(), 2)); + } + + public function incr($key) + { + return $this->initializeLazyObject()->incr(...\func_get_args()); + } + + public function incrBy($key, $value) + { + return $this->initializeLazyObject()->incrBy(...\func_get_args()); + } + + public function incrByFloat($key, $value) + { + return $this->initializeLazyObject()->incrByFloat(...\func_get_args()); + } + + public function info($option = null) + { + return $this->initializeLazyObject()->info(...\func_get_args()); + } + + public function isConnected() + { + return $this->initializeLazyObject()->isConnected(...\func_get_args()); + } + + public function keys($pattern) + { + return $this->initializeLazyObject()->keys(...\func_get_args()); + } + + public function lInsert($key, $position, $pivot, $value) + { + return $this->initializeLazyObject()->lInsert(...\func_get_args()); + } + + public function lLen($key) + { + return $this->initializeLazyObject()->lLen(...\func_get_args()); + } + + public function lPop($key) + { + return $this->initializeLazyObject()->lPop(...\func_get_args()); + } + + public function lPush($key, $value) + { + return $this->initializeLazyObject()->lPush(...\func_get_args()); + } + + public function lPushx($key, $value) + { + return $this->initializeLazyObject()->lPushx(...\func_get_args()); + } + + public function lSet($key, $index, $value) + { + return $this->initializeLazyObject()->lSet(...\func_get_args()); + } + + public function lastSave() + { + return $this->initializeLazyObject()->lastSave(...\func_get_args()); + } + + public function lindex($key, $index) + { + return $this->initializeLazyObject()->lindex(...\func_get_args()); + } + + public function lrange($key, $start, $end) + { + return $this->initializeLazyObject()->lrange(...\func_get_args()); + } + + public function lrem($key, $value, $count) + { + return $this->initializeLazyObject()->lrem(...\func_get_args()); + } + + public function ltrim($key, $start, $stop) + { + return $this->initializeLazyObject()->ltrim(...\func_get_args()); + } + + public function mget($keys) + { + return $this->initializeLazyObject()->mget(...\func_get_args()); + } + + public function migrate($host, $port, $key, $db, $timeout, $copy = null, $replace = null) + { + return $this->initializeLazyObject()->migrate(...\func_get_args()); + } + + public function move($key, $dbindex) + { + return $this->initializeLazyObject()->move(...\func_get_args()); + } + + public function mset($pairs) + { + return $this->initializeLazyObject()->mset(...\func_get_args()); + } + + public function msetnx($pairs) + { + return $this->initializeLazyObject()->msetnx(...\func_get_args()); + } + + public function multi($mode = null) + { + return $this->initializeLazyObject()->multi(...\func_get_args()); + } + + public function object($field, $key) + { + return $this->initializeLazyObject()->object(...\func_get_args()); + } + + public function pconnect($host, $port = null, $timeout = null) + { + return $this->initializeLazyObject()->pconnect(...\func_get_args()); + } + + public function persist($key) + { + return $this->initializeLazyObject()->persist(...\func_get_args()); + } + + public function pexpire($key, $timestamp) + { + return $this->initializeLazyObject()->pexpire(...\func_get_args()); + } + + public function pexpireAt($key, $timestamp) + { + return $this->initializeLazyObject()->pexpireAt(...\func_get_args()); + } + + public function pfadd($key, $elements) + { + return $this->initializeLazyObject()->pfadd(...\func_get_args()); + } + + public function pfcount($key) + { + return $this->initializeLazyObject()->pfcount(...\func_get_args()); + } + + public function pfmerge($dstkey, $keys) + { + return $this->initializeLazyObject()->pfmerge(...\func_get_args()); + } + + public function ping() + { + return $this->initializeLazyObject()->ping(...\func_get_args()); + } + + public function pipeline() + { + return $this->initializeLazyObject()->pipeline(...\func_get_args()); + } + + public function psetex($key, $expire, $value) + { + return $this->initializeLazyObject()->psetex(...\func_get_args()); + } + + public function psubscribe($patterns, $callback) + { + return $this->initializeLazyObject()->psubscribe(...\func_get_args()); + } + + public function pttl($key) + { + return $this->initializeLazyObject()->pttl(...\func_get_args()); + } + + public function publish($channel, $message) + { + return $this->initializeLazyObject()->publish(...\func_get_args()); + } + + public function pubsub($cmd, ...$args) + { + return $this->initializeLazyObject()->pubsub(...\func_get_args()); + } + + public function punsubscribe($pattern, ...$other_patterns) + { + return $this->initializeLazyObject()->punsubscribe(...\func_get_args()); + } + + public function rPop($key) + { + return $this->initializeLazyObject()->rPop(...\func_get_args()); + } + + public function rPush($key, $value) + { + return $this->initializeLazyObject()->rPush(...\func_get_args()); + } + + public function rPushx($key, $value) + { + return $this->initializeLazyObject()->rPushx(...\func_get_args()); + } + + public function randomKey() + { + return $this->initializeLazyObject()->randomKey(...\func_get_args()); + } + + public function rawcommand($cmd, ...$args) + { + return $this->initializeLazyObject()->rawcommand(...\func_get_args()); + } + + public function rename($key, $newkey) + { + return $this->initializeLazyObject()->rename(...\func_get_args()); + } + + public function renameNx($key, $newkey) + { + return $this->initializeLazyObject()->renameNx(...\func_get_args()); + } + + public function restore($ttl, $key, $value) + { + return $this->initializeLazyObject()->restore(...\func_get_args()); + } + + public function role() + { + return $this->initializeLazyObject()->role(...\func_get_args()); + } + + public function rpoplpush($src, $dst) + { + return $this->initializeLazyObject()->rpoplpush(...\func_get_args()); + } + + public function sAdd($key, $value) + { + return $this->initializeLazyObject()->sAdd(...\func_get_args()); + } + + public function sAddArray($key, $options) + { + return $this->initializeLazyObject()->sAddArray(...\func_get_args()); + } + + public function sDiff($key, ...$other_keys) + { + return $this->initializeLazyObject()->sDiff(...\func_get_args()); + } + + public function sDiffStore($dst, $key, ...$other_keys) + { + return $this->initializeLazyObject()->sDiffStore(...\func_get_args()); + } + + public function sInter($key, ...$other_keys) + { + return $this->initializeLazyObject()->sInter(...\func_get_args()); + } + + public function sInterStore($dst, $key, ...$other_keys) + { + return $this->initializeLazyObject()->sInterStore(...\func_get_args()); + } + + public function sMembers($key) + { + return $this->initializeLazyObject()->sMembers(...\func_get_args()); + } + + public function sMisMember($key, $member, ...$other_members) + { + return $this->initializeLazyObject()->sMisMember(...\func_get_args()); + } + + public function sMove($src, $dst, $value) + { + return $this->initializeLazyObject()->sMove(...\func_get_args()); + } + + public function sPop($key) + { + return $this->initializeLazyObject()->sPop(...\func_get_args()); + } + + public function sRandMember($key, $count = null) + { + return $this->initializeLazyObject()->sRandMember(...\func_get_args()); + } + + public function sUnion($key, ...$other_keys) + { + return $this->initializeLazyObject()->sUnion(...\func_get_args()); + } + + public function sUnionStore($dst, $key, ...$other_keys) + { + return $this->initializeLazyObject()->sUnionStore(...\func_get_args()); + } + + public function save() + { + return $this->initializeLazyObject()->save(...\func_get_args()); + } + + public function scan(&$i_iterator, $str_pattern = null, $i_count = null) + { + return $this->initializeLazyObject()->scan($i_iterator, ...\array_slice(\func_get_args(), 1)); + } + + public function scard($key) + { + return $this->initializeLazyObject()->scard(...\func_get_args()); + } + + public function script($cmd, ...$args) + { + return $this->initializeLazyObject()->script(...\func_get_args()); + } + + public function select($dbindex) + { + return $this->initializeLazyObject()->select(...\func_get_args()); + } + + public function set($key, $value, $opts = null) + { + return $this->initializeLazyObject()->set(...\func_get_args()); + } + + public function setBit($key, $offset, $value) + { + return $this->initializeLazyObject()->setBit(...\func_get_args()); + } + + public function setOption($option, $value) + { + return $this->initializeLazyObject()->setOption(...\func_get_args()); + } + + public function setRange($key, $offset, $value) + { + return $this->initializeLazyObject()->setRange(...\func_get_args()); + } + + public function setex($key, $expire, $value) + { + return $this->initializeLazyObject()->setex(...\func_get_args()); + } + + public function setnx($key, $value) + { + return $this->initializeLazyObject()->setnx(...\func_get_args()); + } + + public function sismember($key, $value) + { + return $this->initializeLazyObject()->sismember(...\func_get_args()); + } + + public function slaveof($host = null, $port = null) + { + return $this->initializeLazyObject()->slaveof(...\func_get_args()); + } + + public function slowlog($arg, $option = null) + { + return $this->initializeLazyObject()->slowlog(...\func_get_args()); + } + + public function sort($key, $options = null) + { + return $this->initializeLazyObject()->sort(...\func_get_args()); + } + + public function sortAsc($key, $pattern = null, $get = null, $start = null, $end = null, $getList = null) + { + return $this->initializeLazyObject()->sortAsc(...\func_get_args()); + } + + public function sortAscAlpha($key, $pattern = null, $get = null, $start = null, $end = null, $getList = null) + { + return $this->initializeLazyObject()->sortAscAlpha(...\func_get_args()); + } + + public function sortDesc($key, $pattern = null, $get = null, $start = null, $end = null, $getList = null) + { + return $this->initializeLazyObject()->sortDesc(...\func_get_args()); + } + + public function sortDescAlpha($key, $pattern = null, $get = null, $start = null, $end = null, $getList = null) + { + return $this->initializeLazyObject()->sortDescAlpha(...\func_get_args()); + } + + public function srem($key, $member, ...$other_members) + { + return $this->initializeLazyObject()->srem(...\func_get_args()); + } + + public function sscan($str_key, &$i_iterator, $str_pattern = null, $i_count = null) + { + return $this->initializeLazyObject()->sscan($str_key, $i_iterator, ...\array_slice(\func_get_args(), 2)); + } + + public function strlen($key) + { + return $this->initializeLazyObject()->strlen(...\func_get_args()); + } + + public function subscribe($channels, $callback) + { + return $this->initializeLazyObject()->subscribe(...\func_get_args()); + } + + public function swapdb($srcdb, $dstdb) + { + return $this->initializeLazyObject()->swapdb(...\func_get_args()); + } + + public function time() + { + return $this->initializeLazyObject()->time(...\func_get_args()); + } + + public function ttl($key) + { + return $this->initializeLazyObject()->ttl(...\func_get_args()); + } + + public function type($key) + { + return $this->initializeLazyObject()->type(...\func_get_args()); + } + + public function unlink($key, ...$other_keys) + { + return $this->initializeLazyObject()->unlink(...\func_get_args()); + } + + public function unsubscribe($channel, ...$other_channels) + { + return $this->initializeLazyObject()->unsubscribe(...\func_get_args()); + } + + public function unwatch() + { + return $this->initializeLazyObject()->unwatch(...\func_get_args()); + } + + public function wait($numslaves, $timeout) + { + return $this->initializeLazyObject()->wait(...\func_get_args()); + } + + public function watch($key, ...$other_keys) + { + return $this->initializeLazyObject()->watch(...\func_get_args()); + } + + public function xack($str_key, $str_group, $arr_ids) + { + return $this->initializeLazyObject()->xack(...\func_get_args()); + } + + public function xadd($str_key, $str_id, $arr_fields, $i_maxlen = null, $boo_approximate = null) + { + return $this->initializeLazyObject()->xadd(...\func_get_args()); + } + + public function xclaim($str_key, $str_group, $str_consumer, $i_min_idle, $arr_ids, $arr_opts = null) + { + return $this->initializeLazyObject()->xclaim(...\func_get_args()); + } + + public function xdel($str_key, $arr_ids) + { + return $this->initializeLazyObject()->xdel(...\func_get_args()); + } + + public function xgroup($str_operation, $str_key = null, $str_arg1 = null, $str_arg2 = null, $str_arg3 = null) + { + return $this->initializeLazyObject()->xgroup(...\func_get_args()); + } + + public function xinfo($str_cmd, $str_key = null, $str_group = null) + { + return $this->initializeLazyObject()->xinfo(...\func_get_args()); + } + + public function xlen($key) + { + return $this->initializeLazyObject()->xlen(...\func_get_args()); + } + + public function xpending($str_key, $str_group, $str_start = null, $str_end = null, $i_count = null, $str_consumer = null) + { + return $this->initializeLazyObject()->xpending(...\func_get_args()); + } + + public function xrange($str_key, $str_start, $str_end, $i_count = null) + { + return $this->initializeLazyObject()->xrange(...\func_get_args()); + } + + public function xread($arr_streams, $i_count = null, $i_block = null) + { + return $this->initializeLazyObject()->xread(...\func_get_args()); + } + + public function xreadgroup($str_group, $str_consumer, $arr_streams, $i_count = null, $i_block = null) + { + return $this->initializeLazyObject()->xreadgroup(...\func_get_args()); + } + + public function xrevrange($str_key, $str_start, $str_end, $i_count = null) + { + return $this->initializeLazyObject()->xrevrange(...\func_get_args()); + } + + public function xtrim($str_key, $i_maxlen, $boo_approximate = null) + { + return $this->initializeLazyObject()->xtrim(...\func_get_args()); + } + + public function zAdd($key, $score, $value, ...$extra_args) + { + return $this->initializeLazyObject()->zAdd(...\func_get_args()); + } + + public function zCard($key) + { + return $this->initializeLazyObject()->zCard(...\func_get_args()); + } + + public function zCount($key, $min, $max) + { + return $this->initializeLazyObject()->zCount(...\func_get_args()); + } + + public function zIncrBy($key, $value, $member) + { + return $this->initializeLazyObject()->zIncrBy(...\func_get_args()); + } + + public function zLexCount($key, $min, $max) + { + return $this->initializeLazyObject()->zLexCount(...\func_get_args()); + } + + public function zPopMax($key) + { + return $this->initializeLazyObject()->zPopMax(...\func_get_args()); + } + + public function zPopMin($key) + { + return $this->initializeLazyObject()->zPopMin(...\func_get_args()); + } + + public function zRange($key, $start, $end, $scores = null) + { + return $this->initializeLazyObject()->zRange(...\func_get_args()); + } + + public function zRangeByLex($key, $min, $max, $offset = null, $limit = null) + { + return $this->initializeLazyObject()->zRangeByLex(...\func_get_args()); + } + + public function zRangeByScore($key, $start, $end, $options = null) + { + return $this->initializeLazyObject()->zRangeByScore(...\func_get_args()); + } + + public function zRank($key, $member) + { + return $this->initializeLazyObject()->zRank(...\func_get_args()); + } + + public function zRem($key, $member, ...$other_members) + { + return $this->initializeLazyObject()->zRem(...\func_get_args()); + } + + public function zRemRangeByLex($key, $min, $max) + { + return $this->initializeLazyObject()->zRemRangeByLex(...\func_get_args()); + } + + public function zRemRangeByRank($key, $start, $end) + { + return $this->initializeLazyObject()->zRemRangeByRank(...\func_get_args()); + } + + public function zRemRangeByScore($key, $min, $max) + { + return $this->initializeLazyObject()->zRemRangeByScore(...\func_get_args()); + } + + public function zRevRange($key, $start, $end, $scores = null) + { + return $this->initializeLazyObject()->zRevRange(...\func_get_args()); + } + + public function zRevRangeByLex($key, $min, $max, $offset = null, $limit = null) + { + return $this->initializeLazyObject()->zRevRangeByLex(...\func_get_args()); + } + + public function zRevRangeByScore($key, $start, $end, $options = null) + { + return $this->initializeLazyObject()->zRevRangeByScore(...\func_get_args()); + } + + public function zRevRank($key, $member) + { + return $this->initializeLazyObject()->zRevRank(...\func_get_args()); + } + + public function zScore($key, $member) + { + return $this->initializeLazyObject()->zScore(...\func_get_args()); + } + + public function zinterstore($key, $keys, $weights = null, $aggregate = null) + { + return $this->initializeLazyObject()->zinterstore(...\func_get_args()); + } + + public function zscan($str_key, &$i_iterator, $str_pattern = null, $i_count = null) + { + return $this->initializeLazyObject()->zscan($str_key, $i_iterator, ...\array_slice(\func_get_args(), 2)); + } + + public function zunionstore($key, $keys, $weights = null, $aggregate = null) + { + return $this->initializeLazyObject()->zunionstore(...\func_get_args()); + } + + public function delete($key, ...$other_keys) + { + return $this->initializeLazyObject()->delete(...\func_get_args()); + } + + public function evaluate($script, $args = null, $num_keys = null) + { + return $this->initializeLazyObject()->evaluate(...\func_get_args()); + } + + public function evaluateSha($script_sha, $args = null, $num_keys = null) + { + return $this->initializeLazyObject()->evaluateSha(...\func_get_args()); + } + + public function getKeys($pattern) + { + return $this->initializeLazyObject()->getKeys(...\func_get_args()); + } + + public function getMultiple($keys) + { + return $this->initializeLazyObject()->getMultiple(...\func_get_args()); + } + + public function lGet($key, $index) + { + return $this->initializeLazyObject()->lGet(...\func_get_args()); + } + + public function lGetRange($key, $start, $end) + { + return $this->initializeLazyObject()->lGetRange(...\func_get_args()); + } + + public function lRemove($key, $value, $count) + { + return $this->initializeLazyObject()->lRemove(...\func_get_args()); + } + + public function lSize($key) + { + return $this->initializeLazyObject()->lSize(...\func_get_args()); + } + + public function listTrim($key, $start, $stop) + { + return $this->initializeLazyObject()->listTrim(...\func_get_args()); + } + + public function open($host, $port = null, $timeout = null, $retry_interval = null) + { + return $this->initializeLazyObject()->open(...\func_get_args()); + } + + public function popen($host, $port = null, $timeout = null) + { + return $this->initializeLazyObject()->popen(...\func_get_args()); + } + + public function renameKey($key, $newkey) + { + return $this->initializeLazyObject()->renameKey(...\func_get_args()); + } + + public function sContains($key, $value) + { + return $this->initializeLazyObject()->sContains(...\func_get_args()); + } + + public function sGetMembers($key) + { + return $this->initializeLazyObject()->sGetMembers(...\func_get_args()); + } + + public function sRemove($key, $member, ...$other_members) + { + return $this->initializeLazyObject()->sRemove(...\func_get_args()); + } + + public function sSize($key) + { + return $this->initializeLazyObject()->sSize(...\func_get_args()); + } + + public function sendEcho($msg) + { + return $this->initializeLazyObject()->sendEcho(...\func_get_args()); + } + + public function setTimeout($key, $timeout) + { + return $this->initializeLazyObject()->setTimeout(...\func_get_args()); + } + + public function substr($key, $start, $end) + { + return $this->initializeLazyObject()->substr(...\func_get_args()); + } + + public function zDelete($key, $member, ...$other_members) + { + return $this->initializeLazyObject()->zDelete(...\func_get_args()); + } + + public function zDeleteRangeByRank($key, $min, $max) + { + return $this->initializeLazyObject()->zDeleteRangeByRank(...\func_get_args()); + } + + public function zDeleteRangeByScore($key, $min, $max) + { + return $this->initializeLazyObject()->zDeleteRangeByScore(...\func_get_args()); + } + + public function zInter($key, $keys, $weights = null, $aggregate = null) + { + return $this->initializeLazyObject()->zInter(...\func_get_args()); + } + + public function zRemove($key, $member, ...$other_members) + { + return $this->initializeLazyObject()->zRemove(...\func_get_args()); + } + + public function zRemoveRangeByScore($key, $min, $max) + { + return $this->initializeLazyObject()->zRemoveRangeByScore(...\func_get_args()); + } + + public function zReverseRange($key, $start, $end, $scores = null) + { + return $this->initializeLazyObject()->zReverseRange(...\func_get_args()); + } + + public function zSize($key) + { + return $this->initializeLazyObject()->zSize(...\func_get_args()); + } + + public function zUnion($key, $keys, $weights = null, $aggregate = null) + { + return $this->initializeLazyObject()->zUnion(...\func_get_args()); + } +} diff --git a/vendor/symfony/cache/Traits/Redis6Proxy.php b/vendor/symfony/cache/Traits/Redis6Proxy.php new file mode 100644 index 0000000..c7e05cd --- /dev/null +++ b/vendor/symfony/cache/Traits/Redis6Proxy.php @@ -0,0 +1,1266 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Traits; + +use Symfony\Component\VarExporter\LazyObjectInterface; +use Symfony\Contracts\Service\ResetInterface; + +// Help opcache.preload discover always-needed symbols +class_exists(\Symfony\Component\VarExporter\Internal\Hydrator::class); +class_exists(\Symfony\Component\VarExporter\Internal\LazyObjectRegistry::class); +class_exists(\Symfony\Component\VarExporter\Internal\LazyObjectState::class); + +/** + * @internal + */ +class Redis6Proxy extends \Redis implements ResetInterface, LazyObjectInterface +{ + use Redis6ProxyTrait; + use RedisProxyTrait { + resetLazyObject as reset; + } + + public function __construct($options = null) + { + $this->initializeLazyObject()->__construct(...\func_get_args()); + } + + public function _compress($value): string + { + return $this->initializeLazyObject()->_compress(...\func_get_args()); + } + + public function _uncompress($value): string + { + return $this->initializeLazyObject()->_uncompress(...\func_get_args()); + } + + public function _prefix($key): string + { + return $this->initializeLazyObject()->_prefix(...\func_get_args()); + } + + public function _serialize($value): string + { + return $this->initializeLazyObject()->_serialize(...\func_get_args()); + } + + public function _unserialize($value): mixed + { + return $this->initializeLazyObject()->_unserialize(...\func_get_args()); + } + + public function _pack($value): string + { + return $this->initializeLazyObject()->_pack(...\func_get_args()); + } + + public function _unpack($value): mixed + { + return $this->initializeLazyObject()->_unpack(...\func_get_args()); + } + + public function acl($subcmd, ...$args): mixed + { + return $this->initializeLazyObject()->acl(...\func_get_args()); + } + + public function append($key, $value): \Redis|false|int + { + return $this->initializeLazyObject()->append(...\func_get_args()); + } + + public function auth(#[\SensitiveParameter] $credentials): \Redis|bool + { + return $this->initializeLazyObject()->auth(...\func_get_args()); + } + + public function bgSave(): \Redis|bool + { + return $this->initializeLazyObject()->bgSave(...\func_get_args()); + } + + public function bgrewriteaof(): \Redis|bool + { + return $this->initializeLazyObject()->bgrewriteaof(...\func_get_args()); + } + + public function bitcount($key, $start = 0, $end = -1, $bybit = false): \Redis|false|int + { + return $this->initializeLazyObject()->bitcount(...\func_get_args()); + } + + public function bitop($operation, $deskey, $srckey, ...$other_keys): \Redis|false|int + { + return $this->initializeLazyObject()->bitop(...\func_get_args()); + } + + public function bitpos($key, $bit, $start = 0, $end = -1, $bybit = false): \Redis|false|int + { + return $this->initializeLazyObject()->bitpos(...\func_get_args()); + } + + public function blPop($key_or_keys, $timeout_or_key, ...$extra_args): \Redis|array|false|null + { + return $this->initializeLazyObject()->blPop(...\func_get_args()); + } + + public function brPop($key_or_keys, $timeout_or_key, ...$extra_args): \Redis|array|false|null + { + return $this->initializeLazyObject()->brPop(...\func_get_args()); + } + + public function brpoplpush($src, $dst, $timeout): \Redis|false|string + { + return $this->initializeLazyObject()->brpoplpush(...\func_get_args()); + } + + public function bzPopMax($key, $timeout_or_key, ...$extra_args): \Redis|array|false + { + return $this->initializeLazyObject()->bzPopMax(...\func_get_args()); + } + + public function bzPopMin($key, $timeout_or_key, ...$extra_args): \Redis|array|false + { + return $this->initializeLazyObject()->bzPopMin(...\func_get_args()); + } + + public function bzmpop($timeout, $keys, $from, $count = 1): \Redis|array|false|null + { + return $this->initializeLazyObject()->bzmpop(...\func_get_args()); + } + + public function zmpop($keys, $from, $count = 1): \Redis|array|false|null + { + return $this->initializeLazyObject()->zmpop(...\func_get_args()); + } + + public function blmpop($timeout, $keys, $from, $count = 1): \Redis|array|false|null + { + return $this->initializeLazyObject()->blmpop(...\func_get_args()); + } + + public function lmpop($keys, $from, $count = 1): \Redis|array|false|null + { + return $this->initializeLazyObject()->lmpop(...\func_get_args()); + } + + public function clearLastError(): bool + { + return $this->initializeLazyObject()->clearLastError(...\func_get_args()); + } + + public function client($opt, ...$args): mixed + { + return $this->initializeLazyObject()->client(...\func_get_args()); + } + + public function close(): bool + { + return $this->initializeLazyObject()->close(...\func_get_args()); + } + + public function command($opt = null, ...$args): mixed + { + return $this->initializeLazyObject()->command(...\func_get_args()); + } + + public function config($operation, $key_or_settings = null, $value = null): mixed + { + return $this->initializeLazyObject()->config(...\func_get_args()); + } + + public function connect($host, $port = 6379, $timeout = 0, $persistent_id = null, $retry_interval = 0, $read_timeout = 0, $context = null): bool + { + return $this->initializeLazyObject()->connect(...\func_get_args()); + } + + public function copy($src, $dst, $options = null): \Redis|bool + { + return $this->initializeLazyObject()->copy(...\func_get_args()); + } + + public function dbSize(): \Redis|false|int + { + return $this->initializeLazyObject()->dbSize(...\func_get_args()); + } + + public function debug($key): \Redis|string + { + return $this->initializeLazyObject()->debug(...\func_get_args()); + } + + public function decr($key, $by = 1): \Redis|false|int + { + return $this->initializeLazyObject()->decr(...\func_get_args()); + } + + public function decrBy($key, $value): \Redis|false|int + { + return $this->initializeLazyObject()->decrBy(...\func_get_args()); + } + + public function del($key, ...$other_keys): \Redis|false|int + { + return $this->initializeLazyObject()->del(...\func_get_args()); + } + + public function delete($key, ...$other_keys): \Redis|false|int + { + return $this->initializeLazyObject()->delete(...\func_get_args()); + } + + public function discard(): \Redis|bool + { + return $this->initializeLazyObject()->discard(...\func_get_args()); + } + + public function echo($str): \Redis|false|string + { + return $this->initializeLazyObject()->echo(...\func_get_args()); + } + + public function eval($script, $args = [], $num_keys = 0): mixed + { + return $this->initializeLazyObject()->eval(...\func_get_args()); + } + + public function eval_ro($script_sha, $args = [], $num_keys = 0): mixed + { + return $this->initializeLazyObject()->eval_ro(...\func_get_args()); + } + + public function evalsha($sha1, $args = [], $num_keys = 0): mixed + { + return $this->initializeLazyObject()->evalsha(...\func_get_args()); + } + + public function evalsha_ro($sha1, $args = [], $num_keys = 0): mixed + { + return $this->initializeLazyObject()->evalsha_ro(...\func_get_args()); + } + + public function exec(): \Redis|array|false + { + return $this->initializeLazyObject()->exec(...\func_get_args()); + } + + public function exists($key, ...$other_keys): \Redis|bool|int + { + return $this->initializeLazyObject()->exists(...\func_get_args()); + } + + public function expire($key, $timeout, $mode = null): \Redis|bool + { + return $this->initializeLazyObject()->expire(...\func_get_args()); + } + + public function expireAt($key, $timestamp, $mode = null): \Redis|bool + { + return $this->initializeLazyObject()->expireAt(...\func_get_args()); + } + + public function failover($to = null, $abort = false, $timeout = 0): \Redis|bool + { + return $this->initializeLazyObject()->failover(...\func_get_args()); + } + + public function expiretime($key): \Redis|false|int + { + return $this->initializeLazyObject()->expiretime(...\func_get_args()); + } + + public function pexpiretime($key): \Redis|false|int + { + return $this->initializeLazyObject()->pexpiretime(...\func_get_args()); + } + + public function fcall($fn, $keys = [], $args = []): mixed + { + return $this->initializeLazyObject()->fcall(...\func_get_args()); + } + + public function fcall_ro($fn, $keys = [], $args = []): mixed + { + return $this->initializeLazyObject()->fcall_ro(...\func_get_args()); + } + + public function flushAll($sync = null): \Redis|bool + { + return $this->initializeLazyObject()->flushAll(...\func_get_args()); + } + + public function flushDB($sync = null): \Redis|bool + { + return $this->initializeLazyObject()->flushDB(...\func_get_args()); + } + + public function function($operation, ...$args): \Redis|array|bool|string + { + return $this->initializeLazyObject()->function(...\func_get_args()); + } + + public function geoadd($key, $lng, $lat, $member, ...$other_triples_and_options): \Redis|false|int + { + return $this->initializeLazyObject()->geoadd(...\func_get_args()); + } + + public function geodist($key, $src, $dst, $unit = null): \Redis|false|float + { + return $this->initializeLazyObject()->geodist(...\func_get_args()); + } + + public function geohash($key, $member, ...$other_members): \Redis|array|false + { + return $this->initializeLazyObject()->geohash(...\func_get_args()); + } + + public function geopos($key, $member, ...$other_members): \Redis|array|false + { + return $this->initializeLazyObject()->geopos(...\func_get_args()); + } + + public function georadius($key, $lng, $lat, $radius, $unit, $options = []): mixed + { + return $this->initializeLazyObject()->georadius(...\func_get_args()); + } + + public function georadius_ro($key, $lng, $lat, $radius, $unit, $options = []): mixed + { + return $this->initializeLazyObject()->georadius_ro(...\func_get_args()); + } + + public function georadiusbymember($key, $member, $radius, $unit, $options = []): mixed + { + return $this->initializeLazyObject()->georadiusbymember(...\func_get_args()); + } + + public function georadiusbymember_ro($key, $member, $radius, $unit, $options = []): mixed + { + return $this->initializeLazyObject()->georadiusbymember_ro(...\func_get_args()); + } + + public function geosearch($key, $position, $shape, $unit, $options = []): array + { + return $this->initializeLazyObject()->geosearch(...\func_get_args()); + } + + public function geosearchstore($dst, $src, $position, $shape, $unit, $options = []): \Redis|array|false|int + { + return $this->initializeLazyObject()->geosearchstore(...\func_get_args()); + } + + public function get($key): mixed + { + return $this->initializeLazyObject()->get(...\func_get_args()); + } + + public function getAuth(): mixed + { + return $this->initializeLazyObject()->getAuth(...\func_get_args()); + } + + public function getBit($key, $idx): \Redis|false|int + { + return $this->initializeLazyObject()->getBit(...\func_get_args()); + } + + public function getEx($key, $options = []): \Redis|bool|string + { + return $this->initializeLazyObject()->getEx(...\func_get_args()); + } + + public function getDBNum(): int + { + return $this->initializeLazyObject()->getDBNum(...\func_get_args()); + } + + public function getDel($key): \Redis|bool|string + { + return $this->initializeLazyObject()->getDel(...\func_get_args()); + } + + public function getHost(): string + { + return $this->initializeLazyObject()->getHost(...\func_get_args()); + } + + public function getLastError(): ?string + { + return $this->initializeLazyObject()->getLastError(...\func_get_args()); + } + + public function getMode(): int + { + return $this->initializeLazyObject()->getMode(...\func_get_args()); + } + + public function getOption($option): mixed + { + return $this->initializeLazyObject()->getOption(...\func_get_args()); + } + + public function getPersistentID(): ?string + { + return $this->initializeLazyObject()->getPersistentID(...\func_get_args()); + } + + public function getPort(): int + { + return $this->initializeLazyObject()->getPort(...\func_get_args()); + } + + public function getRange($key, $start, $end): \Redis|false|string + { + return $this->initializeLazyObject()->getRange(...\func_get_args()); + } + + public function lcs($key1, $key2, $options = null): \Redis|array|false|int|string + { + return $this->initializeLazyObject()->lcs(...\func_get_args()); + } + + public function getReadTimeout(): float + { + return $this->initializeLazyObject()->getReadTimeout(...\func_get_args()); + } + + public function getset($key, $value): \Redis|false|string + { + return $this->initializeLazyObject()->getset(...\func_get_args()); + } + + public function getTimeout(): false|float + { + return $this->initializeLazyObject()->getTimeout(...\func_get_args()); + } + + public function getTransferredBytes(): array + { + return $this->initializeLazyObject()->getTransferredBytes(...\func_get_args()); + } + + public function clearTransferredBytes(): void + { + $this->initializeLazyObject()->clearTransferredBytes(...\func_get_args()); + } + + public function hDel($key, $field, ...$other_fields): \Redis|false|int + { + return $this->initializeLazyObject()->hDel(...\func_get_args()); + } + + public function hExists($key, $field): \Redis|bool + { + return $this->initializeLazyObject()->hExists(...\func_get_args()); + } + + public function hGet($key, $member): mixed + { + return $this->initializeLazyObject()->hGet(...\func_get_args()); + } + + public function hGetAll($key): \Redis|array|false + { + return $this->initializeLazyObject()->hGetAll(...\func_get_args()); + } + + public function hIncrBy($key, $field, $value): \Redis|false|int + { + return $this->initializeLazyObject()->hIncrBy(...\func_get_args()); + } + + public function hIncrByFloat($key, $field, $value): \Redis|false|float + { + return $this->initializeLazyObject()->hIncrByFloat(...\func_get_args()); + } + + public function hKeys($key): \Redis|array|false + { + return $this->initializeLazyObject()->hKeys(...\func_get_args()); + } + + public function hLen($key): \Redis|false|int + { + return $this->initializeLazyObject()->hLen(...\func_get_args()); + } + + public function hMget($key, $fields): \Redis|array|false + { + return $this->initializeLazyObject()->hMget(...\func_get_args()); + } + + public function hMset($key, $fieldvals): \Redis|bool + { + return $this->initializeLazyObject()->hMset(...\func_get_args()); + } + + public function hSetNx($key, $field, $value): \Redis|bool + { + return $this->initializeLazyObject()->hSetNx(...\func_get_args()); + } + + public function hStrLen($key, $field): \Redis|false|int + { + return $this->initializeLazyObject()->hStrLen(...\func_get_args()); + } + + public function hVals($key): \Redis|array|false + { + return $this->initializeLazyObject()->hVals(...\func_get_args()); + } + + public function hscan($key, &$iterator, $pattern = null, $count = 0): \Redis|array|bool + { + return $this->initializeLazyObject()->hscan($key, $iterator, ...\array_slice(\func_get_args(), 2)); + } + + public function incr($key, $by = 1): \Redis|false|int + { + return $this->initializeLazyObject()->incr(...\func_get_args()); + } + + public function incrBy($key, $value): \Redis|false|int + { + return $this->initializeLazyObject()->incrBy(...\func_get_args()); + } + + public function incrByFloat($key, $value): \Redis|false|float + { + return $this->initializeLazyObject()->incrByFloat(...\func_get_args()); + } + + public function info(...$sections): \Redis|array|false + { + return $this->initializeLazyObject()->info(...\func_get_args()); + } + + public function isConnected(): bool + { + return $this->initializeLazyObject()->isConnected(...\func_get_args()); + } + + public function keys($pattern) + { + return $this->initializeLazyObject()->keys(...\func_get_args()); + } + + public function lInsert($key, $pos, $pivot, $value) + { + return $this->initializeLazyObject()->lInsert(...\func_get_args()); + } + + public function lLen($key): \Redis|false|int + { + return $this->initializeLazyObject()->lLen(...\func_get_args()); + } + + public function lMove($src, $dst, $wherefrom, $whereto): \Redis|false|string + { + return $this->initializeLazyObject()->lMove(...\func_get_args()); + } + + public function blmove($src, $dst, $wherefrom, $whereto, $timeout): \Redis|false|string + { + return $this->initializeLazyObject()->blmove(...\func_get_args()); + } + + public function lPop($key, $count = 0): \Redis|array|bool|string + { + return $this->initializeLazyObject()->lPop(...\func_get_args()); + } + + public function lPos($key, $value, $options = null): \Redis|array|bool|int|null + { + return $this->initializeLazyObject()->lPos(...\func_get_args()); + } + + public function lPush($key, ...$elements): \Redis|false|int + { + return $this->initializeLazyObject()->lPush(...\func_get_args()); + } + + public function rPush($key, ...$elements): \Redis|false|int + { + return $this->initializeLazyObject()->rPush(...\func_get_args()); + } + + public function lPushx($key, $value): \Redis|false|int + { + return $this->initializeLazyObject()->lPushx(...\func_get_args()); + } + + public function rPushx($key, $value): \Redis|false|int + { + return $this->initializeLazyObject()->rPushx(...\func_get_args()); + } + + public function lSet($key, $index, $value): \Redis|bool + { + return $this->initializeLazyObject()->lSet(...\func_get_args()); + } + + public function lastSave(): int + { + return $this->initializeLazyObject()->lastSave(...\func_get_args()); + } + + public function lindex($key, $index): mixed + { + return $this->initializeLazyObject()->lindex(...\func_get_args()); + } + + public function lrange($key, $start, $end): \Redis|array|false + { + return $this->initializeLazyObject()->lrange(...\func_get_args()); + } + + public function lrem($key, $value, $count = 0): \Redis|false|int + { + return $this->initializeLazyObject()->lrem(...\func_get_args()); + } + + public function ltrim($key, $start, $end): \Redis|bool + { + return $this->initializeLazyObject()->ltrim(...\func_get_args()); + } + + public function migrate($host, $port, $key, $dstdb, $timeout, $copy = false, $replace = false, #[\SensitiveParameter] $credentials = null): \Redis|bool + { + return $this->initializeLazyObject()->migrate(...\func_get_args()); + } + + public function move($key, $index): \Redis|bool + { + return $this->initializeLazyObject()->move(...\func_get_args()); + } + + public function mset($key_values): \Redis|bool + { + return $this->initializeLazyObject()->mset(...\func_get_args()); + } + + public function msetnx($key_values): \Redis|bool + { + return $this->initializeLazyObject()->msetnx(...\func_get_args()); + } + + public function multi($value = \Redis::MULTI): \Redis|bool + { + return $this->initializeLazyObject()->multi(...\func_get_args()); + } + + public function object($subcommand, $key): \Redis|false|int|string + { + return $this->initializeLazyObject()->object(...\func_get_args()); + } + + public function open($host, $port = 6379, $timeout = 0, $persistent_id = null, $retry_interval = 0, $read_timeout = 0, $context = null): bool + { + return $this->initializeLazyObject()->open(...\func_get_args()); + } + + public function pconnect($host, $port = 6379, $timeout = 0, $persistent_id = null, $retry_interval = 0, $read_timeout = 0, $context = null): bool + { + return $this->initializeLazyObject()->pconnect(...\func_get_args()); + } + + public function persist($key): \Redis|bool + { + return $this->initializeLazyObject()->persist(...\func_get_args()); + } + + public function pexpire($key, $timeout, $mode = null): bool + { + return $this->initializeLazyObject()->pexpire(...\func_get_args()); + } + + public function pexpireAt($key, $timestamp, $mode = null): \Redis|bool + { + return $this->initializeLazyObject()->pexpireAt(...\func_get_args()); + } + + public function pfadd($key, $elements): \Redis|int + { + return $this->initializeLazyObject()->pfadd(...\func_get_args()); + } + + public function pfcount($key_or_keys): \Redis|false|int + { + return $this->initializeLazyObject()->pfcount(...\func_get_args()); + } + + public function pfmerge($dst, $srckeys): \Redis|bool + { + return $this->initializeLazyObject()->pfmerge(...\func_get_args()); + } + + public function ping($message = null): \Redis|bool|string + { + return $this->initializeLazyObject()->ping(...\func_get_args()); + } + + public function pipeline(): \Redis|bool + { + return $this->initializeLazyObject()->pipeline(...\func_get_args()); + } + + public function popen($host, $port = 6379, $timeout = 0, $persistent_id = null, $retry_interval = 0, $read_timeout = 0, $context = null): bool + { + return $this->initializeLazyObject()->popen(...\func_get_args()); + } + + public function psetex($key, $expire, $value): \Redis|bool + { + return $this->initializeLazyObject()->psetex(...\func_get_args()); + } + + public function psubscribe($patterns, $cb): bool + { + return $this->initializeLazyObject()->psubscribe(...\func_get_args()); + } + + public function pttl($key): \Redis|false|int + { + return $this->initializeLazyObject()->pttl(...\func_get_args()); + } + + public function publish($channel, $message): \Redis|false|int + { + return $this->initializeLazyObject()->publish(...\func_get_args()); + } + + public function pubsub($command, $arg = null): mixed + { + return $this->initializeLazyObject()->pubsub(...\func_get_args()); + } + + public function punsubscribe($patterns): \Redis|array|bool + { + return $this->initializeLazyObject()->punsubscribe(...\func_get_args()); + } + + public function rPop($key, $count = 0): \Redis|array|bool|string + { + return $this->initializeLazyObject()->rPop(...\func_get_args()); + } + + public function randomKey(): \Redis|false|string + { + return $this->initializeLazyObject()->randomKey(...\func_get_args()); + } + + public function rawcommand($command, ...$args): mixed + { + return $this->initializeLazyObject()->rawcommand(...\func_get_args()); + } + + public function rename($old_name, $new_name): \Redis|bool + { + return $this->initializeLazyObject()->rename(...\func_get_args()); + } + + public function renameNx($key_src, $key_dst): \Redis|bool + { + return $this->initializeLazyObject()->renameNx(...\func_get_args()); + } + + public function restore($key, $ttl, $value, $options = null): \Redis|bool + { + return $this->initializeLazyObject()->restore(...\func_get_args()); + } + + public function role(): mixed + { + return $this->initializeLazyObject()->role(...\func_get_args()); + } + + public function rpoplpush($srckey, $dstkey): \Redis|false|string + { + return $this->initializeLazyObject()->rpoplpush(...\func_get_args()); + } + + public function sAdd($key, $value, ...$other_values): \Redis|false|int + { + return $this->initializeLazyObject()->sAdd(...\func_get_args()); + } + + public function sAddArray($key, $values): int + { + return $this->initializeLazyObject()->sAddArray(...\func_get_args()); + } + + public function sDiff($key, ...$other_keys): \Redis|array|false + { + return $this->initializeLazyObject()->sDiff(...\func_get_args()); + } + + public function sDiffStore($dst, $key, ...$other_keys): \Redis|false|int + { + return $this->initializeLazyObject()->sDiffStore(...\func_get_args()); + } + + public function sInter($key, ...$other_keys): \Redis|array|false + { + return $this->initializeLazyObject()->sInter(...\func_get_args()); + } + + public function sintercard($keys, $limit = -1): \Redis|false|int + { + return $this->initializeLazyObject()->sintercard(...\func_get_args()); + } + + public function sInterStore($key, ...$other_keys): \Redis|false|int + { + return $this->initializeLazyObject()->sInterStore(...\func_get_args()); + } + + public function sMembers($key): \Redis|array|false + { + return $this->initializeLazyObject()->sMembers(...\func_get_args()); + } + + public function sMisMember($key, $member, ...$other_members): \Redis|array|false + { + return $this->initializeLazyObject()->sMisMember(...\func_get_args()); + } + + public function sMove($src, $dst, $value): \Redis|bool + { + return $this->initializeLazyObject()->sMove(...\func_get_args()); + } + + public function sPop($key, $count = 0): \Redis|array|false|string + { + return $this->initializeLazyObject()->sPop(...\func_get_args()); + } + + public function sUnion($key, ...$other_keys): \Redis|array|false + { + return $this->initializeLazyObject()->sUnion(...\func_get_args()); + } + + public function sUnionStore($dst, $key, ...$other_keys): \Redis|false|int + { + return $this->initializeLazyObject()->sUnionStore(...\func_get_args()); + } + + public function save(): \Redis|bool + { + return $this->initializeLazyObject()->save(...\func_get_args()); + } + + public function scan(&$iterator, $pattern = null, $count = 0, $type = null): array|false + { + return $this->initializeLazyObject()->scan($iterator, ...\array_slice(\func_get_args(), 1)); + } + + public function scard($key): \Redis|false|int + { + return $this->initializeLazyObject()->scard(...\func_get_args()); + } + + public function script($command, ...$args): mixed + { + return $this->initializeLazyObject()->script(...\func_get_args()); + } + + public function select($db): \Redis|bool + { + return $this->initializeLazyObject()->select(...\func_get_args()); + } + + public function set($key, $value, $options = null): \Redis|bool|string + { + return $this->initializeLazyObject()->set(...\func_get_args()); + } + + public function setBit($key, $idx, $value): \Redis|false|int + { + return $this->initializeLazyObject()->setBit(...\func_get_args()); + } + + public function setRange($key, $index, $value): \Redis|false|int + { + return $this->initializeLazyObject()->setRange(...\func_get_args()); + } + + public function setOption($option, $value): bool + { + return $this->initializeLazyObject()->setOption(...\func_get_args()); + } + + public function setex($key, $expire, $value) + { + return $this->initializeLazyObject()->setex(...\func_get_args()); + } + + public function setnx($key, $value): \Redis|bool + { + return $this->initializeLazyObject()->setnx(...\func_get_args()); + } + + public function sismember($key, $value): \Redis|bool + { + return $this->initializeLazyObject()->sismember(...\func_get_args()); + } + + public function slaveof($host = null, $port = 6379): \Redis|bool + { + return $this->initializeLazyObject()->slaveof(...\func_get_args()); + } + + public function replicaof($host = null, $port = 6379): \Redis|bool + { + return $this->initializeLazyObject()->replicaof(...\func_get_args()); + } + + public function touch($key_or_array, ...$more_keys): \Redis|false|int + { + return $this->initializeLazyObject()->touch(...\func_get_args()); + } + + public function slowlog($operation, $length = 0): mixed + { + return $this->initializeLazyObject()->slowlog(...\func_get_args()); + } + + public function sort($key, $options = null): mixed + { + return $this->initializeLazyObject()->sort(...\func_get_args()); + } + + public function sort_ro($key, $options = null): mixed + { + return $this->initializeLazyObject()->sort_ro(...\func_get_args()); + } + + public function sortAsc($key, $pattern = null, $get = null, $offset = -1, $count = -1, $store = null): array + { + return $this->initializeLazyObject()->sortAsc(...\func_get_args()); + } + + public function sortAscAlpha($key, $pattern = null, $get = null, $offset = -1, $count = -1, $store = null): array + { + return $this->initializeLazyObject()->sortAscAlpha(...\func_get_args()); + } + + public function sortDesc($key, $pattern = null, $get = null, $offset = -1, $count = -1, $store = null): array + { + return $this->initializeLazyObject()->sortDesc(...\func_get_args()); + } + + public function sortDescAlpha($key, $pattern = null, $get = null, $offset = -1, $count = -1, $store = null): array + { + return $this->initializeLazyObject()->sortDescAlpha(...\func_get_args()); + } + + public function srem($key, $value, ...$other_values): \Redis|false|int + { + return $this->initializeLazyObject()->srem(...\func_get_args()); + } + + public function sscan($key, &$iterator, $pattern = null, $count = 0): array|false + { + return $this->initializeLazyObject()->sscan($key, $iterator, ...\array_slice(\func_get_args(), 2)); + } + + public function ssubscribe($channels, $cb): bool + { + return $this->initializeLazyObject()->ssubscribe(...\func_get_args()); + } + + public function strlen($key): \Redis|false|int + { + return $this->initializeLazyObject()->strlen(...\func_get_args()); + } + + public function subscribe($channels, $cb): bool + { + return $this->initializeLazyObject()->subscribe(...\func_get_args()); + } + + public function sunsubscribe($channels): \Redis|array|bool + { + return $this->initializeLazyObject()->sunsubscribe(...\func_get_args()); + } + + public function swapdb($src, $dst): \Redis|bool + { + return $this->initializeLazyObject()->swapdb(...\func_get_args()); + } + + public function time(): \Redis|array + { + return $this->initializeLazyObject()->time(...\func_get_args()); + } + + public function ttl($key): \Redis|false|int + { + return $this->initializeLazyObject()->ttl(...\func_get_args()); + } + + public function type($key): \Redis|false|int + { + return $this->initializeLazyObject()->type(...\func_get_args()); + } + + public function unlink($key, ...$other_keys): \Redis|false|int + { + return $this->initializeLazyObject()->unlink(...\func_get_args()); + } + + public function unsubscribe($channels): \Redis|array|bool + { + return $this->initializeLazyObject()->unsubscribe(...\func_get_args()); + } + + public function unwatch(): \Redis|bool + { + return $this->initializeLazyObject()->unwatch(...\func_get_args()); + } + + public function watch($key, ...$other_keys): \Redis|bool + { + return $this->initializeLazyObject()->watch(...\func_get_args()); + } + + public function wait($numreplicas, $timeout): false|int + { + return $this->initializeLazyObject()->wait(...\func_get_args()); + } + + public function xack($key, $group, $ids): false|int + { + return $this->initializeLazyObject()->xack(...\func_get_args()); + } + + public function xadd($key, $id, $values, $maxlen = 0, $approx = false, $nomkstream = false): \Redis|false|string + { + return $this->initializeLazyObject()->xadd(...\func_get_args()); + } + + public function xautoclaim($key, $group, $consumer, $min_idle, $start, $count = -1, $justid = false): \Redis|array|bool + { + return $this->initializeLazyObject()->xautoclaim(...\func_get_args()); + } + + public function xclaim($key, $group, $consumer, $min_idle, $ids, $options): \Redis|array|bool + { + return $this->initializeLazyObject()->xclaim(...\func_get_args()); + } + + public function xdel($key, $ids): \Redis|false|int + { + return $this->initializeLazyObject()->xdel(...\func_get_args()); + } + + public function xgroup($operation, $key = null, $group = null, $id_or_consumer = null, $mkstream = false, $entries_read = -2): mixed + { + return $this->initializeLazyObject()->xgroup(...\func_get_args()); + } + + public function xinfo($operation, $arg1 = null, $arg2 = null, $count = -1): mixed + { + return $this->initializeLazyObject()->xinfo(...\func_get_args()); + } + + public function xlen($key): \Redis|false|int + { + return $this->initializeLazyObject()->xlen(...\func_get_args()); + } + + public function xpending($key, $group, $start = null, $end = null, $count = -1, $consumer = null): \Redis|array|false + { + return $this->initializeLazyObject()->xpending(...\func_get_args()); + } + + public function xrange($key, $start, $end, $count = -1): \Redis|array|bool + { + return $this->initializeLazyObject()->xrange(...\func_get_args()); + } + + public function xread($streams, $count = -1, $block = -1): \Redis|array|bool + { + return $this->initializeLazyObject()->xread(...\func_get_args()); + } + + public function xreadgroup($group, $consumer, $streams, $count = 1, $block = 1): \Redis|array|bool + { + return $this->initializeLazyObject()->xreadgroup(...\func_get_args()); + } + + public function xrevrange($key, $end, $start, $count = -1): \Redis|array|bool + { + return $this->initializeLazyObject()->xrevrange(...\func_get_args()); + } + + public function xtrim($key, $threshold, $approx = false, $minid = false, $limit = -1): \Redis|false|int + { + return $this->initializeLazyObject()->xtrim(...\func_get_args()); + } + + public function zAdd($key, $score_or_options, ...$more_scores_and_mems): \Redis|false|float|int + { + return $this->initializeLazyObject()->zAdd(...\func_get_args()); + } + + public function zCard($key): \Redis|false|int + { + return $this->initializeLazyObject()->zCard(...\func_get_args()); + } + + public function zCount($key, $start, $end): \Redis|false|int + { + return $this->initializeLazyObject()->zCount(...\func_get_args()); + } + + public function zIncrBy($key, $value, $member): \Redis|false|float + { + return $this->initializeLazyObject()->zIncrBy(...\func_get_args()); + } + + public function zLexCount($key, $min, $max): \Redis|false|int + { + return $this->initializeLazyObject()->zLexCount(...\func_get_args()); + } + + public function zMscore($key, $member, ...$other_members): \Redis|array|false + { + return $this->initializeLazyObject()->zMscore(...\func_get_args()); + } + + public function zPopMax($key, $count = null): \Redis|array|false + { + return $this->initializeLazyObject()->zPopMax(...\func_get_args()); + } + + public function zPopMin($key, $count = null): \Redis|array|false + { + return $this->initializeLazyObject()->zPopMin(...\func_get_args()); + } + + public function zRange($key, $start, $end, $options = null): \Redis|array|false + { + return $this->initializeLazyObject()->zRange(...\func_get_args()); + } + + public function zRangeByLex($key, $min, $max, $offset = -1, $count = -1): \Redis|array|false + { + return $this->initializeLazyObject()->zRangeByLex(...\func_get_args()); + } + + public function zRangeByScore($key, $start, $end, $options = []): \Redis|array|false + { + return $this->initializeLazyObject()->zRangeByScore(...\func_get_args()); + } + + public function zrangestore($dstkey, $srckey, $start, $end, $options = null): \Redis|false|int + { + return $this->initializeLazyObject()->zrangestore(...\func_get_args()); + } + + public function zRandMember($key, $options = null): \Redis|array|string + { + return $this->initializeLazyObject()->zRandMember(...\func_get_args()); + } + + public function zRank($key, $member): \Redis|false|int + { + return $this->initializeLazyObject()->zRank(...\func_get_args()); + } + + public function zRem($key, $member, ...$other_members): \Redis|false|int + { + return $this->initializeLazyObject()->zRem(...\func_get_args()); + } + + public function zRemRangeByLex($key, $min, $max): \Redis|false|int + { + return $this->initializeLazyObject()->zRemRangeByLex(...\func_get_args()); + } + + public function zRemRangeByRank($key, $start, $end): \Redis|false|int + { + return $this->initializeLazyObject()->zRemRangeByRank(...\func_get_args()); + } + + public function zRemRangeByScore($key, $start, $end): \Redis|false|int + { + return $this->initializeLazyObject()->zRemRangeByScore(...\func_get_args()); + } + + public function zRevRange($key, $start, $end, $scores = null): \Redis|array|false + { + return $this->initializeLazyObject()->zRevRange(...\func_get_args()); + } + + public function zRevRangeByLex($key, $max, $min, $offset = -1, $count = -1): \Redis|array|false + { + return $this->initializeLazyObject()->zRevRangeByLex(...\func_get_args()); + } + + public function zRevRangeByScore($key, $max, $min, $options = []): \Redis|array|false + { + return $this->initializeLazyObject()->zRevRangeByScore(...\func_get_args()); + } + + public function zRevRank($key, $member): \Redis|false|int + { + return $this->initializeLazyObject()->zRevRank(...\func_get_args()); + } + + public function zScore($key, $member): \Redis|false|float + { + return $this->initializeLazyObject()->zScore(...\func_get_args()); + } + + public function zdiff($keys, $options = null): \Redis|array|false + { + return $this->initializeLazyObject()->zdiff(...\func_get_args()); + } + + public function zdiffstore($dst, $keys): \Redis|false|int + { + return $this->initializeLazyObject()->zdiffstore(...\func_get_args()); + } + + public function zinter($keys, $weights = null, $options = null): \Redis|array|false + { + return $this->initializeLazyObject()->zinter(...\func_get_args()); + } + + public function zintercard($keys, $limit = -1): \Redis|false|int + { + return $this->initializeLazyObject()->zintercard(...\func_get_args()); + } + + public function zinterstore($dst, $keys, $weights = null, $aggregate = null): \Redis|false|int + { + return $this->initializeLazyObject()->zinterstore(...\func_get_args()); + } + + public function zscan($key, &$iterator, $pattern = null, $count = 0): \Redis|array|false + { + return $this->initializeLazyObject()->zscan($key, $iterator, ...\array_slice(\func_get_args(), 2)); + } + + public function zunion($keys, $weights = null, $options = null): \Redis|array|false + { + return $this->initializeLazyObject()->zunion(...\func_get_args()); + } + + public function zunionstore($dst, $keys, $weights = null, $aggregate = null): \Redis|false|int + { + return $this->initializeLazyObject()->zunionstore(...\func_get_args()); + } +} diff --git a/vendor/symfony/cache/Traits/Redis6ProxyTrait.php b/vendor/symfony/cache/Traits/Redis6ProxyTrait.php new file mode 100644 index 0000000..bb8d978 --- /dev/null +++ b/vendor/symfony/cache/Traits/Redis6ProxyTrait.php @@ -0,0 +1,81 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Traits; + +if (version_compare(phpversion('redis'), '6.1.0-dev', '>=')) { + /** + * @internal + */ + trait Redis6ProxyTrait + { + public function dump($key): \Redis|string|false + { + return $this->initializeLazyObject()->dump(...\func_get_args()); + } + + public function hRandField($key, $options = null): \Redis|array|string|false + { + return $this->initializeLazyObject()->hRandField(...\func_get_args()); + } + + public function hSet($key, ...$fields_and_vals): \Redis|false|int + { + return $this->initializeLazyObject()->hSet(...\func_get_args()); + } + + public function mget($keys): \Redis|array|false + { + return $this->initializeLazyObject()->mget(...\func_get_args()); + } + + public function sRandMember($key, $count = 0): mixed + { + return $this->initializeLazyObject()->sRandMember(...\func_get_args()); + } + + public function waitaof($numlocal, $numreplicas, $timeout): \Redis|array|false + { + return $this->initializeLazyObject()->waitaof(...\func_get_args()); + } + } +} else { + /** + * @internal + */ + trait Redis6ProxyTrait + { + public function dump($key): \Redis|string + { + return $this->initializeLazyObject()->dump(...\func_get_args()); + } + + public function hRandField($key, $options = null): \Redis|array|string + { + return $this->initializeLazyObject()->hRandField(...\func_get_args()); + } + + public function hSet($key, $member, $value): \Redis|false|int + { + return $this->initializeLazyObject()->hSet(...\func_get_args()); + } + + public function mget($keys): \Redis|array + { + return $this->initializeLazyObject()->mget(...\func_get_args()); + } + + public function sRandMember($key, $count = 0): \Redis|array|false|string + { + return $this->initializeLazyObject()->sRandMember(...\func_get_args()); + } + } +} diff --git a/vendor/symfony/cache/Traits/RedisCluster5Proxy.php b/vendor/symfony/cache/Traits/RedisCluster5Proxy.php new file mode 100644 index 0000000..43f3404 --- /dev/null +++ b/vendor/symfony/cache/Traits/RedisCluster5Proxy.php @@ -0,0 +1,980 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Traits; + +use Symfony\Component\VarExporter\LazyObjectInterface; +use Symfony\Contracts\Service\ResetInterface; + +// Help opcache.preload discover always-needed symbols +class_exists(\Symfony\Component\VarExporter\Internal\Hydrator::class); +class_exists(\Symfony\Component\VarExporter\Internal\LazyObjectRegistry::class); +class_exists(\Symfony\Component\VarExporter\Internal\LazyObjectState::class); + +/** + * @internal + */ +class RedisCluster5Proxy extends \RedisCluster implements ResetInterface, LazyObjectInterface +{ + use RedisProxyTrait { + resetLazyObject as reset; + } + + public function __construct($name, $seeds = null, $timeout = null, $read_timeout = null, $persistent = null, #[\SensitiveParameter] $auth = null) + { + $this->initializeLazyObject()->__construct(...\func_get_args()); + } + + public function _masters() + { + return $this->initializeLazyObject()->_masters(...\func_get_args()); + } + + public function _prefix($key) + { + return $this->initializeLazyObject()->_prefix(...\func_get_args()); + } + + public function _redir() + { + return $this->initializeLazyObject()->_redir(...\func_get_args()); + } + + public function _serialize($value) + { + return $this->initializeLazyObject()->_serialize(...\func_get_args()); + } + + public function _unserialize($value) + { + return $this->initializeLazyObject()->_unserialize(...\func_get_args()); + } + + public function _compress($value) + { + return $this->initializeLazyObject()->_compress(...\func_get_args()); + } + + public function _uncompress($value) + { + return $this->initializeLazyObject()->_uncompress(...\func_get_args()); + } + + public function _pack($value) + { + return $this->initializeLazyObject()->_pack(...\func_get_args()); + } + + public function _unpack($value) + { + return $this->initializeLazyObject()->_unpack(...\func_get_args()); + } + + public function acl($key_or_address, $subcmd, ...$args) + { + return $this->initializeLazyObject()->acl(...\func_get_args()); + } + + public function append($key, $value) + { + return $this->initializeLazyObject()->append(...\func_get_args()); + } + + public function bgrewriteaof($key_or_address) + { + return $this->initializeLazyObject()->bgrewriteaof(...\func_get_args()); + } + + public function bgsave($key_or_address) + { + return $this->initializeLazyObject()->bgsave(...\func_get_args()); + } + + public function bitcount($key) + { + return $this->initializeLazyObject()->bitcount(...\func_get_args()); + } + + public function bitop($operation, $ret_key, $key, ...$other_keys) + { + return $this->initializeLazyObject()->bitop(...\func_get_args()); + } + + public function bitpos($key, $bit, $start = null, $end = null) + { + return $this->initializeLazyObject()->bitpos(...\func_get_args()); + } + + public function blpop($key, $timeout_or_key, ...$extra_args) + { + return $this->initializeLazyObject()->blpop(...\func_get_args()); + } + + public function brpop($key, $timeout_or_key, ...$extra_args) + { + return $this->initializeLazyObject()->brpop(...\func_get_args()); + } + + public function brpoplpush($src, $dst, $timeout) + { + return $this->initializeLazyObject()->brpoplpush(...\func_get_args()); + } + + public function clearlasterror() + { + return $this->initializeLazyObject()->clearlasterror(...\func_get_args()); + } + + public function bzpopmax($key, $timeout_or_key, ...$extra_args) + { + return $this->initializeLazyObject()->bzpopmax(...\func_get_args()); + } + + public function bzpopmin($key, $timeout_or_key, ...$extra_args) + { + return $this->initializeLazyObject()->bzpopmin(...\func_get_args()); + } + + public function client($key_or_address, $arg = null, ...$other_args) + { + return $this->initializeLazyObject()->client(...\func_get_args()); + } + + public function close() + { + return $this->initializeLazyObject()->close(...\func_get_args()); + } + + public function cluster($key_or_address, $arg = null, ...$other_args) + { + return $this->initializeLazyObject()->cluster(...\func_get_args()); + } + + public function command(...$args) + { + return $this->initializeLazyObject()->command(...\func_get_args()); + } + + public function config($key_or_address, $arg = null, ...$other_args) + { + return $this->initializeLazyObject()->config(...\func_get_args()); + } + + public function dbsize($key_or_address) + { + return $this->initializeLazyObject()->dbsize(...\func_get_args()); + } + + public function decr($key) + { + return $this->initializeLazyObject()->decr(...\func_get_args()); + } + + public function decrby($key, $value) + { + return $this->initializeLazyObject()->decrby(...\func_get_args()); + } + + public function del($key, ...$other_keys) + { + return $this->initializeLazyObject()->del(...\func_get_args()); + } + + public function discard() + { + return $this->initializeLazyObject()->discard(...\func_get_args()); + } + + public function dump($key) + { + return $this->initializeLazyObject()->dump(...\func_get_args()); + } + + public function echo($msg) + { + return $this->initializeLazyObject()->echo(...\func_get_args()); + } + + public function eval($script, $args = null, $num_keys = null) + { + return $this->initializeLazyObject()->eval(...\func_get_args()); + } + + public function evalsha($script_sha, $args = null, $num_keys = null) + { + return $this->initializeLazyObject()->evalsha(...\func_get_args()); + } + + public function exec() + { + return $this->initializeLazyObject()->exec(...\func_get_args()); + } + + public function exists($key) + { + return $this->initializeLazyObject()->exists(...\func_get_args()); + } + + public function expire($key, $timeout) + { + return $this->initializeLazyObject()->expire(...\func_get_args()); + } + + public function expireat($key, $timestamp) + { + return $this->initializeLazyObject()->expireat(...\func_get_args()); + } + + public function flushall($key_or_address, $async = null) + { + return $this->initializeLazyObject()->flushall(...\func_get_args()); + } + + public function flushdb($key_or_address, $async = null) + { + return $this->initializeLazyObject()->flushdb(...\func_get_args()); + } + + public function geoadd($key, $lng, $lat, $member, ...$other_triples) + { + return $this->initializeLazyObject()->geoadd(...\func_get_args()); + } + + public function geodist($key, $src, $dst, $unit = null) + { + return $this->initializeLazyObject()->geodist(...\func_get_args()); + } + + public function geohash($key, $member, ...$other_members) + { + return $this->initializeLazyObject()->geohash(...\func_get_args()); + } + + public function geopos($key, $member, ...$other_members) + { + return $this->initializeLazyObject()->geopos(...\func_get_args()); + } + + public function georadius($key, $lng, $lan, $radius, $unit, $opts = null) + { + return $this->initializeLazyObject()->georadius(...\func_get_args()); + } + + public function georadius_ro($key, $lng, $lan, $radius, $unit, $opts = null) + { + return $this->initializeLazyObject()->georadius_ro(...\func_get_args()); + } + + public function georadiusbymember($key, $member, $radius, $unit, $opts = null) + { + return $this->initializeLazyObject()->georadiusbymember(...\func_get_args()); + } + + public function georadiusbymember_ro($key, $member, $radius, $unit, $opts = null) + { + return $this->initializeLazyObject()->georadiusbymember_ro(...\func_get_args()); + } + + public function get($key) + { + return $this->initializeLazyObject()->get(...\func_get_args()); + } + + public function getbit($key, $offset) + { + return $this->initializeLazyObject()->getbit(...\func_get_args()); + } + + public function getlasterror() + { + return $this->initializeLazyObject()->getlasterror(...\func_get_args()); + } + + public function getmode() + { + return $this->initializeLazyObject()->getmode(...\func_get_args()); + } + + public function getoption($option) + { + return $this->initializeLazyObject()->getoption(...\func_get_args()); + } + + public function getrange($key, $start, $end) + { + return $this->initializeLazyObject()->getrange(...\func_get_args()); + } + + public function getset($key, $value) + { + return $this->initializeLazyObject()->getset(...\func_get_args()); + } + + public function hdel($key, $member, ...$other_members) + { + return $this->initializeLazyObject()->hdel(...\func_get_args()); + } + + public function hexists($key, $member) + { + return $this->initializeLazyObject()->hexists(...\func_get_args()); + } + + public function hget($key, $member) + { + return $this->initializeLazyObject()->hget(...\func_get_args()); + } + + public function hgetall($key) + { + return $this->initializeLazyObject()->hgetall(...\func_get_args()); + } + + public function hincrby($key, $member, $value) + { + return $this->initializeLazyObject()->hincrby(...\func_get_args()); + } + + public function hincrbyfloat($key, $member, $value) + { + return $this->initializeLazyObject()->hincrbyfloat(...\func_get_args()); + } + + public function hkeys($key) + { + return $this->initializeLazyObject()->hkeys(...\func_get_args()); + } + + public function hlen($key) + { + return $this->initializeLazyObject()->hlen(...\func_get_args()); + } + + public function hmget($key, $keys) + { + return $this->initializeLazyObject()->hmget(...\func_get_args()); + } + + public function hmset($key, $pairs) + { + return $this->initializeLazyObject()->hmset(...\func_get_args()); + } + + public function hscan($str_key, &$i_iterator, $str_pattern = null, $i_count = null) + { + return $this->initializeLazyObject()->hscan($str_key, $i_iterator, ...\array_slice(\func_get_args(), 2)); + } + + public function hset($key, $member, $value) + { + return $this->initializeLazyObject()->hset(...\func_get_args()); + } + + public function hsetnx($key, $member, $value) + { + return $this->initializeLazyObject()->hsetnx(...\func_get_args()); + } + + public function hstrlen($key, $member) + { + return $this->initializeLazyObject()->hstrlen(...\func_get_args()); + } + + public function hvals($key) + { + return $this->initializeLazyObject()->hvals(...\func_get_args()); + } + + public function incr($key) + { + return $this->initializeLazyObject()->incr(...\func_get_args()); + } + + public function incrby($key, $value) + { + return $this->initializeLazyObject()->incrby(...\func_get_args()); + } + + public function incrbyfloat($key, $value) + { + return $this->initializeLazyObject()->incrbyfloat(...\func_get_args()); + } + + public function info($key_or_address, $option = null) + { + return $this->initializeLazyObject()->info(...\func_get_args()); + } + + public function keys($pattern) + { + return $this->initializeLazyObject()->keys(...\func_get_args()); + } + + public function lastsave($key_or_address) + { + return $this->initializeLazyObject()->lastsave(...\func_get_args()); + } + + public function lget($key, $index) + { + return $this->initializeLazyObject()->lget(...\func_get_args()); + } + + public function lindex($key, $index) + { + return $this->initializeLazyObject()->lindex(...\func_get_args()); + } + + public function linsert($key, $position, $pivot, $value) + { + return $this->initializeLazyObject()->linsert(...\func_get_args()); + } + + public function llen($key) + { + return $this->initializeLazyObject()->llen(...\func_get_args()); + } + + public function lpop($key) + { + return $this->initializeLazyObject()->lpop(...\func_get_args()); + } + + public function lpush($key, $value) + { + return $this->initializeLazyObject()->lpush(...\func_get_args()); + } + + public function lpushx($key, $value) + { + return $this->initializeLazyObject()->lpushx(...\func_get_args()); + } + + public function lrange($key, $start, $end) + { + return $this->initializeLazyObject()->lrange(...\func_get_args()); + } + + public function lrem($key, $value) + { + return $this->initializeLazyObject()->lrem(...\func_get_args()); + } + + public function lset($key, $index, $value) + { + return $this->initializeLazyObject()->lset(...\func_get_args()); + } + + public function ltrim($key, $start, $stop) + { + return $this->initializeLazyObject()->ltrim(...\func_get_args()); + } + + public function mget($keys) + { + return $this->initializeLazyObject()->mget(...\func_get_args()); + } + + public function mset($pairs) + { + return $this->initializeLazyObject()->mset(...\func_get_args()); + } + + public function msetnx($pairs) + { + return $this->initializeLazyObject()->msetnx(...\func_get_args()); + } + + public function multi() + { + return $this->initializeLazyObject()->multi(...\func_get_args()); + } + + public function object($field, $key) + { + return $this->initializeLazyObject()->object(...\func_get_args()); + } + + public function persist($key) + { + return $this->initializeLazyObject()->persist(...\func_get_args()); + } + + public function pexpire($key, $timestamp) + { + return $this->initializeLazyObject()->pexpire(...\func_get_args()); + } + + public function pexpireat($key, $timestamp) + { + return $this->initializeLazyObject()->pexpireat(...\func_get_args()); + } + + public function pfadd($key, $elements) + { + return $this->initializeLazyObject()->pfadd(...\func_get_args()); + } + + public function pfcount($key) + { + return $this->initializeLazyObject()->pfcount(...\func_get_args()); + } + + public function pfmerge($dstkey, $keys) + { + return $this->initializeLazyObject()->pfmerge(...\func_get_args()); + } + + public function ping($key_or_address) + { + return $this->initializeLazyObject()->ping(...\func_get_args()); + } + + public function psetex($key, $expire, $value) + { + return $this->initializeLazyObject()->psetex(...\func_get_args()); + } + + public function psubscribe($patterns, $callback) + { + return $this->initializeLazyObject()->psubscribe(...\func_get_args()); + } + + public function pttl($key) + { + return $this->initializeLazyObject()->pttl(...\func_get_args()); + } + + public function publish($channel, $message) + { + return $this->initializeLazyObject()->publish(...\func_get_args()); + } + + public function pubsub($key_or_address, $arg = null, ...$other_args) + { + return $this->initializeLazyObject()->pubsub(...\func_get_args()); + } + + public function punsubscribe($pattern, ...$other_patterns) + { + return $this->initializeLazyObject()->punsubscribe(...\func_get_args()); + } + + public function randomkey($key_or_address) + { + return $this->initializeLazyObject()->randomkey(...\func_get_args()); + } + + public function rawcommand($cmd, ...$args) + { + return $this->initializeLazyObject()->rawcommand(...\func_get_args()); + } + + public function rename($key, $newkey) + { + return $this->initializeLazyObject()->rename(...\func_get_args()); + } + + public function renamenx($key, $newkey) + { + return $this->initializeLazyObject()->renamenx(...\func_get_args()); + } + + public function restore($ttl, $key, $value) + { + return $this->initializeLazyObject()->restore(...\func_get_args()); + } + + public function role() + { + return $this->initializeLazyObject()->role(...\func_get_args()); + } + + public function rpop($key) + { + return $this->initializeLazyObject()->rpop(...\func_get_args()); + } + + public function rpoplpush($src, $dst) + { + return $this->initializeLazyObject()->rpoplpush(...\func_get_args()); + } + + public function rpush($key, $value) + { + return $this->initializeLazyObject()->rpush(...\func_get_args()); + } + + public function rpushx($key, $value) + { + return $this->initializeLazyObject()->rpushx(...\func_get_args()); + } + + public function sadd($key, $value) + { + return $this->initializeLazyObject()->sadd(...\func_get_args()); + } + + public function saddarray($key, $options) + { + return $this->initializeLazyObject()->saddarray(...\func_get_args()); + } + + public function save($key_or_address) + { + return $this->initializeLazyObject()->save(...\func_get_args()); + } + + public function scan(&$i_iterator, $str_node, $str_pattern = null, $i_count = null) + { + return $this->initializeLazyObject()->scan($i_iterator, ...\array_slice(\func_get_args(), 1)); + } + + public function scard($key) + { + return $this->initializeLazyObject()->scard(...\func_get_args()); + } + + public function script($key_or_address, $arg = null, ...$other_args) + { + return $this->initializeLazyObject()->script(...\func_get_args()); + } + + public function sdiff($key, ...$other_keys) + { + return $this->initializeLazyObject()->sdiff(...\func_get_args()); + } + + public function sdiffstore($dst, $key, ...$other_keys) + { + return $this->initializeLazyObject()->sdiffstore(...\func_get_args()); + } + + public function set($key, $value, $opts = null) + { + return $this->initializeLazyObject()->set(...\func_get_args()); + } + + public function setbit($key, $offset, $value) + { + return $this->initializeLazyObject()->setbit(...\func_get_args()); + } + + public function setex($key, $expire, $value) + { + return $this->initializeLazyObject()->setex(...\func_get_args()); + } + + public function setnx($key, $value) + { + return $this->initializeLazyObject()->setnx(...\func_get_args()); + } + + public function setoption($option, $value) + { + return $this->initializeLazyObject()->setoption(...\func_get_args()); + } + + public function setrange($key, $offset, $value) + { + return $this->initializeLazyObject()->setrange(...\func_get_args()); + } + + public function sinter($key, ...$other_keys) + { + return $this->initializeLazyObject()->sinter(...\func_get_args()); + } + + public function sinterstore($dst, $key, ...$other_keys) + { + return $this->initializeLazyObject()->sinterstore(...\func_get_args()); + } + + public function sismember($key, $value) + { + return $this->initializeLazyObject()->sismember(...\func_get_args()); + } + + public function slowlog($key_or_address, $arg = null, ...$other_args) + { + return $this->initializeLazyObject()->slowlog(...\func_get_args()); + } + + public function smembers($key) + { + return $this->initializeLazyObject()->smembers(...\func_get_args()); + } + + public function smove($src, $dst, $value) + { + return $this->initializeLazyObject()->smove(...\func_get_args()); + } + + public function sort($key, $options = null) + { + return $this->initializeLazyObject()->sort(...\func_get_args()); + } + + public function spop($key) + { + return $this->initializeLazyObject()->spop(...\func_get_args()); + } + + public function srandmember($key, $count = null) + { + return $this->initializeLazyObject()->srandmember(...\func_get_args()); + } + + public function srem($key, $value) + { + return $this->initializeLazyObject()->srem(...\func_get_args()); + } + + public function sscan($str_key, &$i_iterator, $str_pattern = null, $i_count = null) + { + return $this->initializeLazyObject()->sscan($str_key, $i_iterator, ...\array_slice(\func_get_args(), 2)); + } + + public function strlen($key) + { + return $this->initializeLazyObject()->strlen(...\func_get_args()); + } + + public function subscribe($channels, $callback) + { + return $this->initializeLazyObject()->subscribe(...\func_get_args()); + } + + public function sunion($key, ...$other_keys) + { + return $this->initializeLazyObject()->sunion(...\func_get_args()); + } + + public function sunionstore($dst, $key, ...$other_keys) + { + return $this->initializeLazyObject()->sunionstore(...\func_get_args()); + } + + public function time() + { + return $this->initializeLazyObject()->time(...\func_get_args()); + } + + public function ttl($key) + { + return $this->initializeLazyObject()->ttl(...\func_get_args()); + } + + public function type($key) + { + return $this->initializeLazyObject()->type(...\func_get_args()); + } + + public function unsubscribe($channel, ...$other_channels) + { + return $this->initializeLazyObject()->unsubscribe(...\func_get_args()); + } + + public function unlink($key, ...$other_keys) + { + return $this->initializeLazyObject()->unlink(...\func_get_args()); + } + + public function unwatch() + { + return $this->initializeLazyObject()->unwatch(...\func_get_args()); + } + + public function watch($key, ...$other_keys) + { + return $this->initializeLazyObject()->watch(...\func_get_args()); + } + + public function xack($str_key, $str_group, $arr_ids) + { + return $this->initializeLazyObject()->xack(...\func_get_args()); + } + + public function xadd($str_key, $str_id, $arr_fields, $i_maxlen = null, $boo_approximate = null) + { + return $this->initializeLazyObject()->xadd(...\func_get_args()); + } + + public function xclaim($str_key, $str_group, $str_consumer, $i_min_idle, $arr_ids, $arr_opts = null) + { + return $this->initializeLazyObject()->xclaim(...\func_get_args()); + } + + public function xdel($str_key, $arr_ids) + { + return $this->initializeLazyObject()->xdel(...\func_get_args()); + } + + public function xgroup($str_operation, $str_key = null, $str_arg1 = null, $str_arg2 = null, $str_arg3 = null) + { + return $this->initializeLazyObject()->xgroup(...\func_get_args()); + } + + public function xinfo($str_cmd, $str_key = null, $str_group = null) + { + return $this->initializeLazyObject()->xinfo(...\func_get_args()); + } + + public function xlen($key) + { + return $this->initializeLazyObject()->xlen(...\func_get_args()); + } + + public function xpending($str_key, $str_group, $str_start = null, $str_end = null, $i_count = null, $str_consumer = null) + { + return $this->initializeLazyObject()->xpending(...\func_get_args()); + } + + public function xrange($str_key, $str_start, $str_end, $i_count = null) + { + return $this->initializeLazyObject()->xrange(...\func_get_args()); + } + + public function xread($arr_streams, $i_count = null, $i_block = null) + { + return $this->initializeLazyObject()->xread(...\func_get_args()); + } + + public function xreadgroup($str_group, $str_consumer, $arr_streams, $i_count = null, $i_block = null) + { + return $this->initializeLazyObject()->xreadgroup(...\func_get_args()); + } + + public function xrevrange($str_key, $str_start, $str_end, $i_count = null) + { + return $this->initializeLazyObject()->xrevrange(...\func_get_args()); + } + + public function xtrim($str_key, $i_maxlen, $boo_approximate = null) + { + return $this->initializeLazyObject()->xtrim(...\func_get_args()); + } + + public function zadd($key, $score, $value, ...$extra_args) + { + return $this->initializeLazyObject()->zadd(...\func_get_args()); + } + + public function zcard($key) + { + return $this->initializeLazyObject()->zcard(...\func_get_args()); + } + + public function zcount($key, $min, $max) + { + return $this->initializeLazyObject()->zcount(...\func_get_args()); + } + + public function zincrby($key, $value, $member) + { + return $this->initializeLazyObject()->zincrby(...\func_get_args()); + } + + public function zinterstore($key, $keys, $weights = null, $aggregate = null) + { + return $this->initializeLazyObject()->zinterstore(...\func_get_args()); + } + + public function zlexcount($key, $min, $max) + { + return $this->initializeLazyObject()->zlexcount(...\func_get_args()); + } + + public function zpopmax($key) + { + return $this->initializeLazyObject()->zpopmax(...\func_get_args()); + } + + public function zpopmin($key) + { + return $this->initializeLazyObject()->zpopmin(...\func_get_args()); + } + + public function zrange($key, $start, $end, $scores = null) + { + return $this->initializeLazyObject()->zrange(...\func_get_args()); + } + + public function zrangebylex($key, $min, $max, $offset = null, $limit = null) + { + return $this->initializeLazyObject()->zrangebylex(...\func_get_args()); + } + + public function zrangebyscore($key, $start, $end, $options = null) + { + return $this->initializeLazyObject()->zrangebyscore(...\func_get_args()); + } + + public function zrank($key, $member) + { + return $this->initializeLazyObject()->zrank(...\func_get_args()); + } + + public function zrem($key, $member, ...$other_members) + { + return $this->initializeLazyObject()->zrem(...\func_get_args()); + } + + public function zremrangebylex($key, $min, $max) + { + return $this->initializeLazyObject()->zremrangebylex(...\func_get_args()); + } + + public function zremrangebyrank($key, $min, $max) + { + return $this->initializeLazyObject()->zremrangebyrank(...\func_get_args()); + } + + public function zremrangebyscore($key, $min, $max) + { + return $this->initializeLazyObject()->zremrangebyscore(...\func_get_args()); + } + + public function zrevrange($key, $start, $end, $scores = null) + { + return $this->initializeLazyObject()->zrevrange(...\func_get_args()); + } + + public function zrevrangebylex($key, $min, $max, $offset = null, $limit = null) + { + return $this->initializeLazyObject()->zrevrangebylex(...\func_get_args()); + } + + public function zrevrangebyscore($key, $start, $end, $options = null) + { + return $this->initializeLazyObject()->zrevrangebyscore(...\func_get_args()); + } + + public function zrevrank($key, $member) + { + return $this->initializeLazyObject()->zrevrank(...\func_get_args()); + } + + public function zscan($str_key, &$i_iterator, $str_pattern = null, $i_count = null) + { + return $this->initializeLazyObject()->zscan($str_key, $i_iterator, ...\array_slice(\func_get_args(), 2)); + } + + public function zscore($key, $member) + { + return $this->initializeLazyObject()->zscore(...\func_get_args()); + } + + public function zunionstore($key, $keys, $weights = null, $aggregate = null) + { + return $this->initializeLazyObject()->zunionstore(...\func_get_args()); + } +} diff --git a/vendor/symfony/cache/Traits/RedisCluster6Proxy.php b/vendor/symfony/cache/Traits/RedisCluster6Proxy.php new file mode 100644 index 0000000..38dedf7 --- /dev/null +++ b/vendor/symfony/cache/Traits/RedisCluster6Proxy.php @@ -0,0 +1,1136 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Traits; + +use Symfony\Component\VarExporter\LazyObjectInterface; +use Symfony\Contracts\Service\ResetInterface; + +// Help opcache.preload discover always-needed symbols +class_exists(\Symfony\Component\VarExporter\Internal\Hydrator::class); +class_exists(\Symfony\Component\VarExporter\Internal\LazyObjectRegistry::class); +class_exists(\Symfony\Component\VarExporter\Internal\LazyObjectState::class); + +/** + * @internal + */ +class RedisCluster6Proxy extends \RedisCluster implements ResetInterface, LazyObjectInterface +{ + use RedisCluster6ProxyTrait; + use RedisProxyTrait { + resetLazyObject as reset; + } + + public function __construct($name, $seeds = null, $timeout = 0, $read_timeout = 0, $persistent = false, #[\SensitiveParameter] $auth = null, $context = null) + { + $this->initializeLazyObject()->__construct(...\func_get_args()); + } + + public function _compress($value): string + { + return $this->initializeLazyObject()->_compress(...\func_get_args()); + } + + public function _uncompress($value): string + { + return $this->initializeLazyObject()->_uncompress(...\func_get_args()); + } + + public function _serialize($value): bool|string + { + return $this->initializeLazyObject()->_serialize(...\func_get_args()); + } + + public function _unserialize($value): mixed + { + return $this->initializeLazyObject()->_unserialize(...\func_get_args()); + } + + public function _pack($value): string + { + return $this->initializeLazyObject()->_pack(...\func_get_args()); + } + + public function _unpack($value): mixed + { + return $this->initializeLazyObject()->_unpack(...\func_get_args()); + } + + public function _prefix($key): bool|string + { + return $this->initializeLazyObject()->_prefix(...\func_get_args()); + } + + public function _masters(): array + { + return $this->initializeLazyObject()->_masters(...\func_get_args()); + } + + public function _redir(): ?string + { + return $this->initializeLazyObject()->_redir(...\func_get_args()); + } + + public function acl($key_or_address, $subcmd, ...$args): mixed + { + return $this->initializeLazyObject()->acl(...\func_get_args()); + } + + public function append($key, $value): \RedisCluster|bool|int + { + return $this->initializeLazyObject()->append(...\func_get_args()); + } + + public function bgrewriteaof($key_or_address): \RedisCluster|bool + { + return $this->initializeLazyObject()->bgrewriteaof(...\func_get_args()); + } + + public function bgsave($key_or_address): \RedisCluster|bool + { + return $this->initializeLazyObject()->bgsave(...\func_get_args()); + } + + public function bitcount($key, $start = 0, $end = -1, $bybit = false): \RedisCluster|bool|int + { + return $this->initializeLazyObject()->bitcount(...\func_get_args()); + } + + public function bitop($operation, $deskey, $srckey, ...$otherkeys): \RedisCluster|bool|int + { + return $this->initializeLazyObject()->bitop(...\func_get_args()); + } + + public function bitpos($key, $bit, $start = 0, $end = -1, $bybit = false): \RedisCluster|false|int + { + return $this->initializeLazyObject()->bitpos(...\func_get_args()); + } + + public function blpop($key, $timeout_or_key, ...$extra_args): \RedisCluster|array|false|null + { + return $this->initializeLazyObject()->blpop(...\func_get_args()); + } + + public function brpop($key, $timeout_or_key, ...$extra_args): \RedisCluster|array|false|null + { + return $this->initializeLazyObject()->brpop(...\func_get_args()); + } + + public function brpoplpush($srckey, $deskey, $timeout): mixed + { + return $this->initializeLazyObject()->brpoplpush(...\func_get_args()); + } + + public function lmove($src, $dst, $wherefrom, $whereto): \Redis|false|string + { + return $this->initializeLazyObject()->lmove(...\func_get_args()); + } + + public function blmove($src, $dst, $wherefrom, $whereto, $timeout): \Redis|false|string + { + return $this->initializeLazyObject()->blmove(...\func_get_args()); + } + + public function bzpopmax($key, $timeout_or_key, ...$extra_args): array + { + return $this->initializeLazyObject()->bzpopmax(...\func_get_args()); + } + + public function bzpopmin($key, $timeout_or_key, ...$extra_args): array + { + return $this->initializeLazyObject()->bzpopmin(...\func_get_args()); + } + + public function bzmpop($timeout, $keys, $from, $count = 1): \RedisCluster|array|false|null + { + return $this->initializeLazyObject()->bzmpop(...\func_get_args()); + } + + public function zmpop($keys, $from, $count = 1): \RedisCluster|array|false|null + { + return $this->initializeLazyObject()->zmpop(...\func_get_args()); + } + + public function blmpop($timeout, $keys, $from, $count = 1): \RedisCluster|array|false|null + { + return $this->initializeLazyObject()->blmpop(...\func_get_args()); + } + + public function lmpop($keys, $from, $count = 1): \RedisCluster|array|false|null + { + return $this->initializeLazyObject()->lmpop(...\func_get_args()); + } + + public function clearlasterror(): bool + { + return $this->initializeLazyObject()->clearlasterror(...\func_get_args()); + } + + public function client($key_or_address, $subcommand, $arg = null): array|bool|string + { + return $this->initializeLazyObject()->client(...\func_get_args()); + } + + public function close(): bool + { + return $this->initializeLazyObject()->close(...\func_get_args()); + } + + public function cluster($key_or_address, $command, ...$extra_args): mixed + { + return $this->initializeLazyObject()->cluster(...\func_get_args()); + } + + public function command(...$extra_args): mixed + { + return $this->initializeLazyObject()->command(...\func_get_args()); + } + + public function config($key_or_address, $subcommand, ...$extra_args): mixed + { + return $this->initializeLazyObject()->config(...\func_get_args()); + } + + public function dbsize($key_or_address): \RedisCluster|int + { + return $this->initializeLazyObject()->dbsize(...\func_get_args()); + } + + public function copy($src, $dst, $options = null): \RedisCluster|bool + { + return $this->initializeLazyObject()->copy(...\func_get_args()); + } + + public function decr($key, $by = 1): \RedisCluster|false|int + { + return $this->initializeLazyObject()->decr(...\func_get_args()); + } + + public function decrby($key, $value): \RedisCluster|false|int + { + return $this->initializeLazyObject()->decrby(...\func_get_args()); + } + + public function decrbyfloat($key, $value): float + { + return $this->initializeLazyObject()->decrbyfloat(...\func_get_args()); + } + + public function del($key, ...$other_keys): \RedisCluster|false|int + { + return $this->initializeLazyObject()->del(...\func_get_args()); + } + + public function discard(): bool + { + return $this->initializeLazyObject()->discard(...\func_get_args()); + } + + public function dump($key): \RedisCluster|false|string + { + return $this->initializeLazyObject()->dump(...\func_get_args()); + } + + public function echo($key_or_address, $msg): \RedisCluster|false|string + { + return $this->initializeLazyObject()->echo(...\func_get_args()); + } + + public function eval($script, $args = [], $num_keys = 0): mixed + { + return $this->initializeLazyObject()->eval(...\func_get_args()); + } + + public function eval_ro($script, $args = [], $num_keys = 0): mixed + { + return $this->initializeLazyObject()->eval_ro(...\func_get_args()); + } + + public function evalsha($script_sha, $args = [], $num_keys = 0): mixed + { + return $this->initializeLazyObject()->evalsha(...\func_get_args()); + } + + public function evalsha_ro($script_sha, $args = [], $num_keys = 0): mixed + { + return $this->initializeLazyObject()->evalsha_ro(...\func_get_args()); + } + + public function exec(): array|false + { + return $this->initializeLazyObject()->exec(...\func_get_args()); + } + + public function exists($key, ...$other_keys): \RedisCluster|bool|int + { + return $this->initializeLazyObject()->exists(...\func_get_args()); + } + + public function touch($key, ...$other_keys): \RedisCluster|bool|int + { + return $this->initializeLazyObject()->touch(...\func_get_args()); + } + + public function expire($key, $timeout, $mode = null): \RedisCluster|bool + { + return $this->initializeLazyObject()->expire(...\func_get_args()); + } + + public function expireat($key, $timestamp, $mode = null): \RedisCluster|bool + { + return $this->initializeLazyObject()->expireat(...\func_get_args()); + } + + public function expiretime($key): \RedisCluster|false|int + { + return $this->initializeLazyObject()->expiretime(...\func_get_args()); + } + + public function pexpiretime($key): \RedisCluster|false|int + { + return $this->initializeLazyObject()->pexpiretime(...\func_get_args()); + } + + public function flushall($key_or_address, $async = false): \RedisCluster|bool + { + return $this->initializeLazyObject()->flushall(...\func_get_args()); + } + + public function flushdb($key_or_address, $async = false): \RedisCluster|bool + { + return $this->initializeLazyObject()->flushdb(...\func_get_args()); + } + + public function geoadd($key, $lng, $lat, $member, ...$other_triples_and_options): \RedisCluster|false|int + { + return $this->initializeLazyObject()->geoadd(...\func_get_args()); + } + + public function geodist($key, $src, $dest, $unit = null): \RedisCluster|false|float + { + return $this->initializeLazyObject()->geodist(...\func_get_args()); + } + + public function geohash($key, $member, ...$other_members): \RedisCluster|array|false + { + return $this->initializeLazyObject()->geohash(...\func_get_args()); + } + + public function geopos($key, $member, ...$other_members): \RedisCluster|array|false + { + return $this->initializeLazyObject()->geopos(...\func_get_args()); + } + + public function georadius($key, $lng, $lat, $radius, $unit, $options = []): mixed + { + return $this->initializeLazyObject()->georadius(...\func_get_args()); + } + + public function georadius_ro($key, $lng, $lat, $radius, $unit, $options = []): mixed + { + return $this->initializeLazyObject()->georadius_ro(...\func_get_args()); + } + + public function georadiusbymember($key, $member, $radius, $unit, $options = []): mixed + { + return $this->initializeLazyObject()->georadiusbymember(...\func_get_args()); + } + + public function georadiusbymember_ro($key, $member, $radius, $unit, $options = []): mixed + { + return $this->initializeLazyObject()->georadiusbymember_ro(...\func_get_args()); + } + + public function geosearch($key, $position, $shape, $unit, $options = []): \RedisCluster|array + { + return $this->initializeLazyObject()->geosearch(...\func_get_args()); + } + + public function geosearchstore($dst, $src, $position, $shape, $unit, $options = []): \RedisCluster|array|false|int + { + return $this->initializeLazyObject()->geosearchstore(...\func_get_args()); + } + + public function get($key): mixed + { + return $this->initializeLazyObject()->get(...\func_get_args()); + } + + public function getbit($key, $value): \RedisCluster|false|int + { + return $this->initializeLazyObject()->getbit(...\func_get_args()); + } + + public function getlasterror(): ?string + { + return $this->initializeLazyObject()->getlasterror(...\func_get_args()); + } + + public function getmode(): int + { + return $this->initializeLazyObject()->getmode(...\func_get_args()); + } + + public function getoption($option): mixed + { + return $this->initializeLazyObject()->getoption(...\func_get_args()); + } + + public function getrange($key, $start, $end): \RedisCluster|false|string + { + return $this->initializeLazyObject()->getrange(...\func_get_args()); + } + + public function lcs($key1, $key2, $options = null): \RedisCluster|array|false|int|string + { + return $this->initializeLazyObject()->lcs(...\func_get_args()); + } + + public function getset($key, $value): \RedisCluster|bool|string + { + return $this->initializeLazyObject()->getset(...\func_get_args()); + } + + public function gettransferredbytes(): array|false + { + return $this->initializeLazyObject()->gettransferredbytes(...\func_get_args()); + } + + public function cleartransferredbytes(): void + { + $this->initializeLazyObject()->cleartransferredbytes(...\func_get_args()); + } + + public function hdel($key, $member, ...$other_members): \RedisCluster|false|int + { + return $this->initializeLazyObject()->hdel(...\func_get_args()); + } + + public function hexists($key, $member): \RedisCluster|bool + { + return $this->initializeLazyObject()->hexists(...\func_get_args()); + } + + public function hget($key, $member): mixed + { + return $this->initializeLazyObject()->hget(...\func_get_args()); + } + + public function hgetall($key): \RedisCluster|array|false + { + return $this->initializeLazyObject()->hgetall(...\func_get_args()); + } + + public function hincrby($key, $member, $value): \RedisCluster|false|int + { + return $this->initializeLazyObject()->hincrby(...\func_get_args()); + } + + public function hincrbyfloat($key, $member, $value): \RedisCluster|false|float + { + return $this->initializeLazyObject()->hincrbyfloat(...\func_get_args()); + } + + public function hkeys($key): \RedisCluster|array|false + { + return $this->initializeLazyObject()->hkeys(...\func_get_args()); + } + + public function hlen($key): \RedisCluster|false|int + { + return $this->initializeLazyObject()->hlen(...\func_get_args()); + } + + public function hmget($key, $keys): \RedisCluster|array|false + { + return $this->initializeLazyObject()->hmget(...\func_get_args()); + } + + public function hmset($key, $key_values): \RedisCluster|bool + { + return $this->initializeLazyObject()->hmset(...\func_get_args()); + } + + public function hscan($key, &$iterator, $pattern = null, $count = 0): array|bool + { + return $this->initializeLazyObject()->hscan($key, $iterator, ...\array_slice(\func_get_args(), 2)); + } + + public function hrandfield($key, $options = null): \RedisCluster|array|string + { + return $this->initializeLazyObject()->hrandfield(...\func_get_args()); + } + + public function hset($key, $member, $value): \RedisCluster|false|int + { + return $this->initializeLazyObject()->hset(...\func_get_args()); + } + + public function hsetnx($key, $member, $value): \RedisCluster|bool + { + return $this->initializeLazyObject()->hsetnx(...\func_get_args()); + } + + public function hstrlen($key, $field): \RedisCluster|false|int + { + return $this->initializeLazyObject()->hstrlen(...\func_get_args()); + } + + public function hvals($key): \RedisCluster|array|false + { + return $this->initializeLazyObject()->hvals(...\func_get_args()); + } + + public function incr($key, $by = 1): \RedisCluster|false|int + { + return $this->initializeLazyObject()->incr(...\func_get_args()); + } + + public function incrby($key, $value): \RedisCluster|false|int + { + return $this->initializeLazyObject()->incrby(...\func_get_args()); + } + + public function incrbyfloat($key, $value): \RedisCluster|false|float + { + return $this->initializeLazyObject()->incrbyfloat(...\func_get_args()); + } + + public function info($key_or_address, ...$sections): \RedisCluster|array|false + { + return $this->initializeLazyObject()->info(...\func_get_args()); + } + + public function keys($pattern): \RedisCluster|array|false + { + return $this->initializeLazyObject()->keys(...\func_get_args()); + } + + public function lastsave($key_or_address): \RedisCluster|false|int + { + return $this->initializeLazyObject()->lastsave(...\func_get_args()); + } + + public function lget($key, $index): \RedisCluster|bool|string + { + return $this->initializeLazyObject()->lget(...\func_get_args()); + } + + public function lindex($key, $index): mixed + { + return $this->initializeLazyObject()->lindex(...\func_get_args()); + } + + public function linsert($key, $pos, $pivot, $value): \RedisCluster|false|int + { + return $this->initializeLazyObject()->linsert(...\func_get_args()); + } + + public function llen($key): \RedisCluster|bool|int + { + return $this->initializeLazyObject()->llen(...\func_get_args()); + } + + public function lpop($key, $count = 0): \RedisCluster|array|bool|string + { + return $this->initializeLazyObject()->lpop(...\func_get_args()); + } + + public function lpos($key, $value, $options = null): \Redis|array|bool|int|null + { + return $this->initializeLazyObject()->lpos(...\func_get_args()); + } + + public function lpush($key, $value, ...$other_values): \RedisCluster|bool|int + { + return $this->initializeLazyObject()->lpush(...\func_get_args()); + } + + public function lpushx($key, $value): \RedisCluster|bool|int + { + return $this->initializeLazyObject()->lpushx(...\func_get_args()); + } + + public function lrange($key, $start, $end): \RedisCluster|array|false + { + return $this->initializeLazyObject()->lrange(...\func_get_args()); + } + + public function lrem($key, $value, $count = 0): \RedisCluster|bool|int + { + return $this->initializeLazyObject()->lrem(...\func_get_args()); + } + + public function lset($key, $index, $value): \RedisCluster|bool + { + return $this->initializeLazyObject()->lset(...\func_get_args()); + } + + public function ltrim($key, $start, $end): \RedisCluster|bool + { + return $this->initializeLazyObject()->ltrim(...\func_get_args()); + } + + public function mget($keys): \RedisCluster|array|false + { + return $this->initializeLazyObject()->mget(...\func_get_args()); + } + + public function mset($key_values): \RedisCluster|bool + { + return $this->initializeLazyObject()->mset(...\func_get_args()); + } + + public function msetnx($key_values): \RedisCluster|array|false + { + return $this->initializeLazyObject()->msetnx(...\func_get_args()); + } + + public function multi($value = \Redis::MULTI): \RedisCluster|bool + { + return $this->initializeLazyObject()->multi(...\func_get_args()); + } + + public function object($subcommand, $key): \RedisCluster|false|int|string + { + return $this->initializeLazyObject()->object(...\func_get_args()); + } + + public function persist($key): \RedisCluster|bool + { + return $this->initializeLazyObject()->persist(...\func_get_args()); + } + + public function pexpire($key, $timeout, $mode = null): \RedisCluster|bool + { + return $this->initializeLazyObject()->pexpire(...\func_get_args()); + } + + public function pexpireat($key, $timestamp, $mode = null): \RedisCluster|bool + { + return $this->initializeLazyObject()->pexpireat(...\func_get_args()); + } + + public function pfadd($key, $elements): \RedisCluster|bool + { + return $this->initializeLazyObject()->pfadd(...\func_get_args()); + } + + public function pfcount($key): \RedisCluster|false|int + { + return $this->initializeLazyObject()->pfcount(...\func_get_args()); + } + + public function pfmerge($key, $keys): \RedisCluster|bool + { + return $this->initializeLazyObject()->pfmerge(...\func_get_args()); + } + + public function ping($key_or_address, $message = null): mixed + { + return $this->initializeLazyObject()->ping(...\func_get_args()); + } + + public function psetex($key, $timeout, $value): \RedisCluster|bool + { + return $this->initializeLazyObject()->psetex(...\func_get_args()); + } + + public function psubscribe($patterns, $callback): void + { + $this->initializeLazyObject()->psubscribe(...\func_get_args()); + } + + public function pttl($key): \RedisCluster|false|int + { + return $this->initializeLazyObject()->pttl(...\func_get_args()); + } + + public function pubsub($key_or_address, ...$values): mixed + { + return $this->initializeLazyObject()->pubsub(...\func_get_args()); + } + + public function punsubscribe($pattern, ...$other_patterns): array|bool + { + return $this->initializeLazyObject()->punsubscribe(...\func_get_args()); + } + + public function randomkey($key_or_address): \RedisCluster|bool|string + { + return $this->initializeLazyObject()->randomkey(...\func_get_args()); + } + + public function rawcommand($key_or_address, $command, ...$args): mixed + { + return $this->initializeLazyObject()->rawcommand(...\func_get_args()); + } + + public function rename($key_src, $key_dst): \RedisCluster|bool + { + return $this->initializeLazyObject()->rename(...\func_get_args()); + } + + public function renamenx($key, $newkey): \RedisCluster|bool + { + return $this->initializeLazyObject()->renamenx(...\func_get_args()); + } + + public function restore($key, $timeout, $value, $options = null): \RedisCluster|bool + { + return $this->initializeLazyObject()->restore(...\func_get_args()); + } + + public function role($key_or_address): mixed + { + return $this->initializeLazyObject()->role(...\func_get_args()); + } + + public function rpop($key, $count = 0): \RedisCluster|array|bool|string + { + return $this->initializeLazyObject()->rpop(...\func_get_args()); + } + + public function rpoplpush($src, $dst): \RedisCluster|bool|string + { + return $this->initializeLazyObject()->rpoplpush(...\func_get_args()); + } + + public function rpush($key, ...$elements): \RedisCluster|false|int + { + return $this->initializeLazyObject()->rpush(...\func_get_args()); + } + + public function rpushx($key, $value): \RedisCluster|bool|int + { + return $this->initializeLazyObject()->rpushx(...\func_get_args()); + } + + public function sadd($key, $value, ...$other_values): \RedisCluster|false|int + { + return $this->initializeLazyObject()->sadd(...\func_get_args()); + } + + public function saddarray($key, $values): \RedisCluster|bool|int + { + return $this->initializeLazyObject()->saddarray(...\func_get_args()); + } + + public function save($key_or_address): \RedisCluster|bool + { + return $this->initializeLazyObject()->save(...\func_get_args()); + } + + public function scan(&$iterator, $key_or_address, $pattern = null, $count = 0): array|bool + { + return $this->initializeLazyObject()->scan($iterator, ...\array_slice(\func_get_args(), 1)); + } + + public function scard($key): \RedisCluster|false|int + { + return $this->initializeLazyObject()->scard(...\func_get_args()); + } + + public function script($key_or_address, ...$args): mixed + { + return $this->initializeLazyObject()->script(...\func_get_args()); + } + + public function sdiff($key, ...$other_keys): \RedisCluster|array|false + { + return $this->initializeLazyObject()->sdiff(...\func_get_args()); + } + + public function sdiffstore($dst, $key, ...$other_keys): \RedisCluster|false|int + { + return $this->initializeLazyObject()->sdiffstore(...\func_get_args()); + } + + public function set($key, $value, $options = null): \RedisCluster|bool|string + { + return $this->initializeLazyObject()->set(...\func_get_args()); + } + + public function setbit($key, $offset, $onoff): \RedisCluster|false|int + { + return $this->initializeLazyObject()->setbit(...\func_get_args()); + } + + public function setex($key, $expire, $value): \RedisCluster|bool + { + return $this->initializeLazyObject()->setex(...\func_get_args()); + } + + public function setnx($key, $value): \RedisCluster|bool + { + return $this->initializeLazyObject()->setnx(...\func_get_args()); + } + + public function setoption($option, $value): bool + { + return $this->initializeLazyObject()->setoption(...\func_get_args()); + } + + public function setrange($key, $offset, $value): \RedisCluster|false|int + { + return $this->initializeLazyObject()->setrange(...\func_get_args()); + } + + public function sinter($key, ...$other_keys): \RedisCluster|array|false + { + return $this->initializeLazyObject()->sinter(...\func_get_args()); + } + + public function sintercard($keys, $limit = -1): \RedisCluster|false|int + { + return $this->initializeLazyObject()->sintercard(...\func_get_args()); + } + + public function sinterstore($key, ...$other_keys): \RedisCluster|false|int + { + return $this->initializeLazyObject()->sinterstore(...\func_get_args()); + } + + public function sismember($key, $value): \RedisCluster|bool + { + return $this->initializeLazyObject()->sismember(...\func_get_args()); + } + + public function smismember($key, $member, ...$other_members): \RedisCluster|array|false + { + return $this->initializeLazyObject()->smismember(...\func_get_args()); + } + + public function slowlog($key_or_address, ...$args): mixed + { + return $this->initializeLazyObject()->slowlog(...\func_get_args()); + } + + public function smembers($key): \RedisCluster|array|false + { + return $this->initializeLazyObject()->smembers(...\func_get_args()); + } + + public function smove($src, $dst, $member): \RedisCluster|bool + { + return $this->initializeLazyObject()->smove(...\func_get_args()); + } + + public function sort($key, $options = null): \RedisCluster|array|bool|int|string + { + return $this->initializeLazyObject()->sort(...\func_get_args()); + } + + public function sort_ro($key, $options = null): \RedisCluster|array|bool|int|string + { + return $this->initializeLazyObject()->sort_ro(...\func_get_args()); + } + + public function spop($key, $count = 0): \RedisCluster|array|false|string + { + return $this->initializeLazyObject()->spop(...\func_get_args()); + } + + public function srandmember($key, $count = 0): \RedisCluster|array|false|string + { + return $this->initializeLazyObject()->srandmember(...\func_get_args()); + } + + public function srem($key, $value, ...$other_values): \RedisCluster|false|int + { + return $this->initializeLazyObject()->srem(...\func_get_args()); + } + + public function sscan($key, &$iterator, $pattern = null, $count = 0): array|false + { + return $this->initializeLazyObject()->sscan($key, $iterator, ...\array_slice(\func_get_args(), 2)); + } + + public function strlen($key): \RedisCluster|false|int + { + return $this->initializeLazyObject()->strlen(...\func_get_args()); + } + + public function subscribe($channels, $cb): void + { + $this->initializeLazyObject()->subscribe(...\func_get_args()); + } + + public function sunion($key, ...$other_keys): \RedisCluster|array|bool + { + return $this->initializeLazyObject()->sunion(...\func_get_args()); + } + + public function sunionstore($dst, $key, ...$other_keys): \RedisCluster|false|int + { + return $this->initializeLazyObject()->sunionstore(...\func_get_args()); + } + + public function time($key_or_address): \RedisCluster|array|bool + { + return $this->initializeLazyObject()->time(...\func_get_args()); + } + + public function ttl($key): \RedisCluster|false|int + { + return $this->initializeLazyObject()->ttl(...\func_get_args()); + } + + public function type($key): \RedisCluster|false|int + { + return $this->initializeLazyObject()->type(...\func_get_args()); + } + + public function unsubscribe($channels): array|bool + { + return $this->initializeLazyObject()->unsubscribe(...\func_get_args()); + } + + public function unlink($key, ...$other_keys): \RedisCluster|false|int + { + return $this->initializeLazyObject()->unlink(...\func_get_args()); + } + + public function unwatch(): bool + { + return $this->initializeLazyObject()->unwatch(...\func_get_args()); + } + + public function watch($key, ...$other_keys): \RedisCluster|bool + { + return $this->initializeLazyObject()->watch(...\func_get_args()); + } + + public function xack($key, $group, $ids): \RedisCluster|false|int + { + return $this->initializeLazyObject()->xack(...\func_get_args()); + } + + public function xadd($key, $id, $values, $maxlen = 0, $approx = false): \RedisCluster|false|string + { + return $this->initializeLazyObject()->xadd(...\func_get_args()); + } + + public function xclaim($key, $group, $consumer, $min_iddle, $ids, $options): \RedisCluster|array|false|string + { + return $this->initializeLazyObject()->xclaim(...\func_get_args()); + } + + public function xdel($key, $ids): \RedisCluster|false|int + { + return $this->initializeLazyObject()->xdel(...\func_get_args()); + } + + public function xgroup($operation, $key = null, $group = null, $id_or_consumer = null, $mkstream = false, $entries_read = -2): mixed + { + return $this->initializeLazyObject()->xgroup(...\func_get_args()); + } + + public function xautoclaim($key, $group, $consumer, $min_idle, $start, $count = -1, $justid = false): \RedisCluster|array|bool + { + return $this->initializeLazyObject()->xautoclaim(...\func_get_args()); + } + + public function xinfo($operation, $arg1 = null, $arg2 = null, $count = -1): mixed + { + return $this->initializeLazyObject()->xinfo(...\func_get_args()); + } + + public function xlen($key): \RedisCluster|false|int + { + return $this->initializeLazyObject()->xlen(...\func_get_args()); + } + + public function xpending($key, $group, $start = null, $end = null, $count = -1, $consumer = null): \RedisCluster|array|false + { + return $this->initializeLazyObject()->xpending(...\func_get_args()); + } + + public function xrange($key, $start, $end, $count = -1): \RedisCluster|array|bool + { + return $this->initializeLazyObject()->xrange(...\func_get_args()); + } + + public function xread($streams, $count = -1, $block = -1): \RedisCluster|array|bool + { + return $this->initializeLazyObject()->xread(...\func_get_args()); + } + + public function xreadgroup($group, $consumer, $streams, $count = 1, $block = 1): \RedisCluster|array|bool + { + return $this->initializeLazyObject()->xreadgroup(...\func_get_args()); + } + + public function xrevrange($key, $start, $end, $count = -1): \RedisCluster|array|bool + { + return $this->initializeLazyObject()->xrevrange(...\func_get_args()); + } + + public function xtrim($key, $maxlen, $approx = false, $minid = false, $limit = -1): \RedisCluster|false|int + { + return $this->initializeLazyObject()->xtrim(...\func_get_args()); + } + + public function zadd($key, $score_or_options, ...$more_scores_and_mems): \RedisCluster|false|float|int + { + return $this->initializeLazyObject()->zadd(...\func_get_args()); + } + + public function zcard($key): \RedisCluster|false|int + { + return $this->initializeLazyObject()->zcard(...\func_get_args()); + } + + public function zcount($key, $start, $end): \RedisCluster|false|int + { + return $this->initializeLazyObject()->zcount(...\func_get_args()); + } + + public function zincrby($key, $value, $member): \RedisCluster|false|float + { + return $this->initializeLazyObject()->zincrby(...\func_get_args()); + } + + public function zinterstore($dst, $keys, $weights = null, $aggregate = null): \RedisCluster|false|int + { + return $this->initializeLazyObject()->zinterstore(...\func_get_args()); + } + + public function zintercard($keys, $limit = -1): \RedisCluster|false|int + { + return $this->initializeLazyObject()->zintercard(...\func_get_args()); + } + + public function zlexcount($key, $min, $max): \RedisCluster|false|int + { + return $this->initializeLazyObject()->zlexcount(...\func_get_args()); + } + + public function zpopmax($key, $value = null): \RedisCluster|array|bool + { + return $this->initializeLazyObject()->zpopmax(...\func_get_args()); + } + + public function zpopmin($key, $value = null): \RedisCluster|array|bool + { + return $this->initializeLazyObject()->zpopmin(...\func_get_args()); + } + + public function zrange($key, $start, $end, $options = null): \RedisCluster|array|bool + { + return $this->initializeLazyObject()->zrange(...\func_get_args()); + } + + public function zrangestore($dstkey, $srckey, $start, $end, $options = null): \RedisCluster|false|int + { + return $this->initializeLazyObject()->zrangestore(...\func_get_args()); + } + + public function zrandmember($key, $options = null): \RedisCluster|array|string + { + return $this->initializeLazyObject()->zrandmember(...\func_get_args()); + } + + public function zrangebylex($key, $min, $max, $offset = -1, $count = -1): \RedisCluster|array|false + { + return $this->initializeLazyObject()->zrangebylex(...\func_get_args()); + } + + public function zrangebyscore($key, $start, $end, $options = []): \RedisCluster|array|false + { + return $this->initializeLazyObject()->zrangebyscore(...\func_get_args()); + } + + public function zrank($key, $member): \RedisCluster|false|int + { + return $this->initializeLazyObject()->zrank(...\func_get_args()); + } + + public function zrem($key, $value, ...$other_values): \RedisCluster|false|int + { + return $this->initializeLazyObject()->zrem(...\func_get_args()); + } + + public function zremrangebylex($key, $min, $max): \RedisCluster|false|int + { + return $this->initializeLazyObject()->zremrangebylex(...\func_get_args()); + } + + public function zremrangebyrank($key, $min, $max): \RedisCluster|false|int + { + return $this->initializeLazyObject()->zremrangebyrank(...\func_get_args()); + } + + public function zremrangebyscore($key, $min, $max): \RedisCluster|false|int + { + return $this->initializeLazyObject()->zremrangebyscore(...\func_get_args()); + } + + public function zrevrange($key, $min, $max, $options = null): \RedisCluster|array|bool + { + return $this->initializeLazyObject()->zrevrange(...\func_get_args()); + } + + public function zrevrangebylex($key, $min, $max, $options = null): \RedisCluster|array|bool + { + return $this->initializeLazyObject()->zrevrangebylex(...\func_get_args()); + } + + public function zrevrangebyscore($key, $min, $max, $options = null): \RedisCluster|array|bool + { + return $this->initializeLazyObject()->zrevrangebyscore(...\func_get_args()); + } + + public function zrevrank($key, $member): \RedisCluster|false|int + { + return $this->initializeLazyObject()->zrevrank(...\func_get_args()); + } + + public function zscan($key, &$iterator, $pattern = null, $count = 0): \RedisCluster|array|bool + { + return $this->initializeLazyObject()->zscan($key, $iterator, ...\array_slice(\func_get_args(), 2)); + } + + public function zscore($key, $member): \RedisCluster|false|float + { + return $this->initializeLazyObject()->zscore(...\func_get_args()); + } + + public function zmscore($key, $member, ...$other_members): \Redis|array|false + { + return $this->initializeLazyObject()->zmscore(...\func_get_args()); + } + + public function zunionstore($dst, $keys, $weights = null, $aggregate = null): \RedisCluster|false|int + { + return $this->initializeLazyObject()->zunionstore(...\func_get_args()); + } + + public function zinter($keys, $weights = null, $options = null): \RedisCluster|array|false + { + return $this->initializeLazyObject()->zinter(...\func_get_args()); + } + + public function zdiffstore($dst, $keys): \RedisCluster|false|int + { + return $this->initializeLazyObject()->zdiffstore(...\func_get_args()); + } + + public function zunion($keys, $weights = null, $options = null): \RedisCluster|array|false + { + return $this->initializeLazyObject()->zunion(...\func_get_args()); + } + + public function zdiff($keys, $options = null): \RedisCluster|array|false + { + return $this->initializeLazyObject()->zdiff(...\func_get_args()); + } +} diff --git a/vendor/symfony/cache/Traits/RedisCluster6ProxyTrait.php b/vendor/symfony/cache/Traits/RedisCluster6ProxyTrait.php new file mode 100644 index 0000000..5033c01 --- /dev/null +++ b/vendor/symfony/cache/Traits/RedisCluster6ProxyTrait.php @@ -0,0 +1,46 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Traits; + +if (version_compare(phpversion('redis'), '6.1.0-dev', '>')) { + /** + * @internal + */ + trait RedisCluster6ProxyTrait + { + public function getex($key, $options = []): \RedisCluster|string|false + { + return $this->initializeLazyObject()->getex(...\func_get_args()); + } + + public function publish($channel, $message): \RedisCluster|bool|int + { + return $this->initializeLazyObject()->publish(...\func_get_args()); + } + + public function waitaof($key_or_address, $numlocal, $numreplicas, $timeout): \RedisCluster|array|false + { + return $this->initializeLazyObject()->waitaof(...\func_get_args()); + } + } +} else { + /** + * @internal + */ + trait RedisCluster6ProxyTrait + { + public function publish($channel, $message): \RedisCluster|bool + { + return $this->initializeLazyObject()->publish(...\func_get_args()); + } + } +} diff --git a/vendor/symfony/cache/Traits/RedisClusterNodeProxy.php b/vendor/symfony/cache/Traits/RedisClusterNodeProxy.php new file mode 100644 index 0000000..f5c0baa --- /dev/null +++ b/vendor/symfony/cache/Traits/RedisClusterNodeProxy.php @@ -0,0 +1,47 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Traits; + +/** + * This file acts as a wrapper to the \RedisCluster implementation so it can accept the same type of calls as + * individual \Redis objects. + * + * Calls are made to individual nodes via: RedisCluster->{method}($host, ...args)' + * according to https://github.com/phpredis/phpredis/blob/develop/cluster.markdown#directed-node-commands + * + * @author Jack Thomas + * + * @internal + */ +class RedisClusterNodeProxy +{ + public function __construct( + private array $host, + private \RedisCluster $redis, + ) { + } + + public function __call(string $method, array $args) + { + return $this->redis->{$method}($this->host, ...$args); + } + + public function scan(&$iIterator, $strPattern = null, $iCount = null) + { + return $this->redis->scan($iIterator, $this->host, $strPattern, $iCount); + } + + public function getOption($name) + { + return $this->redis->getOption($name); + } +} diff --git a/vendor/symfony/cache/Traits/RedisClusterProxy.php b/vendor/symfony/cache/Traits/RedisClusterProxy.php new file mode 100644 index 0000000..c67d534 --- /dev/null +++ b/vendor/symfony/cache/Traits/RedisClusterProxy.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Traits; + +class_alias(6.0 <= (float) phpversion('redis') ? RedisCluster6Proxy::class : RedisCluster5Proxy::class, RedisClusterProxy::class); + +if (false) { + /** + * @internal + */ + class RedisClusterProxy extends \RedisCluster + { + } +} diff --git a/vendor/symfony/cache/Traits/RedisProxy.php b/vendor/symfony/cache/Traits/RedisProxy.php new file mode 100644 index 0000000..7f4537b --- /dev/null +++ b/vendor/symfony/cache/Traits/RedisProxy.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Traits; + +class_alias(6.0 <= (float) phpversion('redis') ? Redis6Proxy::class : Redis5Proxy::class, RedisProxy::class); + +if (false) { + /** + * @internal + */ + class RedisProxy extends \Redis + { + } +} diff --git a/vendor/symfony/cache/Traits/RedisProxyTrait.php b/vendor/symfony/cache/Traits/RedisProxyTrait.php new file mode 100644 index 0000000..1acbdf1 --- /dev/null +++ b/vendor/symfony/cache/Traits/RedisProxyTrait.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Traits; + +/** + * @internal + */ +trait RedisProxyTrait +{ + private \Closure $initializer; + private ?parent $realInstance = null; + + public static function createLazyProxy(\Closure $initializer, ?self $instance = null): static + { + $instance ??= (new \ReflectionClass(static::class))->newInstanceWithoutConstructor(); + $instance->realInstance = null; + $instance->initializer = $initializer; + + return $instance; + } + + public function isLazyObjectInitialized(bool $partial = false): bool + { + return isset($this->realInstance); + } + + public function initializeLazyObject(): object + { + return $this->realInstance ??= ($this->initializer)(); + } + + public function resetLazyObject(): bool + { + $this->realInstance = null; + + return true; + } + + public function __destruct() + { + } +} diff --git a/vendor/symfony/cache/Traits/RedisTrait.php b/vendor/symfony/cache/Traits/RedisTrait.php new file mode 100644 index 0000000..87c6892 --- /dev/null +++ b/vendor/symfony/cache/Traits/RedisTrait.php @@ -0,0 +1,682 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Traits; + +use Predis\Command\Redis\UNLINK; +use Predis\Connection\Aggregate\ClusterInterface; +use Predis\Connection\Aggregate\RedisCluster; +use Predis\Connection\Aggregate\ReplicationInterface; +use Predis\Connection\Cluster\ClusterInterface as Predis2ClusterInterface; +use Predis\Connection\Cluster\RedisCluster as Predis2RedisCluster; +use Predis\Response\ErrorInterface; +use Predis\Response\Status; +use Relay\Relay; +use Relay\Sentinel; +use Symfony\Component\Cache\Exception\CacheException; +use Symfony\Component\Cache\Exception\InvalidArgumentException; +use Symfony\Component\Cache\Marshaller\DefaultMarshaller; +use Symfony\Component\Cache\Marshaller\MarshallerInterface; + +/** + * @author Aurimas Niekis + * @author Nicolas Grekas + * + * @internal + */ +trait RedisTrait +{ + private static array $defaultConnectionOptions = [ + 'class' => null, + 'persistent' => 0, + 'persistent_id' => null, + 'timeout' => 30, + 'read_timeout' => 0, + 'retry_interval' => 0, + 'tcp_keepalive' => 0, + 'lazy' => null, + 'redis_cluster' => false, + 'redis_sentinel' => null, + 'dbindex' => 0, + 'failover' => 'none', + 'ssl' => null, // see https://php.net/context.ssl + ]; + private \Redis|Relay|\RedisArray|\RedisCluster|\Predis\ClientInterface $redis; + private MarshallerInterface $marshaller; + + private function init(\Redis|Relay|\RedisArray|\RedisCluster|\Predis\ClientInterface $redis, string $namespace, int $defaultLifetime, ?MarshallerInterface $marshaller): void + { + parent::__construct($namespace, $defaultLifetime); + + if (preg_match('#[^-+_.A-Za-z0-9]#', $namespace, $match)) { + throw new InvalidArgumentException(\sprintf('RedisAdapter namespace contains "%s" but only characters in [-+_.A-Za-z0-9] are allowed.', $match[0])); + } + + if ($redis instanceof \Predis\ClientInterface && $redis->getOptions()->exceptions) { + $options = clone $redis->getOptions(); + \Closure::bind(function () { $this->options['exceptions'] = false; }, $options, $options)(); + $redis = new $redis($redis->getConnection(), $options); + } + + $this->redis = $redis; + $this->marshaller = $marshaller ?? new DefaultMarshaller(); + } + + /** + * Creates a Redis connection using a DSN configuration. + * + * Example DSN: + * - redis://localhost + * - redis://example.com:1234 + * - redis://secret@example.com/13 + * - redis:///var/run/redis.sock + * - redis://secret@/var/run/redis.sock/13 + * + * @param array $options See self::$defaultConnectionOptions + * + * @throws InvalidArgumentException when the DSN is invalid + */ + public static function createConnection(#[\SensitiveParameter] string $dsn, array $options = []): \Redis|\RedisArray|\RedisCluster|\Predis\ClientInterface|Relay + { + if (str_starts_with($dsn, 'redis:')) { + $scheme = 'redis'; + } elseif (str_starts_with($dsn, 'rediss:')) { + $scheme = 'rediss'; + } else { + throw new InvalidArgumentException('Invalid Redis DSN: it does not start with "redis[s]:".'); + } + + if (!\extension_loaded('redis') && !class_exists(\Predis\Client::class)) { + throw new CacheException('Cannot find the "redis" extension nor the "predis/predis" package.'); + } + + $params = preg_replace_callback('#^'.$scheme.':(//)?(?:(?:(?[^:@]*+):)?(?[^@]*+)@)?#', function ($m) use (&$auth) { + if (isset($m['password'])) { + if (\in_array($m['user'], ['', 'default'], true)) { + $auth = rawurldecode($m['password']); + } else { + $auth = [rawurldecode($m['user']), rawurldecode($m['password'])]; + } + + if ('' === $auth) { + $auth = null; + } + } + + return 'file:'.($m[1] ?? ''); + }, $dsn); + + if (false === $params = parse_url($params)) { + throw new InvalidArgumentException('Invalid Redis DSN.'); + } + + $query = $hosts = []; + + $tls = 'rediss' === $scheme; + $tcpScheme = $tls ? 'tls' : 'tcp'; + + if (isset($params['query'])) { + parse_str($params['query'], $query); + + if (isset($query['host'])) { + if (!\is_array($hosts = $query['host'])) { + throw new InvalidArgumentException('Invalid Redis DSN: query parameter "host" must be an array.'); + } + foreach ($hosts as $host => $parameters) { + if (\is_string($parameters)) { + parse_str($parameters, $parameters); + } + if (false === $i = strrpos($host, ':')) { + $hosts[$host] = ['scheme' => $tcpScheme, 'host' => $host, 'port' => 6379] + $parameters; + } elseif ($port = (int) substr($host, 1 + $i)) { + $hosts[$host] = ['scheme' => $tcpScheme, 'host' => substr($host, 0, $i), 'port' => $port] + $parameters; + } else { + $hosts[$host] = ['scheme' => 'unix', 'path' => substr($host, 0, $i)] + $parameters; + } + } + $hosts = array_values($hosts); + } + } + + if (isset($params['host']) || isset($params['path'])) { + if (!isset($params['dbindex']) && isset($params['path'])) { + if (preg_match('#/(\d+)?$#', $params['path'], $m)) { + $params['dbindex'] = $m[1] ?? $query['dbindex'] ?? '0'; + $params['path'] = substr($params['path'], 0, -\strlen($m[0])); + } elseif (isset($params['host'])) { + throw new InvalidArgumentException('Invalid Redis DSN: parameter "dbindex" must be a number.'); + } + } + + if (isset($params['host'])) { + array_unshift($hosts, ['scheme' => $tcpScheme, 'host' => $params['host'], 'port' => $params['port'] ?? 6379]); + } else { + array_unshift($hosts, ['scheme' => 'unix', 'path' => $params['path']]); + } + } + + if (!$hosts) { + throw new InvalidArgumentException('Invalid Redis DSN: missing host.'); + } + + if (isset($params['dbindex'], $query['dbindex']) && $params['dbindex'] !== $query['dbindex']) { + throw new InvalidArgumentException('Invalid Redis DSN: path and query "dbindex" parameters mismatch.'); + } + + $params += $query + $options + self::$defaultConnectionOptions; + + if (isset($params['redis_sentinel']) && isset($params['sentinel_master'])) { + throw new InvalidArgumentException('Cannot use both "redis_sentinel" and "sentinel_master" at the same time.'); + } + + $params['redis_sentinel'] ??= $params['sentinel_master'] ?? null; + + if (isset($params['redis_sentinel']) && !class_exists(\Predis\Client::class) && !class_exists(\RedisSentinel::class) && !class_exists(Sentinel::class)) { + throw new CacheException('Redis Sentinel support requires one of: "predis/predis", "ext-redis >= 5.2", "ext-relay".'); + } + + if (isset($params['lazy'])) { + $params['lazy'] = filter_var($params['lazy'], \FILTER_VALIDATE_BOOLEAN); + } + $params['redis_cluster'] = filter_var($params['redis_cluster'], \FILTER_VALIDATE_BOOLEAN); + + if ($params['redis_cluster'] && isset($params['redis_sentinel'])) { + throw new InvalidArgumentException('Cannot use both "redis_cluster" and "redis_sentinel" at the same time.'); + } + + $class = $params['class'] ?? match (true) { + $params['redis_cluster'] => \extension_loaded('redis') ? \RedisCluster::class : \Predis\Client::class, + isset($params['redis_sentinel']) => match (true) { + \extension_loaded('redis') => \Redis::class, + \extension_loaded('relay') => Relay::class, + default => \Predis\Client::class, + }, + 1 < \count($hosts) && \extension_loaded('redis') => \RedisArray::class, + \extension_loaded('redis') => \Redis::class, + \extension_loaded('relay') => Relay::class, + default => \Predis\Client::class, + }; + + if (isset($params['redis_sentinel']) && !is_a($class, \Predis\Client::class, true) && !class_exists(\RedisSentinel::class) && !class_exists(Sentinel::class)) { + throw new CacheException(\sprintf('Cannot use Redis Sentinel: class "%s" does not extend "Predis\Client" and neither ext-redis >= 5.2 nor ext-relay have been found.', $class)); + } + + $isRedisExt = is_a($class, \Redis::class, true); + $isRelayExt = !$isRedisExt && is_a($class, Relay::class, true); + + if ($isRedisExt || $isRelayExt) { + $connect = $params['persistent'] || $params['persistent_id'] ? 'pconnect' : 'connect'; + + $initializer = static function () use ($class, $isRedisExt, $connect, $params, $auth, $hosts, $tls) { + $sentinelClass = $isRedisExt ? \RedisSentinel::class : Sentinel::class; + $redis = new $class(); + $hostIndex = 0; + do { + $host = $hosts[$hostIndex]['host'] ?? $hosts[$hostIndex]['path']; + $port = $hosts[$hostIndex]['port'] ?? 0; + $passAuth = isset($params['auth']) && (!$isRedisExt || \defined('Redis::OPT_NULL_MULTIBULK_AS_NULL')); + $address = false; + + if (isset($hosts[$hostIndex]['host']) && $tls) { + $host = 'tls://'.$host; + } + + if (!isset($params['redis_sentinel'])) { + break; + } + + try { + if (version_compare(phpversion('redis'), '6.0.0', '>=') && $isRedisExt) { + $options = [ + 'host' => $host, + 'port' => $port, + 'connectTimeout' => (float) $params['timeout'], + 'persistent' => $params['persistent_id'], + 'retryInterval' => (int) $params['retry_interval'], + 'readTimeout' => (float) $params['read_timeout'], + ]; + + if ($passAuth) { + $options['auth'] = $params['auth']; + } + + $sentinel = new \RedisSentinel($options); + } else { + $extra = $passAuth ? [$params['auth']] : []; + + $sentinel = @new $sentinelClass($host, $port, $params['timeout'], (string) $params['persistent_id'], $params['retry_interval'], $params['read_timeout'], ...$extra); + } + + if ($address = @$sentinel->getMasterAddrByName($params['redis_sentinel'])) { + [$host, $port] = $address; + } + } catch (\RedisException|\Relay\Exception $redisException) { + } + } while (++$hostIndex < \count($hosts) && !$address); + + if (isset($params['redis_sentinel']) && !$address) { + throw new InvalidArgumentException(\sprintf('Failed to retrieve master information from sentinel "%s".', $params['redis_sentinel']), previous: $redisException ?? null); + } + + try { + $extra = [ + 'stream' => $params['ssl'] ?? null, + ]; + $booleanStreamOptions = [ + 'allow_self_signed', + 'capture_peer_cert', + 'capture_peer_cert_chain', + 'disable_compression', + 'SNI_enabled', + 'verify_peer', + 'verify_peer_name', + ]; + + foreach ($extra['stream'] ?? [] as $streamOption => $value) { + if (\in_array($streamOption, $booleanStreamOptions, true) && \is_string($value)) { + $extra['stream'][$streamOption] = filter_var($value, \FILTER_VALIDATE_BOOL); + } + } + + if (isset($params['auth'])) { + $extra['auth'] = $params['auth']; + } + @$redis->{$connect}($host, $port, (float) $params['timeout'], (string) $params['persistent_id'], $params['retry_interval'], $params['read_timeout'], ...\defined('Redis::SCAN_PREFIX') || !$isRedisExt ? [$extra] : []); + + set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; }); + try { + $isConnected = $redis->isConnected(); + } finally { + restore_error_handler(); + } + if (!$isConnected) { + $error = preg_match('/^Redis::p?connect\(\): (.*)/', $error ?? $redis->getLastError() ?? '', $error) ? \sprintf(' (%s)', $error[1]) : ''; + throw new InvalidArgumentException('Redis connection failed: '.$error.'.'); + } + + if ((null !== $auth && !$redis->auth($auth)) + // Due to a bug in phpredis we must always select the dbindex if persistent pooling is enabled + // @see https://github.com/phpredis/phpredis/issues/1920 + // @see https://github.com/symfony/symfony/issues/51578 + || (($params['dbindex'] || ('pconnect' === $connect && '0' !== \ini_get('redis.pconnect.pooling_enabled'))) && !$redis->select($params['dbindex'])) + ) { + $e = preg_replace('/^ERR /', '', $redis->getLastError()); + throw new InvalidArgumentException('Redis connection failed: '.$e.'.'); + } + + if (0 < $params['tcp_keepalive'] && (!$isRedisExt || \defined('Redis::OPT_TCP_KEEPALIVE'))) { + $redis->setOption($isRedisExt ? \Redis::OPT_TCP_KEEPALIVE : Relay::OPT_TCP_KEEPALIVE, $params['tcp_keepalive']); + } + } catch (\RedisException|\Relay\Exception $e) { + throw new InvalidArgumentException('Redis connection failed: '.$e->getMessage()); + } + + return $redis; + }; + + if ($params['lazy']) { + $redis = $isRedisExt ? RedisProxy::createLazyProxy($initializer) : RelayProxy::createLazyProxy($initializer); + } else { + $redis = $initializer(); + } + } elseif (is_a($class, \RedisArray::class, true)) { + foreach ($hosts as $i => $host) { + $hosts[$i] = match ($host['scheme']) { + 'tcp' => $host['host'].':'.$host['port'], + 'tls' => 'tls://'.$host['host'].':'.$host['port'], + default => $host['path'], + }; + } + $params['lazy_connect'] = $params['lazy'] ?? true; + $params['connect_timeout'] = $params['timeout']; + + try { + $redis = new $class($hosts, $params); + } catch (\RedisClusterException $e) { + throw new InvalidArgumentException('Redis connection failed: '.$e->getMessage()); + } + + if (0 < $params['tcp_keepalive'] && (!$isRedisExt || \defined('Redis::OPT_TCP_KEEPALIVE'))) { + $redis->setOption($isRedisExt ? \Redis::OPT_TCP_KEEPALIVE : Relay::OPT_TCP_KEEPALIVE, $params['tcp_keepalive']); + } + } elseif (is_a($class, \RedisCluster::class, true)) { + $initializer = static function () use ($isRedisExt, $class, $params, $hosts) { + foreach ($hosts as $i => $host) { + $hosts[$i] = match ($host['scheme']) { + 'tcp' => $host['host'].':'.$host['port'], + 'tls' => 'tls://'.$host['host'].':'.$host['port'], + default => $host['path'], + }; + } + + try { + $redis = new $class(null, $hosts, $params['timeout'], $params['read_timeout'], (bool) $params['persistent'], $params['auth'] ?? '', ...\defined('Redis::SCAN_PREFIX') ? [$params['ssl'] ?? null] : []); + } catch (\RedisClusterException $e) { + throw new InvalidArgumentException('Redis connection failed: '.$e->getMessage()); + } + + if (0 < $params['tcp_keepalive'] && (!$isRedisExt || \defined('Redis::OPT_TCP_KEEPALIVE'))) { + $redis->setOption($isRedisExt ? \Redis::OPT_TCP_KEEPALIVE : Relay::OPT_TCP_KEEPALIVE, $params['tcp_keepalive']); + } + $redis->setOption(\RedisCluster::OPT_SLAVE_FAILOVER, match ($params['failover']) { + 'error' => \RedisCluster::FAILOVER_ERROR, + 'distribute' => \RedisCluster::FAILOVER_DISTRIBUTE, + 'slaves' => \RedisCluster::FAILOVER_DISTRIBUTE_SLAVES, + 'none' => \RedisCluster::FAILOVER_NONE, + }); + + return $redis; + }; + + $redis = $params['lazy'] ? RedisClusterProxy::createLazyProxy($initializer) : $initializer(); + } elseif (is_a($class, \Predis\ClientInterface::class, true)) { + if ($params['redis_cluster']) { + $params['cluster'] = 'redis'; + } elseif (isset($params['redis_sentinel'])) { + $params['replication'] = 'sentinel'; + $params['service'] = $params['redis_sentinel']; + } + $params += ['parameters' => []]; + $params['parameters'] += [ + 'persistent' => $params['persistent'], + 'timeout' => $params['timeout'], + 'read_write_timeout' => $params['read_timeout'], + 'tcp_nodelay' => true, + ]; + if ($params['dbindex']) { + $params['parameters']['database'] = $params['dbindex']; + } + if (null !== $auth) { + if (\is_array($auth)) { + // ACL + $params['parameters']['username'] = $auth[0]; + $params['parameters']['password'] = $auth[1]; + } else { + $params['parameters']['password'] = $auth; + } + } + + if (isset($params['ssl'])) { + foreach ($hosts as $i => $host) { + $hosts[$i]['ssl'] ??= $params['ssl']; + } + } + + if (1 === \count($hosts) && !($params['redis_cluster'] || $params['redis_sentinel'])) { + $hosts = $hosts[0]; + } elseif (\in_array($params['failover'], ['slaves', 'distribute'], true) && !isset($params['replication'])) { + $params['replication'] = true; + $hosts[0] += ['alias' => 'master']; + } + $params['exceptions'] = false; + + $redis = new $class($hosts, array_diff_key($params, self::$defaultConnectionOptions)); + if (isset($params['redis_sentinel'])) { + $redis->getConnection()->setSentinelTimeout($params['timeout']); + } + } elseif (class_exists($class, false)) { + throw new InvalidArgumentException(\sprintf('"%s" is not a subclass of "Redis", "RedisArray", "RedisCluster", "Relay\Relay" nor "Predis\ClientInterface".', $class)); + } else { + throw new InvalidArgumentException(\sprintf('Class "%s" does not exist.', $class)); + } + + return $redis; + } + + protected function doFetch(array $ids): iterable + { + if (!$ids) { + return []; + } + + $result = []; + + if ($this->redis instanceof \Predis\ClientInterface && ($this->redis->getConnection() instanceof ClusterInterface || $this->redis->getConnection() instanceof Predis2ClusterInterface)) { + $values = $this->pipeline(function () use ($ids) { + foreach ($ids as $id) { + yield 'get' => [$id]; + } + }); + } else { + $values = $this->redis->mget($ids); + + if (!\is_array($values) || \count($values) !== \count($ids)) { + return []; + } + + $values = array_combine($ids, $values); + } + + foreach ($values as $id => $v) { + if ($v) { + $result[$id] = $this->marshaller->unmarshall($v); + } + } + + return $result; + } + + protected function doHave(string $id): bool + { + return (bool) $this->redis->exists($id); + } + + protected function doClear(string $namespace): bool + { + if ($this->redis instanceof \Predis\ClientInterface) { + $prefix = $this->redis->getOptions()->prefix ? $this->redis->getOptions()->prefix->getPrefix() : ''; + $prefixLen = \strlen($prefix ?? ''); + } + + $cleared = true; + $hosts = $this->getHosts(); + $host = reset($hosts); + if ($host instanceof \Predis\Client && $host->getConnection() instanceof ReplicationInterface) { + // Predis supports info command only on the master in replication environments + $hosts = [$host->getClientFor('master')]; + } + + foreach ($hosts as $host) { + if (!isset($namespace[0])) { + $cleared = $host->flushDb() && $cleared; + continue; + } + + $info = $host->info('Server'); + $info = !$info instanceof ErrorInterface ? $info['Server'] ?? $info : ['redis_version' => '2.0']; + + if ($host instanceof Relay) { + $prefix = Relay::SCAN_PREFIX & $host->getOption(Relay::OPT_SCAN) ? '' : $host->getOption(Relay::OPT_PREFIX); + $prefixLen = \strlen($host->getOption(Relay::OPT_PREFIX) ?? ''); + } elseif (!$host instanceof \Predis\ClientInterface) { + $prefix = \defined('Redis::SCAN_PREFIX') && (\Redis::SCAN_PREFIX & $host->getOption(\Redis::OPT_SCAN)) ? '' : $host->getOption(\Redis::OPT_PREFIX); + $prefixLen = \strlen($host->getOption(\Redis::OPT_PREFIX) ?? ''); + } + $pattern = $prefix.$namespace.'*'; + + if (!version_compare($info['redis_version'], '2.8', '>=')) { + // As documented in Redis documentation (http://redis.io/commands/keys) using KEYS + // can hang your server when it is executed against large databases (millions of items). + // Whenever you hit this scale, you should really consider upgrading to Redis 2.8 or above. + $unlink = version_compare($info['redis_version'], '4.0', '>=') ? 'UNLINK' : 'DEL'; + $args = $this->redis instanceof \Predis\ClientInterface ? [0, $pattern] : [[$pattern], 0]; + $cleared = $host->eval("local keys=redis.call('KEYS',ARGV[1]) for i=1,#keys,5000 do redis.call('$unlink',unpack(keys,i,math.min(i+4999,#keys))) end return 1", $args[0], $args[1]) && $cleared; + continue; + } + + $cursor = null; + do { + $keys = $host instanceof \Predis\ClientInterface ? $host->scan($cursor ?? 0, 'MATCH', $pattern, 'COUNT', 1000) : $host->scan($cursor, $pattern, 1000); + if (isset($keys[1]) && \is_array($keys[1])) { + $cursor = $keys[0]; + $keys = $keys[1]; + } + if ($keys) { + if ($prefixLen) { + foreach ($keys as $i => $key) { + $keys[$i] = substr($key, $prefixLen); + } + } + $this->doDelete($keys); + } + } while ($cursor); + } + + return $cleared; + } + + protected function doDelete(array $ids): bool + { + if (!$ids) { + return true; + } + + if ($this->redis instanceof \Predis\ClientInterface && ($this->redis->getConnection() instanceof ClusterInterface || $this->redis->getConnection() instanceof Predis2ClusterInterface)) { + static $del; + $del ??= (class_exists(UNLINK::class) ? 'unlink' : 'del'); + + $this->pipeline(function () use ($ids, $del) { + foreach ($ids as $id) { + yield $del => [$id]; + } + })->rewind(); + } else { + static $unlink = true; + + if ($unlink) { + try { + $unlink = false !== $this->redis->unlink($ids); + } catch (\Throwable) { + $unlink = false; + } + } + + if (!$unlink) { + $this->redis->del($ids); + } + } + + return true; + } + + protected function doSave(array $values, int $lifetime): array|bool + { + if (!$values = $this->marshaller->marshall($values, $failed)) { + return $failed; + } + + $results = $this->pipeline(function () use ($values, $lifetime) { + foreach ($values as $id => $value) { + if (0 >= $lifetime) { + yield 'set' => [$id, $value]; + } else { + yield 'setEx' => [$id, $lifetime, $value]; + } + } + }); + + foreach ($results as $id => $result) { + if (true !== $result && (!$result instanceof Status || Status::get('OK') !== $result)) { + $failed[] = $id; + } + } + + return $failed; + } + + private function pipeline(\Closure $generator, ?object $redis = null): \Generator + { + $ids = []; + $redis ??= $this->redis; + + if ($redis instanceof \RedisCluster || ($redis instanceof \Predis\ClientInterface && ($redis->getConnection() instanceof RedisCluster || $redis->getConnection() instanceof Predis2RedisCluster))) { + // phpredis & predis don't support pipelining with RedisCluster + // see https://github.com/phpredis/phpredis/blob/develop/cluster.markdown#pipelining + // see https://github.com/nrk/predis/issues/267#issuecomment-123781423 + $results = []; + foreach ($generator() as $command => $args) { + $results[] = $redis->{$command}(...$args); + $ids[] = 'eval' === $command ? ($redis instanceof \Predis\ClientInterface ? $args[2] : $args[1][0]) : $args[0]; + } + } elseif ($redis instanceof \Predis\ClientInterface) { + $results = $redis->pipeline(static function ($redis) use ($generator, &$ids) { + foreach ($generator() as $command => $args) { + $redis->{$command}(...$args); + $ids[] = 'eval' === $command ? $args[2] : $args[0]; + } + }); + } elseif ($redis instanceof \RedisArray) { + $connections = $results = []; + foreach ($generator() as $command => $args) { + $id = 'eval' === $command ? $args[1][0] : $args[0]; + if (!isset($connections[$h = $redis->_target($id)])) { + $connections[$h] = [$redis->_instance($h), -1]; + $connections[$h][0]->multi(\Redis::PIPELINE); + } + $connections[$h][0]->{$command}(...$args); + $results[] = [$h, ++$connections[$h][1]]; + $ids[] = $id; + } + foreach ($connections as $h => $c) { + $connections[$h] = $c[0]->exec(); + } + foreach ($results as $k => [$h, $c]) { + $results[$k] = $connections[$h][$c]; + } + } else { + $redis->multi($redis instanceof Relay ? Relay::PIPELINE : \Redis::PIPELINE); + foreach ($generator() as $command => $args) { + $redis->{$command}(...$args); + $ids[] = 'eval' === $command ? $args[1][0] : $args[0]; + } + $results = $redis->exec(); + } + + if (!$redis instanceof \Predis\ClientInterface && 'eval' === $command && $redis->getLastError()) { + $e = $redis instanceof Relay ? new \Relay\Exception($redis->getLastError()) : new \RedisException($redis->getLastError()); + $results = array_map(fn ($v) => false === $v ? $e : $v, (array) $results); + } + + if (\is_bool($results)) { + return; + } + + foreach ($ids as $k => $id) { + yield $id => $results[$k]; + } + } + + private function getHosts(): array + { + $hosts = [$this->redis]; + if ($this->redis instanceof \Predis\ClientInterface) { + $connection = $this->redis->getConnection(); + if (($connection instanceof ClusterInterface || $connection instanceof Predis2ClusterInterface) && $connection instanceof \Traversable) { + $hosts = []; + foreach ($connection as $c) { + $hosts[] = new \Predis\Client($c); + } + } + } elseif ($this->redis instanceof \RedisArray) { + $hosts = []; + foreach ($this->redis->_hosts() as $host) { + $hosts[] = $this->redis->_instance($host); + } + } elseif ($this->redis instanceof \RedisCluster) { + $hosts = []; + foreach ($this->redis->_masters() as $host) { + $hosts[] = new RedisClusterNodeProxy($host, $this->redis); + } + } + + return $hosts; + } +} diff --git a/vendor/symfony/cache/Traits/Relay/CopyTrait.php b/vendor/symfony/cache/Traits/Relay/CopyTrait.php new file mode 100644 index 0000000..84d52f4 --- /dev/null +++ b/vendor/symfony/cache/Traits/Relay/CopyTrait.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Traits\Relay; + +if (version_compare(phpversion('relay'), '0.8.1', '>=')) { + /** + * @internal + */ + trait CopyTrait + { + public function copy($src, $dst, $options = null): \Relay\Relay|bool + { + return $this->initializeLazyObject()->copy(...\func_get_args()); + } + } +} else { + /** + * @internal + */ + trait CopyTrait + { + public function copy($src, $dst, $options = null): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->copy(...\func_get_args()); + } + } +} diff --git a/vendor/symfony/cache/Traits/Relay/GeosearchTrait.php b/vendor/symfony/cache/Traits/Relay/GeosearchTrait.php new file mode 100644 index 0000000..a358f80 --- /dev/null +++ b/vendor/symfony/cache/Traits/Relay/GeosearchTrait.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Traits\Relay; + +if (version_compare(phpversion('relay'), '0.9.0', '>=')) { + /** + * @internal + */ + trait GeosearchTrait + { + public function geosearch($key, $position, $shape, $unit, $options = []): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->geosearch(...\func_get_args()); + } + } +} else { + /** + * @internal + */ + trait GeosearchTrait + { + public function geosearch($key, $position, $shape, $unit, $options = []): \Relay\Relay|array + { + return $this->initializeLazyObject()->geosearch(...\func_get_args()); + } + } +} diff --git a/vendor/symfony/cache/Traits/Relay/GetrangeTrait.php b/vendor/symfony/cache/Traits/Relay/GetrangeTrait.php new file mode 100644 index 0000000..f26333e --- /dev/null +++ b/vendor/symfony/cache/Traits/Relay/GetrangeTrait.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Traits\Relay; + +if (version_compare(phpversion('relay'), '0.9.0', '>=')) { + /** + * @internal + */ + trait GetrangeTrait + { + public function getrange($key, $start, $end): mixed + { + return $this->initializeLazyObject()->getrange(...\func_get_args()); + } + } +} else { + /** + * @internal + */ + trait GetrangeTrait + { + public function getrange($key, $start, $end): \Relay\Relay|false|string + { + return $this->initializeLazyObject()->getrange(...\func_get_args()); + } + } +} diff --git a/vendor/symfony/cache/Traits/Relay/HsetTrait.php b/vendor/symfony/cache/Traits/Relay/HsetTrait.php new file mode 100644 index 0000000..8334244 --- /dev/null +++ b/vendor/symfony/cache/Traits/Relay/HsetTrait.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Traits\Relay; + +if (version_compare(phpversion('relay'), '0.9.0', '>=')) { + /** + * @internal + */ + trait HsetTrait + { + public function hset($key, ...$keys_and_vals): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->hset(...\func_get_args()); + } + } +} else { + /** + * @internal + */ + trait HsetTrait + { + public function hset($key, $mem, $val, ...$kvals): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->hset(...\func_get_args()); + } + } +} diff --git a/vendor/symfony/cache/Traits/Relay/MoveTrait.php b/vendor/symfony/cache/Traits/Relay/MoveTrait.php new file mode 100644 index 0000000..18086f6 --- /dev/null +++ b/vendor/symfony/cache/Traits/Relay/MoveTrait.php @@ -0,0 +1,46 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Traits\Relay; + +if (version_compare(phpversion('relay'), '0.9.0', '>=')) { + /** + * @internal + */ + trait MoveTrait + { + public function blmove($srckey, $dstkey, $srcpos, $dstpos, $timeout): mixed + { + return $this->initializeLazyObject()->blmove(...\func_get_args()); + } + + public function lmove($srckey, $dstkey, $srcpos, $dstpos): mixed + { + return $this->initializeLazyObject()->lmove(...\func_get_args()); + } + } +} else { + /** + * @internal + */ + trait MoveTrait + { + public function blmove($srckey, $dstkey, $srcpos, $dstpos, $timeout): \Relay\Relay|false|string|null + { + return $this->initializeLazyObject()->blmove(...\func_get_args()); + } + + public function lmove($srckey, $dstkey, $srcpos, $dstpos): \Relay\Relay|false|string|null + { + return $this->initializeLazyObject()->lmove(...\func_get_args()); + } + } +} diff --git a/vendor/symfony/cache/Traits/Relay/NullableReturnTrait.php b/vendor/symfony/cache/Traits/Relay/NullableReturnTrait.php new file mode 100644 index 0000000..661ec47 --- /dev/null +++ b/vendor/symfony/cache/Traits/Relay/NullableReturnTrait.php @@ -0,0 +1,96 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Traits\Relay; + +if (version_compare(phpversion('relay'), '0.9.0', '>=')) { + /** + * @internal + */ + trait NullableReturnTrait + { + public function dump($key): \Relay\Relay|false|string|null + { + return $this->initializeLazyObject()->dump(...\func_get_args()); + } + + public function geodist($key, $src, $dst, $unit = null): \Relay\Relay|false|float|null + { + return $this->initializeLazyObject()->geodist(...\func_get_args()); + } + + public function hrandfield($hash, $options = null): \Relay\Relay|array|false|string|null + { + return $this->initializeLazyObject()->hrandfield(...\func_get_args()); + } + + public function xadd($key, $id, $values, $maxlen = 0, $approx = false, $nomkstream = false): \Relay\Relay|false|string|null + { + return $this->initializeLazyObject()->xadd(...\func_get_args()); + } + + public function zrank($key, $rank, $withscore = false): \Relay\Relay|array|false|int|null + { + return $this->initializeLazyObject()->zrank(...\func_get_args()); + } + + public function zrevrank($key, $rank, $withscore = false): \Relay\Relay|array|false|int|null + { + return $this->initializeLazyObject()->zrevrank(...\func_get_args()); + } + + public function zscore($key, $member): \Relay\Relay|false|float|null + { + return $this->initializeLazyObject()->zscore(...\func_get_args()); + } + } +} else { + /** + * @internal + */ + trait NullableReturnTrait + { + public function dump($key): \Relay\Relay|false|string + { + return $this->initializeLazyObject()->dump(...\func_get_args()); + } + + public function geodist($key, $src, $dst, $unit = null): \Relay\Relay|false|float + { + return $this->initializeLazyObject()->geodist(...\func_get_args()); + } + + public function hrandfield($hash, $options = null): \Relay\Relay|array|false|string + { + return $this->initializeLazyObject()->hrandfield(...\func_get_args()); + } + + public function xadd($key, $id, $values, $maxlen = 0, $approx = false, $nomkstream = false): \Relay\Relay|false|string + { + return $this->initializeLazyObject()->xadd(...\func_get_args()); + } + + public function zrank($key, $rank, $withscore = false): \Relay\Relay|array|false|int + { + return $this->initializeLazyObject()->zrank(...\func_get_args()); + } + + public function zrevrank($key, $rank, $withscore = false): \Relay\Relay|array|false|int + { + return $this->initializeLazyObject()->zrevrank(...\func_get_args()); + } + + public function zscore($key, $member): \Relay\Relay|false|float + { + return $this->initializeLazyObject()->zscore(...\func_get_args()); + } + } +} diff --git a/vendor/symfony/cache/Traits/Relay/PfcountTrait.php b/vendor/symfony/cache/Traits/Relay/PfcountTrait.php new file mode 100644 index 0000000..84e5c59 --- /dev/null +++ b/vendor/symfony/cache/Traits/Relay/PfcountTrait.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Traits\Relay; + +if (version_compare(phpversion('relay'), '0.9.0', '>=')) { + /** + * @internal + */ + trait PfcountTrait + { + public function pfcount($key_or_keys): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->pfcount(...\func_get_args()); + } + } +} else { + /** + * @internal + */ + trait PfcountTrait + { + public function pfcount($key): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->pfcount(...\func_get_args()); + } + } +} diff --git a/vendor/symfony/cache/Traits/RelayProxy.php b/vendor/symfony/cache/Traits/RelayProxy.php new file mode 100644 index 0000000..e0ca887 --- /dev/null +++ b/vendor/symfony/cache/Traits/RelayProxy.php @@ -0,0 +1,1265 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Traits; + +use Symfony\Component\Cache\Traits\Relay\CopyTrait; +use Symfony\Component\Cache\Traits\Relay\GeosearchTrait; +use Symfony\Component\Cache\Traits\Relay\GetrangeTrait; +use Symfony\Component\Cache\Traits\Relay\HsetTrait; +use Symfony\Component\Cache\Traits\Relay\MoveTrait; +use Symfony\Component\Cache\Traits\Relay\NullableReturnTrait; +use Symfony\Component\Cache\Traits\Relay\PfcountTrait; +use Symfony\Component\VarExporter\LazyObjectInterface; +use Symfony\Contracts\Service\ResetInterface; + +// Help opcache.preload discover always-needed symbols +class_exists(\Symfony\Component\VarExporter\Internal\Hydrator::class); +class_exists(\Symfony\Component\VarExporter\Internal\LazyObjectRegistry::class); +class_exists(\Symfony\Component\VarExporter\Internal\LazyObjectState::class); + +/** + * @internal + */ +class RelayProxy extends \Relay\Relay implements ResetInterface, LazyObjectInterface +{ + use CopyTrait; + use GeosearchTrait; + use GetrangeTrait; + use HsetTrait; + use MoveTrait; + use NullableReturnTrait; + use PfcountTrait; + use RedisProxyTrait { + resetLazyObject as reset; + } + use RelayProxyTrait; + + public function __construct($host = null, $port = 6379, $connect_timeout = 0.0, $command_timeout = 0.0, #[\SensitiveParameter] $context = [], $database = 0) + { + $this->initializeLazyObject()->__construct(...\func_get_args()); + } + + public function connect($host, $port = 6379, $timeout = 0.0, $persistent_id = null, $retry_interval = 0, $read_timeout = 0.0, #[\SensitiveParameter] $context = [], $database = 0): bool + { + return $this->initializeLazyObject()->connect(...\func_get_args()); + } + + public function pconnect($host, $port = 6379, $timeout = 0.0, $persistent_id = null, $retry_interval = 0, $read_timeout = 0.0, #[\SensitiveParameter] $context = [], $database = 0): bool + { + return $this->initializeLazyObject()->pconnect(...\func_get_args()); + } + + public function close(): bool + { + return $this->initializeLazyObject()->close(...\func_get_args()); + } + + public function pclose(): bool + { + return $this->initializeLazyObject()->pclose(...\func_get_args()); + } + + public function listen($callback): bool + { + return $this->initializeLazyObject()->listen(...\func_get_args()); + } + + public function onFlushed($callback): bool + { + return $this->initializeLazyObject()->onFlushed(...\func_get_args()); + } + + public function onInvalidated($callback, $pattern = null): bool + { + return $this->initializeLazyObject()->onInvalidated(...\func_get_args()); + } + + public function dispatchEvents(): false|int + { + return $this->initializeLazyObject()->dispatchEvents(...\func_get_args()); + } + + public function getOption($option): mixed + { + return $this->initializeLazyObject()->getOption(...\func_get_args()); + } + + public function option($option, $value = null): mixed + { + return $this->initializeLazyObject()->option(...\func_get_args()); + } + + public function setOption($option, $value): bool + { + return $this->initializeLazyObject()->setOption(...\func_get_args()); + } + + public function addIgnorePatterns(...$pattern): int + { + return $this->initializeLazyObject()->addIgnorePatterns(...\func_get_args()); + } + + public function addAllowPatterns(...$pattern): int + { + return $this->initializeLazyObject()->addAllowPatterns(...\func_get_args()); + } + + public function getTimeout(): false|float + { + return $this->initializeLazyObject()->getTimeout(...\func_get_args()); + } + + public function timeout(): false|float + { + return $this->initializeLazyObject()->timeout(...\func_get_args()); + } + + public function getReadTimeout(): false|float + { + return $this->initializeLazyObject()->getReadTimeout(...\func_get_args()); + } + + public function readTimeout(): false|float + { + return $this->initializeLazyObject()->readTimeout(...\func_get_args()); + } + + public function getBytes(): array + { + return $this->initializeLazyObject()->getBytes(...\func_get_args()); + } + + public function bytes(): array + { + return $this->initializeLazyObject()->bytes(...\func_get_args()); + } + + public function getHost(): false|string + { + return $this->initializeLazyObject()->getHost(...\func_get_args()); + } + + public function isConnected(): bool + { + return $this->initializeLazyObject()->isConnected(...\func_get_args()); + } + + public function getPort(): false|int + { + return $this->initializeLazyObject()->getPort(...\func_get_args()); + } + + public function getAuth(): mixed + { + return $this->initializeLazyObject()->getAuth(...\func_get_args()); + } + + public function getDbNum(): mixed + { + return $this->initializeLazyObject()->getDbNum(...\func_get_args()); + } + + public function _serialize($value): mixed + { + return $this->initializeLazyObject()->_serialize(...\func_get_args()); + } + + public function _unserialize($value): mixed + { + return $this->initializeLazyObject()->_unserialize(...\func_get_args()); + } + + public function _compress($value): string + { + return $this->initializeLazyObject()->_compress(...\func_get_args()); + } + + public function _uncompress($value): string + { + return $this->initializeLazyObject()->_uncompress(...\func_get_args()); + } + + public function _pack($value): string + { + return $this->initializeLazyObject()->_pack(...\func_get_args()); + } + + public function _unpack($value): mixed + { + return $this->initializeLazyObject()->_unpack(...\func_get_args()); + } + + public function _prefix($value): string + { + return $this->initializeLazyObject()->_prefix(...\func_get_args()); + } + + public function getLastError(): ?string + { + return $this->initializeLazyObject()->getLastError(...\func_get_args()); + } + + public function clearLastError(): bool + { + return $this->initializeLazyObject()->clearLastError(...\func_get_args()); + } + + public function endpointId(): false|string + { + return $this->initializeLazyObject()->endpointId(...\func_get_args()); + } + + public function getPersistentID(): false|string + { + return $this->initializeLazyObject()->getPersistentID(...\func_get_args()); + } + + public function socketId(): false|string + { + return $this->initializeLazyObject()->socketId(...\func_get_args()); + } + + public function rawCommand($cmd, ...$args): mixed + { + return $this->initializeLazyObject()->rawCommand(...\func_get_args()); + } + + public function select($db): \Relay\Relay|bool + { + return $this->initializeLazyObject()->select(...\func_get_args()); + } + + public function auth(#[\SensitiveParameter] $auth): bool + { + return $this->initializeLazyObject()->auth(...\func_get_args()); + } + + public function info(...$sections): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->info(...\func_get_args()); + } + + public function flushdb($sync = null): \Relay\Relay|bool + { + return $this->initializeLazyObject()->flushdb(...\func_get_args()); + } + + public function flushall($sync = null): \Relay\Relay|bool + { + return $this->initializeLazyObject()->flushall(...\func_get_args()); + } + + public function fcall($name, $keys = [], $argv = [], $handler = null): mixed + { + return $this->initializeLazyObject()->fcall(...\func_get_args()); + } + + public function fcall_ro($name, $keys = [], $argv = [], $handler = null): mixed + { + return $this->initializeLazyObject()->fcall_ro(...\func_get_args()); + } + + public function function($op, ...$args): mixed + { + return $this->initializeLazyObject()->function(...\func_get_args()); + } + + public function dbsize(): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->dbsize(...\func_get_args()); + } + + public function replicaof($host = null, $port = 0): \Relay\Relay|bool + { + return $this->initializeLazyObject()->replicaof(...\func_get_args()); + } + + public function waitaof($numlocal, $numremote, $timeout): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->waitaof(...\func_get_args()); + } + + public function restore($key, $ttl, $value, $options = null): \Relay\Relay|bool + { + return $this->initializeLazyObject()->restore(...\func_get_args()); + } + + public function migrate($host, $port, $key, $dstdb, $timeout, $copy = false, $replace = false, #[\SensitiveParameter] $credentials = null): \Relay\Relay|bool + { + return $this->initializeLazyObject()->migrate(...\func_get_args()); + } + + public function echo($arg): \Relay\Relay|bool|string + { + return $this->initializeLazyObject()->echo(...\func_get_args()); + } + + public function ping($arg = null): \Relay\Relay|bool|string + { + return $this->initializeLazyObject()->ping(...\func_get_args()); + } + + public function idleTime(): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->idleTime(...\func_get_args()); + } + + public function randomkey(): \Relay\Relay|bool|null|string + { + return $this->initializeLazyObject()->randomkey(...\func_get_args()); + } + + public function time(): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->time(...\func_get_args()); + } + + public function bgrewriteaof(): \Relay\Relay|bool + { + return $this->initializeLazyObject()->bgrewriteaof(...\func_get_args()); + } + + public function lastsave(): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->lastsave(...\func_get_args()); + } + + public function lcs($key1, $key2, $options = null): mixed + { + return $this->initializeLazyObject()->lcs(...\func_get_args()); + } + + public function bgsave($schedule = false): \Relay\Relay|bool + { + return $this->initializeLazyObject()->bgsave(...\func_get_args()); + } + + public function save(): \Relay\Relay|bool + { + return $this->initializeLazyObject()->save(...\func_get_args()); + } + + public function role(): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->role(...\func_get_args()); + } + + public function ttl($key): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->ttl(...\func_get_args()); + } + + public function pttl($key): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->pttl(...\func_get_args()); + } + + public function exists(...$keys): \Relay\Relay|bool|int + { + return $this->initializeLazyObject()->exists(...\func_get_args()); + } + + public function eval($script, $args = [], $num_keys = 0): mixed + { + return $this->initializeLazyObject()->eval(...\func_get_args()); + } + + public function eval_ro($script, $args = [], $num_keys = 0): mixed + { + return $this->initializeLazyObject()->eval_ro(...\func_get_args()); + } + + public function evalsha($sha, $args = [], $num_keys = 0): mixed + { + return $this->initializeLazyObject()->evalsha(...\func_get_args()); + } + + public function evalsha_ro($sha, $args = [], $num_keys = 0): mixed + { + return $this->initializeLazyObject()->evalsha_ro(...\func_get_args()); + } + + public function client($operation, ...$args): mixed + { + return $this->initializeLazyObject()->client(...\func_get_args()); + } + + public function geoadd($key, $lng, $lat, $member, ...$other_triples_and_options): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->geoadd(...\func_get_args()); + } + + public function geohash($key, $member, ...$other_members): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->geohash(...\func_get_args()); + } + + public function georadius($key, $lng, $lat, $radius, $unit, $options = []): mixed + { + return $this->initializeLazyObject()->georadius(...\func_get_args()); + } + + public function georadiusbymember($key, $member, $radius, $unit, $options = []): mixed + { + return $this->initializeLazyObject()->georadiusbymember(...\func_get_args()); + } + + public function georadiusbymember_ro($key, $member, $radius, $unit, $options = []): mixed + { + return $this->initializeLazyObject()->georadiusbymember_ro(...\func_get_args()); + } + + public function georadius_ro($key, $lng, $lat, $radius, $unit, $options = []): mixed + { + return $this->initializeLazyObject()->georadius_ro(...\func_get_args()); + } + + public function geosearchstore($dst, $src, $position, $shape, $unit, $options = []): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->geosearchstore(...\func_get_args()); + } + + public function get($key): mixed + { + return $this->initializeLazyObject()->get(...\func_get_args()); + } + + public function getset($key, $value): mixed + { + return $this->initializeLazyObject()->getset(...\func_get_args()); + } + + public function setrange($key, $start, $value): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->setrange(...\func_get_args()); + } + + public function getbit($key, $pos): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->getbit(...\func_get_args()); + } + + public function bitcount($key, $start = 0, $end = -1, $by_bit = false): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->bitcount(...\func_get_args()); + } + + public function bitfield($key, ...$args): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->bitfield(...\func_get_args()); + } + + public function config($operation, $key = null, $value = null): \Relay\Relay|array|bool + { + return $this->initializeLazyObject()->config(...\func_get_args()); + } + + public function command(...$args): \Relay\Relay|array|false|int + { + return $this->initializeLazyObject()->command(...\func_get_args()); + } + + public function bitop($operation, $dstkey, $srckey, ...$other_keys): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->bitop(...\func_get_args()); + } + + public function bitpos($key, $bit, $start = null, $end = null, $bybit = false): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->bitpos(...\func_get_args()); + } + + public function setbit($key, $pos, $val): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->setbit(...\func_get_args()); + } + + public function acl($cmd, ...$args): mixed + { + return $this->initializeLazyObject()->acl(...\func_get_args()); + } + + public function append($key, $value): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->append(...\func_get_args()); + } + + public function set($key, $value, $options = null): mixed + { + return $this->initializeLazyObject()->set(...\func_get_args()); + } + + public function getex($key, $options = null): mixed + { + return $this->initializeLazyObject()->getex(...\func_get_args()); + } + + public function getdel($key): mixed + { + return $this->initializeLazyObject()->getdel(...\func_get_args()); + } + + public function setex($key, $seconds, $value): \Relay\Relay|bool + { + return $this->initializeLazyObject()->setex(...\func_get_args()); + } + + public function pfadd($key, $elements): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->pfadd(...\func_get_args()); + } + + public function pfmerge($dst, $srckeys): \Relay\Relay|bool + { + return $this->initializeLazyObject()->pfmerge(...\func_get_args()); + } + + public function psetex($key, $milliseconds, $value): \Relay\Relay|bool + { + return $this->initializeLazyObject()->psetex(...\func_get_args()); + } + + public function publish($channel, $message): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->publish(...\func_get_args()); + } + + public function pubsub($operation, ...$args): mixed + { + return $this->initializeLazyObject()->pubsub(...\func_get_args()); + } + + public function spublish($channel, $message): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->spublish(...\func_get_args()); + } + + public function setnx($key, $value): \Relay\Relay|bool + { + return $this->initializeLazyObject()->setnx(...\func_get_args()); + } + + public function mget($keys): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->mget(...\func_get_args()); + } + + public function move($key, $db): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->move(...\func_get_args()); + } + + public function mset($kvals): \Relay\Relay|bool + { + return $this->initializeLazyObject()->mset(...\func_get_args()); + } + + public function msetnx($kvals): \Relay\Relay|bool + { + return $this->initializeLazyObject()->msetnx(...\func_get_args()); + } + + public function rename($key, $newkey): \Relay\Relay|bool + { + return $this->initializeLazyObject()->rename(...\func_get_args()); + } + + public function renamenx($key, $newkey): \Relay\Relay|bool + { + return $this->initializeLazyObject()->renamenx(...\func_get_args()); + } + + public function del(...$keys): \Relay\Relay|bool|int + { + return $this->initializeLazyObject()->del(...\func_get_args()); + } + + public function unlink(...$keys): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->unlink(...\func_get_args()); + } + + public function expire($key, $seconds, $mode = null): \Relay\Relay|bool + { + return $this->initializeLazyObject()->expire(...\func_get_args()); + } + + public function pexpire($key, $milliseconds): \Relay\Relay|bool + { + return $this->initializeLazyObject()->pexpire(...\func_get_args()); + } + + public function expireat($key, $timestamp): \Relay\Relay|bool + { + return $this->initializeLazyObject()->expireat(...\func_get_args()); + } + + public function expiretime($key): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->expiretime(...\func_get_args()); + } + + public function pexpireat($key, $timestamp_ms): \Relay\Relay|bool + { + return $this->initializeLazyObject()->pexpireat(...\func_get_args()); + } + + public function pexpiretime($key): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->pexpiretime(...\func_get_args()); + } + + public function persist($key): \Relay\Relay|bool + { + return $this->initializeLazyObject()->persist(...\func_get_args()); + } + + public function type($key): \Relay\Relay|bool|int|string + { + return $this->initializeLazyObject()->type(...\func_get_args()); + } + + public function lrange($key, $start, $stop): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->lrange(...\func_get_args()); + } + + public function lpush($key, $mem, ...$mems): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->lpush(...\func_get_args()); + } + + public function rpush($key, $mem, ...$mems): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->rpush(...\func_get_args()); + } + + public function lpushx($key, $mem, ...$mems): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->lpushx(...\func_get_args()); + } + + public function rpushx($key, $mem, ...$mems): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->rpushx(...\func_get_args()); + } + + public function lset($key, $index, $mem): \Relay\Relay|bool + { + return $this->initializeLazyObject()->lset(...\func_get_args()); + } + + public function lpop($key, $count = 1): mixed + { + return $this->initializeLazyObject()->lpop(...\func_get_args()); + } + + public function lpos($key, $value, $options = null): \Relay\Relay|array|false|int|null + { + return $this->initializeLazyObject()->lpos(...\func_get_args()); + } + + public function rpop($key, $count = 1): mixed + { + return $this->initializeLazyObject()->rpop(...\func_get_args()); + } + + public function rpoplpush($source, $dest): mixed + { + return $this->initializeLazyObject()->rpoplpush(...\func_get_args()); + } + + public function brpoplpush($source, $dest, $timeout): mixed + { + return $this->initializeLazyObject()->brpoplpush(...\func_get_args()); + } + + public function blpop($key, $timeout_or_key, ...$extra_args): \Relay\Relay|array|false|null + { + return $this->initializeLazyObject()->blpop(...\func_get_args()); + } + + public function blmpop($timeout, $keys, $from, $count = 1): \Relay\Relay|array|false|null + { + return $this->initializeLazyObject()->blmpop(...\func_get_args()); + } + + public function bzmpop($timeout, $keys, $from, $count = 1): \Relay\Relay|array|false|null + { + return $this->initializeLazyObject()->bzmpop(...\func_get_args()); + } + + public function lmpop($keys, $from, $count = 1): \Relay\Relay|array|false|null + { + return $this->initializeLazyObject()->lmpop(...\func_get_args()); + } + + public function zmpop($keys, $from, $count = 1): \Relay\Relay|array|false|null + { + return $this->initializeLazyObject()->zmpop(...\func_get_args()); + } + + public function brpop($key, $timeout_or_key, ...$extra_args): \Relay\Relay|array|false|null + { + return $this->initializeLazyObject()->brpop(...\func_get_args()); + } + + public function bzpopmax($key, $timeout_or_key, ...$extra_args): \Relay\Relay|array|false|null + { + return $this->initializeLazyObject()->bzpopmax(...\func_get_args()); + } + + public function bzpopmin($key, $timeout_or_key, ...$extra_args): \Relay\Relay|array|false|null + { + return $this->initializeLazyObject()->bzpopmin(...\func_get_args()); + } + + public function object($op, $key): mixed + { + return $this->initializeLazyObject()->object(...\func_get_args()); + } + + public function geopos($key, ...$members): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->geopos(...\func_get_args()); + } + + public function lrem($key, $mem, $count = 0): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->lrem(...\func_get_args()); + } + + public function lindex($key, $index): mixed + { + return $this->initializeLazyObject()->lindex(...\func_get_args()); + } + + public function linsert($key, $op, $pivot, $element): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->linsert(...\func_get_args()); + } + + public function ltrim($key, $start, $end): \Relay\Relay|bool + { + return $this->initializeLazyObject()->ltrim(...\func_get_args()); + } + + public function hget($hash, $member): mixed + { + return $this->initializeLazyObject()->hget(...\func_get_args()); + } + + public function hstrlen($hash, $member): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->hstrlen(...\func_get_args()); + } + + public function hgetall($hash): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->hgetall(...\func_get_args()); + } + + public function hkeys($hash): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->hkeys(...\func_get_args()); + } + + public function hvals($hash): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->hvals(...\func_get_args()); + } + + public function hmget($hash, $members): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->hmget(...\func_get_args()); + } + + public function hmset($hash, $members): \Relay\Relay|bool + { + return $this->initializeLazyObject()->hmset(...\func_get_args()); + } + + public function hexists($hash, $member): \Relay\Relay|bool + { + return $this->initializeLazyObject()->hexists(...\func_get_args()); + } + + public function hsetnx($hash, $member, $value): \Relay\Relay|bool + { + return $this->initializeLazyObject()->hsetnx(...\func_get_args()); + } + + public function hdel($key, $mem, ...$mems): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->hdel(...\func_get_args()); + } + + public function hincrby($key, $mem, $value): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->hincrby(...\func_get_args()); + } + + public function hincrbyfloat($key, $mem, $value): \Relay\Relay|bool|float + { + return $this->initializeLazyObject()->hincrbyfloat(...\func_get_args()); + } + + public function incr($key, $by = 1): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->incr(...\func_get_args()); + } + + public function decr($key, $by = 1): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->decr(...\func_get_args()); + } + + public function incrby($key, $value): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->incrby(...\func_get_args()); + } + + public function decrby($key, $value): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->decrby(...\func_get_args()); + } + + public function incrbyfloat($key, $value): \Relay\Relay|false|float + { + return $this->initializeLazyObject()->incrbyfloat(...\func_get_args()); + } + + public function sdiff($key, ...$other_keys): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->sdiff(...\func_get_args()); + } + + public function sdiffstore($key, ...$other_keys): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->sdiffstore(...\func_get_args()); + } + + public function sinter($key, ...$other_keys): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->sinter(...\func_get_args()); + } + + public function sintercard($keys, $limit = -1): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->sintercard(...\func_get_args()); + } + + public function sinterstore($key, ...$other_keys): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->sinterstore(...\func_get_args()); + } + + public function sunion($key, ...$other_keys): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->sunion(...\func_get_args()); + } + + public function sunionstore($key, ...$other_keys): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->sunionstore(...\func_get_args()); + } + + public function subscribe($channels, $callback): bool + { + return $this->initializeLazyObject()->subscribe(...\func_get_args()); + } + + public function unsubscribe($channels = []): bool + { + return $this->initializeLazyObject()->unsubscribe(...\func_get_args()); + } + + public function psubscribe($patterns, $callback): bool + { + return $this->initializeLazyObject()->psubscribe(...\func_get_args()); + } + + public function punsubscribe($patterns = []): bool + { + return $this->initializeLazyObject()->punsubscribe(...\func_get_args()); + } + + public function ssubscribe($channels, $callback): bool + { + return $this->initializeLazyObject()->ssubscribe(...\func_get_args()); + } + + public function sunsubscribe($channels = []): bool + { + return $this->initializeLazyObject()->sunsubscribe(...\func_get_args()); + } + + public function touch($key_or_array, ...$more_keys): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->touch(...\func_get_args()); + } + + public function pipeline(): \Relay\Relay|bool + { + return $this->initializeLazyObject()->pipeline(...\func_get_args()); + } + + public function multi($mode = 0): \Relay\Relay|bool + { + return $this->initializeLazyObject()->multi(...\func_get_args()); + } + + public function exec(): \Relay\Relay|array|bool + { + return $this->initializeLazyObject()->exec(...\func_get_args()); + } + + public function wait($replicas, $timeout): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->wait(...\func_get_args()); + } + + public function watch($key, ...$other_keys): \Relay\Relay|bool + { + return $this->initializeLazyObject()->watch(...\func_get_args()); + } + + public function unwatch(): \Relay\Relay|bool + { + return $this->initializeLazyObject()->unwatch(...\func_get_args()); + } + + public function discard(): bool + { + return $this->initializeLazyObject()->discard(...\func_get_args()); + } + + public function getMode($masked = false): int + { + return $this->initializeLazyObject()->getMode(...\func_get_args()); + } + + public function clearBytes(): void + { + $this->initializeLazyObject()->clearBytes(...\func_get_args()); + } + + public function scan(&$iterator, $match = null, $count = 0, $type = null): array|false + { + return $this->initializeLazyObject()->scan($iterator, ...\array_slice(\func_get_args(), 1)); + } + + public function hscan($key, &$iterator, $match = null, $count = 0): array|false + { + return $this->initializeLazyObject()->hscan($key, $iterator, ...\array_slice(\func_get_args(), 2)); + } + + public function sscan($key, &$iterator, $match = null, $count = 0): array|false + { + return $this->initializeLazyObject()->sscan($key, $iterator, ...\array_slice(\func_get_args(), 2)); + } + + public function zscan($key, &$iterator, $match = null, $count = 0): array|false + { + return $this->initializeLazyObject()->zscan($key, $iterator, ...\array_slice(\func_get_args(), 2)); + } + + public function keys($pattern): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->keys(...\func_get_args()); + } + + public function slowlog($operation, ...$extra_args): \Relay\Relay|array|bool|int + { + return $this->initializeLazyObject()->slowlog(...\func_get_args()); + } + + public function smembers($set): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->smembers(...\func_get_args()); + } + + public function sismember($set, $member): \Relay\Relay|bool + { + return $this->initializeLazyObject()->sismember(...\func_get_args()); + } + + public function smismember($set, ...$members): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->smismember(...\func_get_args()); + } + + public function srem($set, $member, ...$members): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->srem(...\func_get_args()); + } + + public function sadd($set, $member, ...$members): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->sadd(...\func_get_args()); + } + + public function sort($key, $options = []): \Relay\Relay|array|false|int + { + return $this->initializeLazyObject()->sort(...\func_get_args()); + } + + public function sort_ro($key, $options = []): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->sort_ro(...\func_get_args()); + } + + public function smove($srcset, $dstset, $member): \Relay\Relay|bool + { + return $this->initializeLazyObject()->smove(...\func_get_args()); + } + + public function spop($set, $count = 1): mixed + { + return $this->initializeLazyObject()->spop(...\func_get_args()); + } + + public function srandmember($set, $count = 1): mixed + { + return $this->initializeLazyObject()->srandmember(...\func_get_args()); + } + + public function scard($key): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->scard(...\func_get_args()); + } + + public function script($command, ...$args): mixed + { + return $this->initializeLazyObject()->script(...\func_get_args()); + } + + public function strlen($key): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->strlen(...\func_get_args()); + } + + public function hlen($key): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->hlen(...\func_get_args()); + } + + public function llen($key): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->llen(...\func_get_args()); + } + + public function xack($key, $group, $ids): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->xack(...\func_get_args()); + } + + public function xclaim($key, $group, $consumer, $min_idle, $ids, $options): \Relay\Relay|array|bool + { + return $this->initializeLazyObject()->xclaim(...\func_get_args()); + } + + public function xautoclaim($key, $group, $consumer, $min_idle, $start, $count = -1, $justid = false): \Relay\Relay|array|bool + { + return $this->initializeLazyObject()->xautoclaim(...\func_get_args()); + } + + public function xlen($key): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->xlen(...\func_get_args()); + } + + public function xgroup($operation, $key = null, $group = null, $id_or_consumer = null, $mkstream = false, $entries_read = -2): mixed + { + return $this->initializeLazyObject()->xgroup(...\func_get_args()); + } + + public function xdel($key, $ids): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->xdel(...\func_get_args()); + } + + public function xinfo($operation, $arg1 = null, $arg2 = null, $count = -1): mixed + { + return $this->initializeLazyObject()->xinfo(...\func_get_args()); + } + + public function xpending($key, $group, $start = null, $end = null, $count = -1, $consumer = null, $idle = 0): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->xpending(...\func_get_args()); + } + + public function xrange($key, $start, $end, $count = -1): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->xrange(...\func_get_args()); + } + + public function xrevrange($key, $end, $start, $count = -1): \Relay\Relay|array|bool + { + return $this->initializeLazyObject()->xrevrange(...\func_get_args()); + } + + public function xread($streams, $count = -1, $block = -1): \Relay\Relay|array|bool|null + { + return $this->initializeLazyObject()->xread(...\func_get_args()); + } + + public function xreadgroup($group, $consumer, $streams, $count = 1, $block = 1): \Relay\Relay|array|bool|null + { + return $this->initializeLazyObject()->xreadgroup(...\func_get_args()); + } + + public function xtrim($key, $threshold, $approx = false, $minid = false, $limit = -1): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->xtrim(...\func_get_args()); + } + + public function zadd($key, ...$args): mixed + { + return $this->initializeLazyObject()->zadd(...\func_get_args()); + } + + public function zrandmember($key, $options = null): mixed + { + return $this->initializeLazyObject()->zrandmember(...\func_get_args()); + } + + public function zrange($key, $start, $end, $options = null): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->zrange(...\func_get_args()); + } + + public function zrevrange($key, $start, $end, $options = null): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->zrevrange(...\func_get_args()); + } + + public function zrangebyscore($key, $start, $end, $options = null): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->zrangebyscore(...\func_get_args()); + } + + public function zrevrangebyscore($key, $start, $end, $options = null): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->zrevrangebyscore(...\func_get_args()); + } + + public function zrangestore($dst, $src, $start, $end, $options = null): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->zrangestore(...\func_get_args()); + } + + public function zrangebylex($key, $min, $max, $offset = -1, $count = -1): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->zrangebylex(...\func_get_args()); + } + + public function zrevrangebylex($key, $max, $min, $offset = -1, $count = -1): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->zrevrangebylex(...\func_get_args()); + } + + public function zrem($key, ...$args): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->zrem(...\func_get_args()); + } + + public function zremrangebylex($key, $min, $max): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->zremrangebylex(...\func_get_args()); + } + + public function zremrangebyrank($key, $start, $end): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->zremrangebyrank(...\func_get_args()); + } + + public function zremrangebyscore($key, $min, $max): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->zremrangebyscore(...\func_get_args()); + } + + public function zcard($key): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->zcard(...\func_get_args()); + } + + public function zcount($key, $min, $max): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->zcount(...\func_get_args()); + } + + public function zdiff($keys, $options = null): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->zdiff(...\func_get_args()); + } + + public function zdiffstore($dst, $keys): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->zdiffstore(...\func_get_args()); + } + + public function zincrby($key, $score, $mem): \Relay\Relay|false|float + { + return $this->initializeLazyObject()->zincrby(...\func_get_args()); + } + + public function zlexcount($key, $min, $max): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->zlexcount(...\func_get_args()); + } + + public function zmscore($key, ...$mems): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->zmscore(...\func_get_args()); + } + + public function zinter($keys, $weights = null, $options = null): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->zinter(...\func_get_args()); + } + + public function zintercard($keys, $limit = -1): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->zintercard(...\func_get_args()); + } + + public function zinterstore($dst, $keys, $weights = null, $options = null): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->zinterstore(...\func_get_args()); + } + + public function zunion($keys, $weights = null, $options = null): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->zunion(...\func_get_args()); + } + + public function zunionstore($dst, $keys, $weights = null, $options = null): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->zunionstore(...\func_get_args()); + } + + public function zpopmin($key, $count = 1): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->zpopmin(...\func_get_args()); + } + + public function zpopmax($key, $count = 1): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->zpopmax(...\func_get_args()); + } + + public function _getKeys() + { + return $this->initializeLazyObject()->_getKeys(...\func_get_args()); + } +} diff --git a/vendor/symfony/cache/Traits/RelayProxyTrait.php b/vendor/symfony/cache/Traits/RelayProxyTrait.php new file mode 100644 index 0000000..6077b44 --- /dev/null +++ b/vendor/symfony/cache/Traits/RelayProxyTrait.php @@ -0,0 +1,147 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Traits; + +if (version_compare(phpversion('relay'), '0.8.1', '>=')) { + /** + * @internal + */ + trait RelayProxyTrait + { + public function jsonArrAppend($key, $value_or_array, $path = null): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->jsonArrAppend(...\func_get_args()); + } + + public function jsonArrIndex($key, $path, $value, $start = 0, $stop = -1): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->jsonArrIndex(...\func_get_args()); + } + + public function jsonArrInsert($key, $path, $index, $value, ...$other_values): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->jsonArrInsert(...\func_get_args()); + } + + public function jsonArrLen($key, $path = null): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->jsonArrLen(...\func_get_args()); + } + + public function jsonArrPop($key, $path = null, $index = -1): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->jsonArrPop(...\func_get_args()); + } + + public function jsonArrTrim($key, $path, $start, $stop): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->jsonArrTrim(...\func_get_args()); + } + + public function jsonClear($key, $path = null): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->jsonClear(...\func_get_args()); + } + + public function jsonDebug($command, $key, $path = null): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->jsonDebug(...\func_get_args()); + } + + public function jsonDel($key, $path = null): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->jsonDel(...\func_get_args()); + } + + public function jsonForget($key, $path = null): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->jsonForget(...\func_get_args()); + } + + public function jsonGet($key, $options = [], ...$paths): mixed + { + return $this->initializeLazyObject()->jsonGet(...\func_get_args()); + } + + public function jsonMerge($key, $path, $value): \Relay\Relay|bool + { + return $this->initializeLazyObject()->jsonMerge(...\func_get_args()); + } + + public function jsonMget($key_or_array, $path): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->jsonMget(...\func_get_args()); + } + + public function jsonMset($key, $path, $value, ...$other_triples): \Relay\Relay|bool + { + return $this->initializeLazyObject()->jsonMset(...\func_get_args()); + } + + public function jsonNumIncrBy($key, $path, $value): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->jsonNumIncrBy(...\func_get_args()); + } + + public function jsonNumMultBy($key, $path, $value): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->jsonNumMultBy(...\func_get_args()); + } + + public function jsonObjKeys($key, $path = null): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->jsonObjKeys(...\func_get_args()); + } + + public function jsonObjLen($key, $path = null): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->jsonObjLen(...\func_get_args()); + } + + public function jsonResp($key, $path = null): \Relay\Relay|array|false|int|string + { + return $this->initializeLazyObject()->jsonResp(...\func_get_args()); + } + + public function jsonSet($key, $path, $value, $condition = null): \Relay\Relay|bool + { + return $this->initializeLazyObject()->jsonSet(...\func_get_args()); + } + + public function jsonStrAppend($key, $value, $path = null): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->jsonStrAppend(...\func_get_args()); + } + + public function jsonStrLen($key, $path = null): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->jsonStrLen(...\func_get_args()); + } + + public function jsonToggle($key, $path): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->jsonToggle(...\func_get_args()); + } + + public function jsonType($key, $path = null): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->jsonType(...\func_get_args()); + } + } +} else { + /** + * @internal + */ + trait RelayProxyTrait + { + } +} diff --git a/vendor/symfony/cache/Traits/ValueWrapper.php b/vendor/symfony/cache/Traits/ValueWrapper.php new file mode 100644 index 0000000..718a23d --- /dev/null +++ b/vendor/symfony/cache/Traits/ValueWrapper.php @@ -0,0 +1,81 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * A short namespace-less class to serialize items with metadata. + * + * @author Nicolas Grekas + * + * @internal + */ +class © +{ + private const EXPIRY_OFFSET = 1648206727; + private const INT32_MAX = 2147483647; + + public readonly mixed $value; + public readonly array $metadata; + + public function __construct(mixed $value, array $metadata) + { + $this->value = $value; + $this->metadata = $metadata; + } + + public function __serialize(): array + { + // pack 31-bits ctime into 14bits + $c = $this->metadata['ctime'] ?? 0; + $c = match (true) { + $c > self::INT32_MAX - 2 => self::INT32_MAX, + $c > 0 => 1 + $c, + default => 1, + }; + $e = 0; + while (!(0x40000000 & $c)) { + $c <<= 1; + ++$e; + } + $c = (0x7FE0 & ($c >> 16)) | $e; + + $pack = pack('Vn', (int) (0.1 + ($this->metadata['expiry'] ?: self::INT32_MAX + self::EXPIRY_OFFSET) - self::EXPIRY_OFFSET), $c); + + if (isset($this->metadata['tags'])) { + $pack[4] = $pack[4] | "\x80"; + } + + return [$pack => $this->value] + ($this->metadata['tags'] ?? []); + } + + public function __unserialize(array $data): void + { + $pack = array_key_first($data); + $this->value = $data[$pack]; + + if ($hasTags = "\x80" === ($pack[4] & "\x80")) { + unset($data[$pack]); + $pack[4] = $pack[4] & "\x7F"; + } + + $metadata = unpack('Vexpiry/nctime', $pack); + $metadata['expiry'] += self::EXPIRY_OFFSET; + + if (!$metadata['ctime'] = ((0x4000 | $metadata['ctime']) << 16 >> (0x1F & $metadata['ctime'])) - 1) { + unset($metadata['ctime']); + } + + if ($hasTags) { + $metadata['tags'] = $data; + } + + $this->metadata = $metadata; + } +} diff --git a/vendor/symfony/cache/composer.json b/vendor/symfony/cache/composer.json new file mode 100644 index 0000000..bdb461b --- /dev/null +++ b/vendor/symfony/cache/composer.json @@ -0,0 +1,61 @@ +{ + "name": "symfony/cache", + "type": "library", + "description": "Provides extended PSR-6, PSR-16 (and tags) implementations", + "keywords": ["caching", "psr6"], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "provide": { + "psr/cache-implementation": "2.0|3.0", + "psr/simple-cache-implementation": "1.0|2.0|3.0", + "symfony/cache-implementation": "1.1|2.0|3.0" + }, + "require": { + "php": ">=8.2", + "psr/cache": "^2.0|^3.0", + "psr/log": "^1.1|^2|^3", + "symfony/cache-contracts": "^2.5|^3", + "symfony/deprecation-contracts": "^2.5|^3.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/var-exporter": "^6.4|^7.0" + }, + "require-dev": { + "cache/integration-tests": "dev-master", + "doctrine/dbal": "^3.6|^4", + "predis/predis": "^1.1|^2.0", + "psr/simple-cache": "^1.0|^2.0|^3.0", + "symfony/clock": "^6.4|^7.0", + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/filesystem": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/messenger": "^6.4|^7.0", + "symfony/var-dumper": "^6.4|^7.0" + }, + "conflict": { + "doctrine/dbal": "<3.6", + "symfony/dependency-injection": "<6.4", + "symfony/http-kernel": "<6.4", + "symfony/var-dumper": "<6.4" + }, + "autoload": { + "psr-4": { "Symfony\\Component\\Cache\\": "" }, + "classmap": [ + "Traits/ValueWrapper.php" + ], + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "minimum-stability": "dev" +} diff --git a/vendor/symfony/deprecation-contracts/CHANGELOG.md b/vendor/symfony/deprecation-contracts/CHANGELOG.md new file mode 100644 index 0000000..7932e26 --- /dev/null +++ b/vendor/symfony/deprecation-contracts/CHANGELOG.md @@ -0,0 +1,5 @@ +CHANGELOG +========= + +The changelog is maintained for all Symfony contracts at the following URL: +https://github.com/symfony/contracts/blob/main/CHANGELOG.md diff --git a/vendor/symfony/deprecation-contracts/LICENSE b/vendor/symfony/deprecation-contracts/LICENSE new file mode 100644 index 0000000..0ed3a24 --- /dev/null +++ b/vendor/symfony/deprecation-contracts/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2020-present Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/symfony/deprecation-contracts/README.md b/vendor/symfony/deprecation-contracts/README.md new file mode 100644 index 0000000..9814864 --- /dev/null +++ b/vendor/symfony/deprecation-contracts/README.md @@ -0,0 +1,26 @@ +Symfony Deprecation Contracts +============================= + +A generic function and convention to trigger deprecation notices. + +This package provides a single global function named `trigger_deprecation()` that triggers silenced deprecation notices. + +By using a custom PHP error handler such as the one provided by the Symfony ErrorHandler component, +the triggered deprecations can be caught and logged for later discovery, both on dev and prod environments. + +The function requires at least 3 arguments: + - the name of the Composer package that is triggering the deprecation + - the version of the package that introduced the deprecation + - the message of the deprecation + - more arguments can be provided: they will be inserted in the message using `printf()` formatting + +Example: +```php +trigger_deprecation('symfony/blockchain', '8.9', 'Using "%s" is deprecated, use "%s" instead.', 'bitcoin', 'fabcoin'); +``` + +This will generate the following message: +`Since symfony/blockchain 8.9: Using "bitcoin" is deprecated, use "fabcoin" instead.` + +While not recommended, the deprecation notices can be completely ignored by declaring an empty +`function trigger_deprecation() {}` in your application. diff --git a/vendor/symfony/deprecation-contracts/composer.json b/vendor/symfony/deprecation-contracts/composer.json new file mode 100644 index 0000000..ceb6c07 --- /dev/null +++ b/vendor/symfony/deprecation-contracts/composer.json @@ -0,0 +1,35 @@ +{ + "name": "symfony/deprecation-contracts", + "type": "library", + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": ">=8.1" + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-main": "3.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + } +} diff --git a/vendor/symfony/deprecation-contracts/function.php b/vendor/symfony/deprecation-contracts/function.php new file mode 100644 index 0000000..2d56512 --- /dev/null +++ b/vendor/symfony/deprecation-contracts/function.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +if (!function_exists('trigger_deprecation')) { + /** + * Triggers a silenced deprecation notice. + * + * @param string $package The name of the Composer package that is triggering the deprecation + * @param string $version The version of the package that introduced the deprecation + * @param string $message The message of the deprecation + * @param mixed ...$args Values to insert in the message using printf() formatting + * + * @author Nicolas Grekas + */ + function trigger_deprecation(string $package, string $version, string $message, mixed ...$args): void + { + @trigger_error(($package || $version ? "Since $package $version: " : '').($args ? vsprintf($message, $args) : $message), \E_USER_DEPRECATED); + } +} diff --git a/vendor/symfony/expression-language/CHANGELOG.md b/vendor/symfony/expression-language/CHANGELOG.md new file mode 100644 index 0000000..b06620c --- /dev/null +++ b/vendor/symfony/expression-language/CHANGELOG.md @@ -0,0 +1,46 @@ +CHANGELOG +========= + +6.3 +--- + + * Add `enum` expression function + * Deprecate loose comparisons when using the "in" operator; normalize the array parameter + so it only has the expected types or implement loose matching in your own expression function + +6.2 +--- + + * Add support for null-coalescing syntax + +6.1 +--- + + * Add support for null-safe syntax when parsing object's methods and properties + * Add new operators: `contains`, `starts with` and `ends with` + * Support lexing numbers with the numeric literal separator `_` + * Support lexing decimals with no leading zero + +5.1.0 +----- + + * added `lint` method to `ExpressionLanguage` class + * added `lint` method to `Parser` class + +4.0.0 +----- + + * the first argument of the `ExpressionLanguage` constructor must be an instance + of `CacheItemPoolInterface` + * removed the `ArrayParserCache` and `ParserCacheAdapter` classes + * removed the `ParserCacheInterface` + +2.6.0 +----- + + * Added ExpressionFunction and ExpressionFunctionProviderInterface + +2.4.0 +----- + + * added the component diff --git a/vendor/symfony/expression-language/Compiler.php b/vendor/symfony/expression-language/Compiler.php new file mode 100644 index 0000000..ab50d36 --- /dev/null +++ b/vendor/symfony/expression-language/Compiler.php @@ -0,0 +1,149 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ExpressionLanguage; + +use Symfony\Contracts\Service\ResetInterface; + +/** + * Compiles a node to PHP code. + * + * @author Fabien Potencier + */ +class Compiler implements ResetInterface +{ + private string $source = ''; + private array $functions; + + public function __construct(array $functions) + { + $this->functions = $functions; + } + + /** + * @return array + */ + public function getFunction(string $name) + { + return $this->functions[$name]; + } + + /** + * Gets the current PHP code after compilation. + */ + public function getSource(): string + { + return $this->source; + } + + /** + * @return $this + */ + public function reset(): static + { + $this->source = ''; + + return $this; + } + + /** + * Compiles a node. + * + * @return $this + */ + public function compile(Node\Node $node): static + { + $node->compile($this); + + return $this; + } + + /** + * @return string + */ + public function subcompile(Node\Node $node) + { + $current = $this->source; + $this->source = ''; + + $node->compile($this); + + $source = $this->source; + $this->source = $current; + + return $source; + } + + /** + * Adds a raw string to the compiled code. + * + * @return $this + */ + public function raw(string $string): static + { + $this->source .= $string; + + return $this; + } + + /** + * Adds a quoted string to the compiled code. + * + * @return $this + */ + public function string(string $value): static + { + $this->source .= sprintf('"%s"', addcslashes($value, "\0\t\"\$\\")); + + return $this; + } + + /** + * Returns a PHP representation of a given value. + * + * @return $this + */ + public function repr(mixed $value): static + { + if (\is_int($value) || \is_float($value)) { + if (false !== $locale = setlocale(\LC_NUMERIC, 0)) { + setlocale(\LC_NUMERIC, 'C'); + } + + $this->raw($value); + + if (false !== $locale) { + setlocale(\LC_NUMERIC, $locale); + } + } elseif (null === $value) { + $this->raw('null'); + } elseif (\is_bool($value)) { + $this->raw($value ? 'true' : 'false'); + } elseif (\is_array($value)) { + $this->raw('['); + $first = true; + foreach ($value as $key => $value) { + if (!$first) { + $this->raw(', '); + } + $first = false; + $this->repr($key); + $this->raw(' => '); + $this->repr($value); + } + $this->raw(']'); + } else { + $this->string($value); + } + + return $this; + } +} diff --git a/vendor/symfony/expression-language/Expression.php b/vendor/symfony/expression-language/Expression.php new file mode 100644 index 0000000..3cab1df --- /dev/null +++ b/vendor/symfony/expression-language/Expression.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ExpressionLanguage; + +/** + * Represents an expression. + * + * @author Fabien Potencier + */ +class Expression +{ + protected $expression; + + public function __construct(string $expression) + { + $this->expression = $expression; + } + + /** + * Gets the expression. + */ + public function __toString(): string + { + return $this->expression; + } +} diff --git a/vendor/symfony/expression-language/ExpressionFunction.php b/vendor/symfony/expression-language/ExpressionFunction.php new file mode 100644 index 0000000..0b3d6c4 --- /dev/null +++ b/vendor/symfony/expression-language/ExpressionFunction.php @@ -0,0 +1,91 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ExpressionLanguage; + +/** + * Represents a function that can be used in an expression. + * + * A function is defined by two PHP callables. The callables are used + * by the language to compile and/or evaluate the function. + * + * The "compiler" function is used at compilation time and must return a + * PHP representation of the function call (it receives the function + * arguments as arguments). + * + * The "evaluator" function is used for expression evaluation and must return + * the value of the function call based on the values defined for the + * expression (it receives the values as a first argument and the function + * arguments as remaining arguments). + * + * @author Fabien Potencier + */ +class ExpressionFunction +{ + private string $name; + private \Closure $compiler; + private \Closure $evaluator; + + /** + * @param string $name The function name + * @param callable $compiler A callable able to compile the function + * @param callable $evaluator A callable able to evaluate the function + */ + public function __construct(string $name, callable $compiler, callable $evaluator) + { + $this->name = $name; + $this->compiler = $compiler(...); + $this->evaluator = $evaluator(...); + } + + public function getName(): string + { + return $this->name; + } + + public function getCompiler(): \Closure + { + return $this->compiler; + } + + public function getEvaluator(): \Closure + { + return $this->evaluator; + } + + /** + * Creates an ExpressionFunction from a PHP function name. + * + * @param string|null $expressionFunctionName The expression function name (default: same than the PHP function name) + * + * @throws \InvalidArgumentException if given PHP function name does not exist + * @throws \InvalidArgumentException if given PHP function name is in namespace + * and expression function name is not defined + */ + public static function fromPhp(string $phpFunctionName, ?string $expressionFunctionName = null): self + { + $phpFunctionName = ltrim($phpFunctionName, '\\'); + if (!\function_exists($phpFunctionName)) { + throw new \InvalidArgumentException(sprintf('PHP function "%s" does not exist.', $phpFunctionName)); + } + + $parts = explode('\\', $phpFunctionName); + if (!$expressionFunctionName && \count($parts) > 1) { + throw new \InvalidArgumentException(sprintf('An expression function name must be defined when PHP function "%s" is namespaced.', $phpFunctionName)); + } + + $compiler = fn (...$args) => sprintf('\%s(%s)', $phpFunctionName, implode(', ', $args)); + + $evaluator = fn ($p, ...$args) => $phpFunctionName(...$args); + + return new self($expressionFunctionName ?: end($parts), $compiler, $evaluator); + } +} diff --git a/vendor/symfony/expression-language/ExpressionFunctionProviderInterface.php b/vendor/symfony/expression-language/ExpressionFunctionProviderInterface.php new file mode 100644 index 0000000..479aeef --- /dev/null +++ b/vendor/symfony/expression-language/ExpressionFunctionProviderInterface.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ExpressionLanguage; + +/** + * @author Fabien Potencier + */ +interface ExpressionFunctionProviderInterface +{ + /** + * @return ExpressionFunction[] + */ + public function getFunctions(); +} diff --git a/vendor/symfony/expression-language/ExpressionLanguage.php b/vendor/symfony/expression-language/ExpressionLanguage.php new file mode 100644 index 0000000..a7f249f --- /dev/null +++ b/vendor/symfony/expression-language/ExpressionLanguage.php @@ -0,0 +1,183 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ExpressionLanguage; + +use Psr\Cache\CacheItemPoolInterface; +use Symfony\Component\Cache\Adapter\ArrayAdapter; + +// Help opcache.preload discover always-needed symbols +class_exists(ParsedExpression::class); + +/** + * Allows to compile and evaluate expressions written in your own DSL. + * + * @author Fabien Potencier + */ +class ExpressionLanguage +{ + private CacheItemPoolInterface $cache; + private Lexer $lexer; + private Parser $parser; + private Compiler $compiler; + + protected array $functions = []; + + /** + * @param ExpressionFunctionProviderInterface[] $providers + */ + public function __construct(?CacheItemPoolInterface $cache = null, array $providers = []) + { + $this->cache = $cache ?? new ArrayAdapter(); + $this->registerFunctions(); + foreach ($providers as $provider) { + $this->registerProvider($provider); + } + } + + /** + * Compiles an expression source code. + */ + public function compile(Expression|string $expression, array $names = []): string + { + return $this->getCompiler()->compile($this->parse($expression, $names)->getNodes())->getSource(); + } + + /** + * Evaluate an expression. + */ + public function evaluate(Expression|string $expression, array $values = []): mixed + { + return $this->parse($expression, array_keys($values))->getNodes()->evaluate($this->functions, $values); + } + + /** + * Parses an expression. + */ + public function parse(Expression|string $expression, array $names): ParsedExpression + { + if ($expression instanceof ParsedExpression) { + return $expression; + } + + asort($names); + $cacheKeyItems = []; + + foreach ($names as $nameKey => $name) { + $cacheKeyItems[] = \is_int($nameKey) ? $name : $nameKey.':'.$name; + } + + $cacheItem = $this->cache->getItem(rawurlencode($expression.'//'.implode('|', $cacheKeyItems))); + + if (null === $parsedExpression = $cacheItem->get()) { + $nodes = $this->getParser()->parse($this->getLexer()->tokenize((string) $expression), $names); + $parsedExpression = new ParsedExpression((string) $expression, $nodes); + + $cacheItem->set($parsedExpression); + $this->cache->save($cacheItem); + } + + return $parsedExpression; + } + + /** + * Validates the syntax of an expression. + * + * @param array|null $names The list of acceptable variable names in the expression, or null to accept any names + * + * @throws SyntaxError When the passed expression is invalid + */ + public function lint(Expression|string $expression, ?array $names): void + { + if ($expression instanceof ParsedExpression) { + return; + } + + $this->getParser()->lint($this->getLexer()->tokenize((string) $expression), $names); + } + + /** + * Registers a function. + * + * @param callable $compiler A callable able to compile the function + * @param callable $evaluator A callable able to evaluate the function + * + * @return void + * + * @throws \LogicException when registering a function after calling evaluate(), compile() or parse() + * + * @see ExpressionFunction + */ + public function register(string $name, callable $compiler, callable $evaluator) + { + if (isset($this->parser)) { + throw new \LogicException('Registering functions after calling evaluate(), compile() or parse() is not supported.'); + } + + $this->functions[$name] = ['compiler' => $compiler, 'evaluator' => $evaluator]; + } + + /** + * @return void + */ + public function addFunction(ExpressionFunction $function) + { + $this->register($function->getName(), $function->getCompiler(), $function->getEvaluator()); + } + + /** + * @return void + */ + public function registerProvider(ExpressionFunctionProviderInterface $provider) + { + foreach ($provider->getFunctions() as $function) { + $this->addFunction($function); + } + } + + /** + * @return void + */ + protected function registerFunctions() + { + $this->addFunction(ExpressionFunction::fromPhp('constant')); + + $this->addFunction(new ExpressionFunction('enum', + static fn ($str): string => sprintf("(\constant(\$v = (%s))) instanceof \UnitEnum ? \constant(\$v) : throw new \TypeError(\sprintf('The string \"%%s\" is not the name of a valid enum case.', \$v))", $str), + static function ($arguments, $str): \UnitEnum { + $value = \constant($str); + + if (!$value instanceof \UnitEnum) { + throw new \TypeError(sprintf('The string "%s" is not the name of a valid enum case.', $str)); + } + + return $value; + } + )); + } + + private function getLexer(): Lexer + { + return $this->lexer ??= new Lexer(); + } + + private function getParser(): Parser + { + return $this->parser ??= new Parser($this->functions); + } + + private function getCompiler(): Compiler + { + $this->compiler ??= new Compiler($this->functions); + + return $this->compiler->reset(); + } +} diff --git a/vendor/symfony/expression-language/LICENSE b/vendor/symfony/expression-language/LICENSE new file mode 100644 index 0000000..0138f8f --- /dev/null +++ b/vendor/symfony/expression-language/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2004-present Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/symfony/expression-language/Lexer.php b/vendor/symfony/expression-language/Lexer.php new file mode 100644 index 0000000..ab32342 --- /dev/null +++ b/vendor/symfony/expression-language/Lexer.php @@ -0,0 +1,107 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ExpressionLanguage; + +/** + * Lexes an expression. + * + * @author Fabien Potencier + */ +class Lexer +{ + /** + * Tokenizes an expression. + * + * @throws SyntaxError + */ + public function tokenize(string $expression): TokenStream + { + $expression = str_replace(["\r", "\n", "\t", "\v", "\f"], ' ', $expression); + $cursor = 0; + $tokens = []; + $brackets = []; + $end = \strlen($expression); + + while ($cursor < $end) { + if (' ' == $expression[$cursor]) { + ++$cursor; + + continue; + } + + if (preg_match('/ + (?(DEFINE)(?P[0-9]+(_[0-9]+)*)) + (?:\.(?&LNUM)|(?&LNUM)(?:\.(?!\.)(?&LNUM)?)?)(?:[eE][+-]?(?&LNUM))?/Ax', + $expression, $match, 0, $cursor) + ) { + // numbers + $tokens[] = new Token(Token::NUMBER_TYPE, 0 + str_replace('_', '', $match[0]), $cursor + 1); + $cursor += \strlen($match[0]); + } elseif (str_contains('([{', $expression[$cursor])) { + // opening bracket + $brackets[] = [$expression[$cursor], $cursor]; + + $tokens[] = new Token(Token::PUNCTUATION_TYPE, $expression[$cursor], $cursor + 1); + ++$cursor; + } elseif (str_contains(')]}', $expression[$cursor])) { + // closing bracket + if (!$brackets) { + throw new SyntaxError(sprintf('Unexpected "%s".', $expression[$cursor]), $cursor, $expression); + } + + [$expect, $cur] = array_pop($brackets); + if ($expression[$cursor] != strtr($expect, '([{', ')]}')) { + throw new SyntaxError(sprintf('Unclosed "%s".', $expect), $cur, $expression); + } + + $tokens[] = new Token(Token::PUNCTUATION_TYPE, $expression[$cursor], $cursor + 1); + ++$cursor; + } elseif (preg_match('/"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\'/As', $expression, $match, 0, $cursor)) { + // strings + $tokens[] = new Token(Token::STRING_TYPE, stripcslashes(substr($match[0], 1, -1)), $cursor + 1); + $cursor += \strlen($match[0]); + } elseif (preg_match('/(?<=^|[\s(])starts with(?=[\s(])|(?<=^|[\s(])ends with(?=[\s(])|(?<=^|[\s(])contains(?=[\s(])|(?<=^|[\s(])matches(?=[\s(])|(?<=^|[\s(])not in(?=[\s(])|(?<=^|[\s(])not(?=[\s(])|(?<=^|[\s(])and(?=[\s(])|\=\=\=|\!\=\=|(?<=^|[\s(])or(?=[\s(])|\|\||&&|\=\=|\!\=|\>\=|\<\=|(?<=^|[\s(])in(?=[\s(])|\.\.|\*\*|\!|\||\^|&|\<|\>|\+|\-|~|\*|\/|%/A', $expression, $match, 0, $cursor)) { + // operators + $tokens[] = new Token(Token::OPERATOR_TYPE, $match[0], $cursor + 1); + $cursor += \strlen($match[0]); + } elseif ('?' === $expression[$cursor] && '.' === ($expression[$cursor + 1] ?? '')) { + // null-safe + $tokens[] = new Token(Token::PUNCTUATION_TYPE, '?.', ++$cursor); + ++$cursor; + } elseif ('?' === $expression[$cursor] && '?' === ($expression[$cursor + 1] ?? '')) { + // null-coalescing + $tokens[] = new Token(Token::PUNCTUATION_TYPE, '??', ++$cursor); + ++$cursor; + } elseif (str_contains('.,?:', $expression[$cursor])) { + // punctuation + $tokens[] = new Token(Token::PUNCTUATION_TYPE, $expression[$cursor], $cursor + 1); + ++$cursor; + } elseif (preg_match('/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/A', $expression, $match, 0, $cursor)) { + // names + $tokens[] = new Token(Token::NAME_TYPE, $match[0], $cursor + 1); + $cursor += \strlen($match[0]); + } else { + // unlexable + throw new SyntaxError(sprintf('Unexpected character "%s".', $expression[$cursor]), $cursor, $expression); + } + } + + $tokens[] = new Token(Token::EOF_TYPE, null, $cursor + 1); + + if ($brackets) { + [$expect, $cur] = array_pop($brackets); + throw new SyntaxError(sprintf('Unclosed "%s".', $expect), $cur, $expression); + } + + return new TokenStream($tokens, $expression); + } +} diff --git a/vendor/symfony/expression-language/Node/ArgumentsNode.php b/vendor/symfony/expression-language/Node/ArgumentsNode.php new file mode 100644 index 0000000..981cae2 --- /dev/null +++ b/vendor/symfony/expression-language/Node/ArgumentsNode.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ExpressionLanguage\Node; + +use Symfony\Component\ExpressionLanguage\Compiler; + +/** + * @author Fabien Potencier + * + * @internal + */ +class ArgumentsNode extends ArrayNode +{ + public function compile(Compiler $compiler): void + { + $this->compileArguments($compiler, false); + } + + public function toArray(): array + { + $array = []; + + foreach ($this->getKeyValuePairs() as $pair) { + $array[] = $pair['value']; + $array[] = ', '; + } + array_pop($array); + + return $array; + } +} diff --git a/vendor/symfony/expression-language/Node/ArrayNode.php b/vendor/symfony/expression-language/Node/ArrayNode.php new file mode 100644 index 0000000..79eade2 --- /dev/null +++ b/vendor/symfony/expression-language/Node/ArrayNode.php @@ -0,0 +1,116 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ExpressionLanguage\Node; + +use Symfony\Component\ExpressionLanguage\Compiler; + +/** + * @author Fabien Potencier + * + * @internal + */ +class ArrayNode extends Node +{ + protected int $index; + + public function __construct() + { + $this->index = -1; + } + + public function addElement(Node $value, ?Node $key = null): void + { + $key ??= new ConstantNode(++$this->index); + + array_push($this->nodes, $key, $value); + } + + /** + * Compiles the node to PHP. + */ + public function compile(Compiler $compiler): void + { + $compiler->raw('['); + $this->compileArguments($compiler); + $compiler->raw(']'); + } + + public function evaluate(array $functions, array $values): array + { + $result = []; + foreach ($this->getKeyValuePairs() as $pair) { + $result[$pair['key']->evaluate($functions, $values)] = $pair['value']->evaluate($functions, $values); + } + + return $result; + } + + public function toArray(): array + { + $value = []; + foreach ($this->getKeyValuePairs() as $pair) { + $value[$pair['key']->attributes['value']] = $pair['value']; + } + + $array = []; + + if ($this->isHash($value)) { + foreach ($value as $k => $v) { + $array[] = ', '; + $array[] = new ConstantNode($k); + $array[] = ': '; + $array[] = $v; + } + $array[0] = '{'; + $array[] = '}'; + } else { + foreach ($value as $v) { + $array[] = ', '; + $array[] = $v; + } + $array[0] = '['; + $array[] = ']'; + } + + return $array; + } + + protected function getKeyValuePairs(): array + { + $pairs = []; + foreach (array_chunk($this->nodes, 2) as $pair) { + $pairs[] = ['key' => $pair[0], 'value' => $pair[1]]; + } + + return $pairs; + } + + protected function compileArguments(Compiler $compiler, bool $withKeys = true): void + { + $first = true; + foreach ($this->getKeyValuePairs() as $pair) { + if (!$first) { + $compiler->raw(', '); + } + $first = false; + + if ($withKeys) { + $compiler + ->compile($pair['key']) + ->raw(' => ') + ; + } + + $compiler->compile($pair['value']); + } + } +} diff --git a/vendor/symfony/expression-language/Node/BinaryNode.php b/vendor/symfony/expression-language/Node/BinaryNode.php new file mode 100644 index 0000000..0cacfc6 --- /dev/null +++ b/vendor/symfony/expression-language/Node/BinaryNode.php @@ -0,0 +1,204 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ExpressionLanguage\Node; + +use Symfony\Component\ExpressionLanguage\Compiler; +use Symfony\Component\ExpressionLanguage\SyntaxError; + +/** + * @author Fabien Potencier + * + * @internal + */ +class BinaryNode extends Node +{ + private const OPERATORS = [ + '~' => '.', + 'and' => '&&', + 'or' => '||', + ]; + + private const FUNCTIONS = [ + '**' => 'pow', + '..' => 'range', + 'in' => '\\'.self::class.'::inArray', + 'not in' => '!\\'.self::class.'::inArray', + 'contains' => 'str_contains', + 'starts with' => 'str_starts_with', + 'ends with' => 'str_ends_with', + ]; + + public function __construct(string $operator, Node $left, Node $right) + { + parent::__construct( + ['left' => $left, 'right' => $right], + ['operator' => $operator] + ); + } + + public function compile(Compiler $compiler): void + { + $operator = $this->attributes['operator']; + + if ('matches' == $operator) { + if ($this->nodes['right'] instanceof ConstantNode) { + $this->evaluateMatches($this->nodes['right']->evaluate([], []), ''); + } + + $compiler + ->raw('(static function ($regexp, $str) { set_error_handler(static fn ($t, $m) => throw new \Symfony\Component\ExpressionLanguage\SyntaxError(sprintf(\'Regexp "%s" passed to "matches" is not valid\', $regexp).substr($m, 12))); try { return preg_match($regexp, (string) $str); } finally { restore_error_handler(); } })(') + ->compile($this->nodes['right']) + ->raw(', ') + ->compile($this->nodes['left']) + ->raw(')') + ; + + return; + } + + if (isset(self::FUNCTIONS[$operator])) { + $compiler + ->raw(sprintf('%s(', self::FUNCTIONS[$operator])) + ->compile($this->nodes['left']) + ->raw(', ') + ->compile($this->nodes['right']) + ->raw(')') + ; + + return; + } + + if (isset(self::OPERATORS[$operator])) { + $operator = self::OPERATORS[$operator]; + } + + $compiler + ->raw('(') + ->compile($this->nodes['left']) + ->raw(' ') + ->raw($operator) + ->raw(' ') + ->compile($this->nodes['right']) + ->raw(')') + ; + } + + public function evaluate(array $functions, array $values): mixed + { + $operator = $this->attributes['operator']; + $left = $this->nodes['left']->evaluate($functions, $values); + + if (isset(self::FUNCTIONS[$operator])) { + $right = $this->nodes['right']->evaluate($functions, $values); + + if ('not in' === $operator) { + return !self::inArray($left, $right); + } + $f = self::FUNCTIONS[$operator]; + + return $f($left, $right); + } + + switch ($operator) { + case 'or': + case '||': + return $left || $this->nodes['right']->evaluate($functions, $values); + case 'and': + case '&&': + return $left && $this->nodes['right']->evaluate($functions, $values); + } + + $right = $this->nodes['right']->evaluate($functions, $values); + + switch ($operator) { + case '|': + return $left | $right; + case '^': + return $left ^ $right; + case '&': + return $left & $right; + case '==': + return $left == $right; + case '===': + return $left === $right; + case '!=': + return $left != $right; + case '!==': + return $left !== $right; + case '<': + return $left < $right; + case '>': + return $left > $right; + case '>=': + return $left >= $right; + case '<=': + return $left <= $right; + case 'not in': + return !self::inArray($left, $right); + case 'in': + return self::inArray($left, $right); + case '+': + return $left + $right; + case '-': + return $left - $right; + case '~': + return $left.$right; + case '*': + return $left * $right; + case '/': + if (0 == $right) { + throw new \DivisionByZeroError('Division by zero.'); + } + + return $left / $right; + case '%': + if (0 == $right) { + throw new \DivisionByZeroError('Modulo by zero.'); + } + + return $left % $right; + case 'matches': + return $this->evaluateMatches($right, $left); + } + } + + public function toArray(): array + { + return ['(', $this->nodes['left'], ' '.$this->attributes['operator'].' ', $this->nodes['right'], ')']; + } + + /** + * @internal to be replaced by an inline strict call to in_array() in version 7.0 + */ + public static function inArray($value, array $array): bool + { + if (false === $key = array_search($value, $array)) { + return false; + } + + if (!\in_array($value, $array, true)) { + trigger_deprecation('symfony/expression-language', '6.3', 'The "in" operator will use strict comparisons in Symfony 7.0. Loose match found with key "%s" for value %s. Normalize the array parameter so it only has the expected types or implement loose matching in your own expression function.', $key, json_encode($value)); + } + + return true; + } + + private function evaluateMatches(string $regexp, ?string $str): int + { + set_error_handler(static fn ($t, $m) => throw new SyntaxError(sprintf('Regexp "%s" passed to "matches" is not valid', $regexp).substr($m, 12))); + try { + return preg_match($regexp, (string) $str); + } finally { + restore_error_handler(); + } + } +} diff --git a/vendor/symfony/expression-language/Node/ConditionalNode.php b/vendor/symfony/expression-language/Node/ConditionalNode.php new file mode 100644 index 0000000..7d02544 --- /dev/null +++ b/vendor/symfony/expression-language/Node/ConditionalNode.php @@ -0,0 +1,56 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ExpressionLanguage\Node; + +use Symfony\Component\ExpressionLanguage\Compiler; + +/** + * @author Fabien Potencier + * + * @internal + */ +class ConditionalNode extends Node +{ + public function __construct(Node $expr1, Node $expr2, Node $expr3) + { + parent::__construct( + ['expr1' => $expr1, 'expr2' => $expr2, 'expr3' => $expr3] + ); + } + + public function compile(Compiler $compiler): void + { + $compiler + ->raw('((') + ->compile($this->nodes['expr1']) + ->raw(') ? (') + ->compile($this->nodes['expr2']) + ->raw(') : (') + ->compile($this->nodes['expr3']) + ->raw('))') + ; + } + + public function evaluate(array $functions, array $values): mixed + { + if ($this->nodes['expr1']->evaluate($functions, $values)) { + return $this->nodes['expr2']->evaluate($functions, $values); + } + + return $this->nodes['expr3']->evaluate($functions, $values); + } + + public function toArray(): array + { + return ['(', $this->nodes['expr1'], ' ? ', $this->nodes['expr2'], ' : ', $this->nodes['expr3'], ')']; + } +} diff --git a/vendor/symfony/expression-language/Node/ConstantNode.php b/vendor/symfony/expression-language/Node/ConstantNode.php new file mode 100644 index 0000000..37beee8 --- /dev/null +++ b/vendor/symfony/expression-language/Node/ConstantNode.php @@ -0,0 +1,83 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ExpressionLanguage\Node; + +use Symfony\Component\ExpressionLanguage\Compiler; + +/** + * @author Fabien Potencier + * + * @internal + */ +class ConstantNode extends Node +{ + public readonly bool $isNullSafe; + private bool $isIdentifier; + + public function __construct(mixed $value, bool $isIdentifier = false, bool $isNullSafe = false) + { + $this->isIdentifier = $isIdentifier; + $this->isNullSafe = $isNullSafe; + parent::__construct( + [], + ['value' => $value] + ); + } + + public function compile(Compiler $compiler): void + { + $compiler->repr($this->attributes['value']); + } + + public function evaluate(array $functions, array $values): mixed + { + return $this->attributes['value']; + } + + public function toArray(): array + { + $array = []; + $value = $this->attributes['value']; + + if ($this->isIdentifier) { + $array[] = $value; + } elseif (true === $value) { + $array[] = 'true'; + } elseif (false === $value) { + $array[] = 'false'; + } elseif (null === $value) { + $array[] = 'null'; + } elseif (is_numeric($value)) { + $array[] = $value; + } elseif (!\is_array($value)) { + $array[] = $this->dumpString($value); + } elseif ($this->isHash($value)) { + foreach ($value as $k => $v) { + $array[] = ', '; + $array[] = new self($k); + $array[] = ': '; + $array[] = new self($v); + } + $array[0] = '{'; + $array[] = '}'; + } else { + foreach ($value as $v) { + $array[] = ', '; + $array[] = new self($v); + } + $array[0] = '['; + $array[] = ']'; + } + + return $array; + } +} diff --git a/vendor/symfony/expression-language/Node/FunctionNode.php b/vendor/symfony/expression-language/Node/FunctionNode.php new file mode 100644 index 0000000..33323f3 --- /dev/null +++ b/vendor/symfony/expression-language/Node/FunctionNode.php @@ -0,0 +1,70 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ExpressionLanguage\Node; + +use Symfony\Component\ExpressionLanguage\Compiler; + +/** + * @author Fabien Potencier + * + * @internal + */ +class FunctionNode extends Node +{ + public function __construct(string $name, Node $arguments) + { + parent::__construct( + ['arguments' => $arguments], + ['name' => $name] + ); + } + + public function compile(Compiler $compiler): void + { + $arguments = []; + foreach ($this->nodes['arguments']->nodes as $node) { + $arguments[] = $compiler->subcompile($node); + } + + $function = $compiler->getFunction($this->attributes['name']); + + $compiler->raw($function['compiler'](...$arguments)); + } + + public function evaluate(array $functions, array $values): mixed + { + $arguments = [$values]; + foreach ($this->nodes['arguments']->nodes as $node) { + $arguments[] = $node->evaluate($functions, $values); + } + + return $functions[$this->attributes['name']]['evaluator'](...$arguments); + } + + /** + * @return array + */ + public function toArray() + { + $array = []; + $array[] = $this->attributes['name']; + + foreach ($this->nodes['arguments']->nodes as $node) { + $array[] = ', '; + $array[] = $node; + } + $array[1] = '('; + $array[] = ')'; + + return $array; + } +} diff --git a/vendor/symfony/expression-language/Node/GetAttrNode.php b/vendor/symfony/expression-language/Node/GetAttrNode.php new file mode 100644 index 0000000..984247e --- /dev/null +++ b/vendor/symfony/expression-language/Node/GetAttrNode.php @@ -0,0 +1,166 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ExpressionLanguage\Node; + +use Symfony\Component\ExpressionLanguage\Compiler; + +/** + * @author Fabien Potencier + * + * @internal + */ +class GetAttrNode extends Node +{ + public const PROPERTY_CALL = 1; + public const METHOD_CALL = 2; + public const ARRAY_CALL = 3; + + /** + * @param self::* $type + */ + public function __construct(Node $node, Node $attribute, ArrayNode $arguments, int $type) + { + parent::__construct( + ['node' => $node, 'attribute' => $attribute, 'arguments' => $arguments], + ['type' => $type, 'is_null_coalesce' => false, 'is_short_circuited' => false], + ); + } + + public function compile(Compiler $compiler): void + { + $nullSafe = $this->nodes['attribute'] instanceof ConstantNode && $this->nodes['attribute']->isNullSafe; + switch ($this->attributes['type']) { + case self::PROPERTY_CALL: + $compiler + ->compile($this->nodes['node']) + ->raw($nullSafe ? '?->' : '->') + ->raw($this->nodes['attribute']->attributes['value']) + ; + break; + + case self::METHOD_CALL: + $compiler + ->compile($this->nodes['node']) + ->raw($nullSafe ? '?->' : '->') + ->raw($this->nodes['attribute']->attributes['value']) + ->raw('(') + ->compile($this->nodes['arguments']) + ->raw(')') + ; + break; + + case self::ARRAY_CALL: + $compiler + ->compile($this->nodes['node']) + ->raw('[') + ->compile($this->nodes['attribute'])->raw(']') + ; + break; + } + } + + public function evaluate(array $functions, array $values): mixed + { + switch ($this->attributes['type']) { + case self::PROPERTY_CALL: + $obj = $this->nodes['node']->evaluate($functions, $values); + if (null === $obj && ($this->nodes['attribute']->isNullSafe || $this->attributes['is_null_coalesce'])) { + $this->attributes['is_short_circuited'] = true; + + return null; + } + if (null === $obj && $this->isShortCircuited()) { + return null; + } + + if (!\is_object($obj)) { + throw new \RuntimeException(sprintf('Unable to get property "%s" of non-object "%s".', $this->nodes['attribute']->dump(), $this->nodes['node']->dump())); + } + + $property = $this->nodes['attribute']->attributes['value']; + + if ($this->attributes['is_null_coalesce']) { + return $obj->$property ?? null; + } + + return $obj->$property; + + case self::METHOD_CALL: + $obj = $this->nodes['node']->evaluate($functions, $values); + + if (null === $obj && $this->nodes['attribute']->isNullSafe) { + $this->attributes['is_short_circuited'] = true; + + return null; + } + if (null === $obj && $this->isShortCircuited()) { + return null; + } + + if (!\is_object($obj)) { + throw new \RuntimeException(sprintf('Unable to call method "%s" of non-object "%s".', $this->nodes['attribute']->dump(), $this->nodes['node']->dump())); + } + if (!\is_callable($toCall = [$obj, $this->nodes['attribute']->attributes['value']])) { + throw new \RuntimeException(sprintf('Unable to call method "%s" of object "%s".', $this->nodes['attribute']->attributes['value'], get_debug_type($obj))); + } + + return $toCall(...array_values($this->nodes['arguments']->evaluate($functions, $values))); + + case self::ARRAY_CALL: + $array = $this->nodes['node']->evaluate($functions, $values); + + if (null === $array && $this->isShortCircuited()) { + return null; + } + + if (!\is_array($array) && !$array instanceof \ArrayAccess && !(null === $array && $this->attributes['is_null_coalesce'])) { + throw new \RuntimeException(sprintf('Unable to get an item of non-array "%s".', $this->nodes['node']->dump())); + } + + if ($this->attributes['is_null_coalesce']) { + return $array[$this->nodes['attribute']->evaluate($functions, $values)] ?? null; + } + + return $array[$this->nodes['attribute']->evaluate($functions, $values)]; + } + } + + private function isShortCircuited(): bool + { + return $this->attributes['is_short_circuited'] || ($this->nodes['node'] instanceof self && $this->nodes['node']->isShortCircuited()); + } + + public function toArray(): array + { + switch ($this->attributes['type']) { + case self::PROPERTY_CALL: + return [$this->nodes['node'], '.', $this->nodes['attribute']]; + + case self::METHOD_CALL: + return [$this->nodes['node'], '.', $this->nodes['attribute'], '(', $this->nodes['arguments'], ')']; + + case self::ARRAY_CALL: + return [$this->nodes['node'], '[', $this->nodes['attribute'], ']']; + } + } + + /** + * Provides BC with instances serialized before v6.2. + */ + public function __unserialize(array $data): void + { + $this->nodes = $data['nodes']; + $this->attributes = $data['attributes']; + $this->attributes['is_null_coalesce'] ??= false; + $this->attributes['is_short_circuited'] ??= $data["\x00Symfony\Component\ExpressionLanguage\Node\GetAttrNode\x00isShortCircuited"] ?? false; + } +} diff --git a/vendor/symfony/expression-language/Node/NameNode.php b/vendor/symfony/expression-language/Node/NameNode.php new file mode 100644 index 0000000..b9d0e1a --- /dev/null +++ b/vendor/symfony/expression-language/Node/NameNode.php @@ -0,0 +1,45 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ExpressionLanguage\Node; + +use Symfony\Component\ExpressionLanguage\Compiler; + +/** + * @author Fabien Potencier + * + * @internal + */ +class NameNode extends Node +{ + public function __construct(string $name) + { + parent::__construct( + [], + ['name' => $name] + ); + } + + public function compile(Compiler $compiler): void + { + $compiler->raw('$'.$this->attributes['name']); + } + + public function evaluate(array $functions, array $values): mixed + { + return $values[$this->attributes['name']]; + } + + public function toArray(): array + { + return [$this->attributes['name']]; + } +} diff --git a/vendor/symfony/expression-language/Node/Node.php b/vendor/symfony/expression-language/Node/Node.php new file mode 100644 index 0000000..91fcc36 --- /dev/null +++ b/vendor/symfony/expression-language/Node/Node.php @@ -0,0 +1,130 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ExpressionLanguage\Node; + +use Symfony\Component\ExpressionLanguage\Compiler; + +/** + * Represents a node in the AST. + * + * @author Fabien Potencier + */ +class Node +{ + public $nodes = []; + public $attributes = []; + + /** + * @param array $nodes An array of nodes + * @param array $attributes An array of attributes + */ + public function __construct(array $nodes = [], array $attributes = []) + { + $this->nodes = $nodes; + $this->attributes = $attributes; + } + + public function __toString(): string + { + $attributes = []; + foreach ($this->attributes as $name => $value) { + $attributes[] = sprintf('%s: %s', $name, str_replace("\n", '', var_export($value, true))); + } + + $repr = [str_replace('Symfony\Component\ExpressionLanguage\Node\\', '', static::class).'('.implode(', ', $attributes)]; + + if (\count($this->nodes)) { + foreach ($this->nodes as $node) { + foreach (explode("\n", (string) $node) as $line) { + $repr[] = ' '.$line; + } + } + + $repr[] = ')'; + } else { + $repr[0] .= ')'; + } + + return implode("\n", $repr); + } + + /** + * @return void + */ + public function compile(Compiler $compiler) + { + foreach ($this->nodes as $node) { + $node->compile($compiler); + } + } + + /** + * @return mixed + */ + public function evaluate(array $functions, array $values) + { + $results = []; + foreach ($this->nodes as $node) { + $results[] = $node->evaluate($functions, $values); + } + + return $results; + } + + /** + * @return array + * + * @throws \BadMethodCallException when this node cannot be transformed to an array + */ + public function toArray() + { + throw new \BadMethodCallException(sprintf('Dumping a "%s" instance is not supported yet.', static::class)); + } + + /** + * @return string + */ + public function dump() + { + $dump = ''; + + foreach ($this->toArray() as $v) { + $dump .= \is_scalar($v) ? $v : $v->dump(); + } + + return $dump; + } + + /** + * @return string + */ + protected function dumpString(string $value) + { + return sprintf('"%s"', addcslashes($value, "\0\t\"\\")); + } + + /** + * @return bool + */ + protected function isHash(array $value) + { + $expectedKey = 0; + + foreach ($value as $key => $val) { + if ($key !== $expectedKey++) { + return true; + } + } + + return false; + } +} diff --git a/vendor/symfony/expression-language/Node/NullCoalesceNode.php b/vendor/symfony/expression-language/Node/NullCoalesceNode.php new file mode 100644 index 0000000..025bb1a --- /dev/null +++ b/vendor/symfony/expression-language/Node/NullCoalesceNode.php @@ -0,0 +1,65 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ExpressionLanguage\Node; + +use Symfony\Component\ExpressionLanguage\Compiler; + +/** + * @author Fabien Potencier + * + * @internal + */ +class NullCoalesceNode extends Node +{ + public function __construct(Node $expr1, Node $expr2) + { + parent::__construct(['expr1' => $expr1, 'expr2' => $expr2]); + } + + public function compile(Compiler $compiler): void + { + $compiler + ->raw('((') + ->compile($this->nodes['expr1']) + ->raw(') ?? (') + ->compile($this->nodes['expr2']) + ->raw('))') + ; + } + + public function evaluate(array $functions, array $values): mixed + { + if ($this->nodes['expr1'] instanceof GetAttrNode) { + $this->addNullCoalesceAttributeToGetAttrNodes($this->nodes['expr1']); + } + + return $this->nodes['expr1']->evaluate($functions, $values) ?? $this->nodes['expr2']->evaluate($functions, $values); + } + + public function toArray(): array + { + return ['(', $this->nodes['expr1'], ') ?? (', $this->nodes['expr2'], ')']; + } + + private function addNullCoalesceAttributeToGetAttrNodes(Node $node): void + { + if (!$node instanceof GetAttrNode) { + return; + } + + $node->attributes['is_null_coalesce'] = true; + + foreach ($node->nodes as $node) { + $this->addNullCoalesceAttributeToGetAttrNodes($node); + } + } +} diff --git a/vendor/symfony/expression-language/Node/UnaryNode.php b/vendor/symfony/expression-language/Node/UnaryNode.php new file mode 100644 index 0000000..55e2121 --- /dev/null +++ b/vendor/symfony/expression-language/Node/UnaryNode.php @@ -0,0 +1,64 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ExpressionLanguage\Node; + +use Symfony\Component\ExpressionLanguage\Compiler; + +/** + * @author Fabien Potencier + * + * @internal + */ +class UnaryNode extends Node +{ + private const OPERATORS = [ + '!' => '!', + 'not' => '!', + '+' => '+', + '-' => '-', + ]; + + public function __construct(string $operator, Node $node) + { + parent::__construct( + ['node' => $node], + ['operator' => $operator] + ); + } + + public function compile(Compiler $compiler): void + { + $compiler + ->raw('(') + ->raw(self::OPERATORS[$this->attributes['operator']]) + ->compile($this->nodes['node']) + ->raw(')') + ; + } + + public function evaluate(array $functions, array $values): mixed + { + $value = $this->nodes['node']->evaluate($functions, $values); + + return match ($this->attributes['operator']) { + 'not', + '!' => !$value, + '-' => -$value, + default => $value, + }; + } + + public function toArray(): array + { + return ['(', $this->attributes['operator'].' ', $this->nodes['node'], ')']; + } +} diff --git a/vendor/symfony/expression-language/ParsedExpression.php b/vendor/symfony/expression-language/ParsedExpression.php new file mode 100644 index 0000000..239624e --- /dev/null +++ b/vendor/symfony/expression-language/ParsedExpression.php @@ -0,0 +1,39 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ExpressionLanguage; + +use Symfony\Component\ExpressionLanguage\Node\Node; + +/** + * Represents an already parsed expression. + * + * @author Fabien Potencier + */ +class ParsedExpression extends Expression +{ + private Node $nodes; + + public function __construct(string $expression, Node $nodes) + { + parent::__construct($expression); + + $this->nodes = $nodes; + } + + /** + * @return Node + */ + public function getNodes() + { + return $this->nodes; + } +} diff --git a/vendor/symfony/expression-language/Parser.php b/vendor/symfony/expression-language/Parser.php new file mode 100644 index 0000000..a163a7a --- /dev/null +++ b/vendor/symfony/expression-language/Parser.php @@ -0,0 +1,439 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ExpressionLanguage; + +/** + * Parsers a token stream. + * + * This parser implements a "Precedence climbing" algorithm. + * + * @see http://www.engr.mun.ca/~theo/Misc/exp_parsing.htm + * @see http://en.wikipedia.org/wiki/Operator-precedence_parser + * + * @author Fabien Potencier + */ +class Parser +{ + public const OPERATOR_LEFT = 1; + public const OPERATOR_RIGHT = 2; + + private TokenStream $stream; + private array $unaryOperators; + private array $binaryOperators; + private array $functions; + private ?array $names; + private bool $lint = false; + + public function __construct(array $functions) + { + $this->functions = $functions; + + $this->unaryOperators = [ + 'not' => ['precedence' => 50], + '!' => ['precedence' => 50], + '-' => ['precedence' => 500], + '+' => ['precedence' => 500], + ]; + $this->binaryOperators = [ + 'or' => ['precedence' => 10, 'associativity' => self::OPERATOR_LEFT], + '||' => ['precedence' => 10, 'associativity' => self::OPERATOR_LEFT], + 'and' => ['precedence' => 15, 'associativity' => self::OPERATOR_LEFT], + '&&' => ['precedence' => 15, 'associativity' => self::OPERATOR_LEFT], + '|' => ['precedence' => 16, 'associativity' => self::OPERATOR_LEFT], + '^' => ['precedence' => 17, 'associativity' => self::OPERATOR_LEFT], + '&' => ['precedence' => 18, 'associativity' => self::OPERATOR_LEFT], + '==' => ['precedence' => 20, 'associativity' => self::OPERATOR_LEFT], + '===' => ['precedence' => 20, 'associativity' => self::OPERATOR_LEFT], + '!=' => ['precedence' => 20, 'associativity' => self::OPERATOR_LEFT], + '!==' => ['precedence' => 20, 'associativity' => self::OPERATOR_LEFT], + '<' => ['precedence' => 20, 'associativity' => self::OPERATOR_LEFT], + '>' => ['precedence' => 20, 'associativity' => self::OPERATOR_LEFT], + '>=' => ['precedence' => 20, 'associativity' => self::OPERATOR_LEFT], + '<=' => ['precedence' => 20, 'associativity' => self::OPERATOR_LEFT], + 'not in' => ['precedence' => 20, 'associativity' => self::OPERATOR_LEFT], + 'in' => ['precedence' => 20, 'associativity' => self::OPERATOR_LEFT], + 'contains' => ['precedence' => 20, 'associativity' => self::OPERATOR_LEFT], + 'starts with' => ['precedence' => 20, 'associativity' => self::OPERATOR_LEFT], + 'ends with' => ['precedence' => 20, 'associativity' => self::OPERATOR_LEFT], + 'matches' => ['precedence' => 20, 'associativity' => self::OPERATOR_LEFT], + '..' => ['precedence' => 25, 'associativity' => self::OPERATOR_LEFT], + '+' => ['precedence' => 30, 'associativity' => self::OPERATOR_LEFT], + '-' => ['precedence' => 30, 'associativity' => self::OPERATOR_LEFT], + '~' => ['precedence' => 40, 'associativity' => self::OPERATOR_LEFT], + '*' => ['precedence' => 60, 'associativity' => self::OPERATOR_LEFT], + '/' => ['precedence' => 60, 'associativity' => self::OPERATOR_LEFT], + '%' => ['precedence' => 60, 'associativity' => self::OPERATOR_LEFT], + '**' => ['precedence' => 200, 'associativity' => self::OPERATOR_RIGHT], + ]; + } + + /** + * Converts a token stream to a node tree. + * + * The valid names is an array where the values + * are the names that the user can use in an expression. + * + * If the variable name in the compiled PHP code must be + * different, define it as the key. + * + * For instance, ['this' => 'container'] means that the + * variable 'container' can be used in the expression + * but the compiled code will use 'this'. + * + * @throws SyntaxError + */ + public function parse(TokenStream $stream, array $names = []): Node\Node + { + $this->lint = false; + + return $this->doParse($stream, $names); + } + + /** + * Validates the syntax of an expression. + * + * The syntax of the passed expression will be checked, but not parsed. + * If you want to skip checking dynamic variable names, pass `null` instead of the array. + * + * @throws SyntaxError When the passed expression is invalid + */ + public function lint(TokenStream $stream, ?array $names = []): void + { + $this->lint = true; + $this->doParse($stream, $names); + } + + /** + * @throws SyntaxError + */ + private function doParse(TokenStream $stream, ?array $names = []): Node\Node + { + $this->stream = $stream; + $this->names = $names; + + $node = $this->parseExpression(); + if (!$stream->isEOF()) { + throw new SyntaxError(sprintf('Unexpected token "%s" of value "%s".', $stream->current->type, $stream->current->value), $stream->current->cursor, $stream->getExpression()); + } + + unset($this->stream, $this->names); + + return $node; + } + + /** + * @return Node\Node + */ + public function parseExpression(int $precedence = 0) + { + $expr = $this->getPrimary(); + $token = $this->stream->current; + while ($token->test(Token::OPERATOR_TYPE) && isset($this->binaryOperators[$token->value]) && $this->binaryOperators[$token->value]['precedence'] >= $precedence) { + $op = $this->binaryOperators[$token->value]; + $this->stream->next(); + + $expr1 = $this->parseExpression(self::OPERATOR_LEFT === $op['associativity'] ? $op['precedence'] + 1 : $op['precedence']); + $expr = new Node\BinaryNode($token->value, $expr, $expr1); + + $token = $this->stream->current; + } + + if (0 === $precedence) { + return $this->parseConditionalExpression($expr); + } + + return $expr; + } + + /** + * @return Node\Node + */ + protected function getPrimary() + { + $token = $this->stream->current; + + if ($token->test(Token::OPERATOR_TYPE) && isset($this->unaryOperators[$token->value])) { + $operator = $this->unaryOperators[$token->value]; + $this->stream->next(); + $expr = $this->parseExpression($operator['precedence']); + + return $this->parsePostfixExpression(new Node\UnaryNode($token->value, $expr)); + } + + if ($token->test(Token::PUNCTUATION_TYPE, '(')) { + $this->stream->next(); + $expr = $this->parseExpression(); + $this->stream->expect(Token::PUNCTUATION_TYPE, ')', 'An opened parenthesis is not properly closed'); + + return $this->parsePostfixExpression($expr); + } + + return $this->parsePrimaryExpression(); + } + + /** + * @return Node\Node + */ + protected function parseConditionalExpression(Node\Node $expr) + { + while ($this->stream->current->test(Token::PUNCTUATION_TYPE, '??')) { + $this->stream->next(); + $expr2 = $this->parseExpression(); + + $expr = new Node\NullCoalesceNode($expr, $expr2); + } + + while ($this->stream->current->test(Token::PUNCTUATION_TYPE, '?')) { + $this->stream->next(); + if (!$this->stream->current->test(Token::PUNCTUATION_TYPE, ':')) { + $expr2 = $this->parseExpression(); + if ($this->stream->current->test(Token::PUNCTUATION_TYPE, ':')) { + $this->stream->next(); + $expr3 = $this->parseExpression(); + } else { + $expr3 = new Node\ConstantNode(null); + } + } else { + $this->stream->next(); + $expr2 = $expr; + $expr3 = $this->parseExpression(); + } + + $expr = new Node\ConditionalNode($expr, $expr2, $expr3); + } + + return $expr; + } + + /** + * @return Node\Node + */ + public function parsePrimaryExpression() + { + $token = $this->stream->current; + switch ($token->type) { + case Token::NAME_TYPE: + $this->stream->next(); + switch ($token->value) { + case 'true': + case 'TRUE': + return new Node\ConstantNode(true); + + case 'false': + case 'FALSE': + return new Node\ConstantNode(false); + + case 'null': + case 'NULL': + return new Node\ConstantNode(null); + + default: + if ('(' === $this->stream->current->value) { + if (false === isset($this->functions[$token->value])) { + throw new SyntaxError(sprintf('The function "%s" does not exist.', $token->value), $token->cursor, $this->stream->getExpression(), $token->value, array_keys($this->functions)); + } + + $node = new Node\FunctionNode($token->value, $this->parseArguments()); + } else { + if (!$this->lint || \is_array($this->names)) { + if (!\in_array($token->value, $this->names, true)) { + throw new SyntaxError(sprintf('Variable "%s" is not valid.', $token->value), $token->cursor, $this->stream->getExpression(), $token->value, $this->names); + } + + // is the name used in the compiled code different + // from the name used in the expression? + if (\is_int($name = array_search($token->value, $this->names))) { + $name = $token->value; + } + } else { + $name = $token->value; + } + + $node = new Node\NameNode($name); + } + } + break; + + case Token::NUMBER_TYPE: + case Token::STRING_TYPE: + $this->stream->next(); + + return new Node\ConstantNode($token->value); + + default: + if ($token->test(Token::PUNCTUATION_TYPE, '[')) { + $node = $this->parseArrayExpression(); + } elseif ($token->test(Token::PUNCTUATION_TYPE, '{')) { + $node = $this->parseHashExpression(); + } else { + throw new SyntaxError(sprintf('Unexpected token "%s" of value "%s".', $token->type, $token->value), $token->cursor, $this->stream->getExpression()); + } + } + + return $this->parsePostfixExpression($node); + } + + /** + * @return Node\ArrayNode + */ + public function parseArrayExpression() + { + $this->stream->expect(Token::PUNCTUATION_TYPE, '[', 'An array element was expected'); + + $node = new Node\ArrayNode(); + $first = true; + while (!$this->stream->current->test(Token::PUNCTUATION_TYPE, ']')) { + if (!$first) { + $this->stream->expect(Token::PUNCTUATION_TYPE, ',', 'An array element must be followed by a comma'); + + // trailing ,? + if ($this->stream->current->test(Token::PUNCTUATION_TYPE, ']')) { + break; + } + } + $first = false; + + $node->addElement($this->parseExpression()); + } + $this->stream->expect(Token::PUNCTUATION_TYPE, ']', 'An opened array is not properly closed'); + + return $node; + } + + /** + * @return Node\ArrayNode + */ + public function parseHashExpression() + { + $this->stream->expect(Token::PUNCTUATION_TYPE, '{', 'A hash element was expected'); + + $node = new Node\ArrayNode(); + $first = true; + while (!$this->stream->current->test(Token::PUNCTUATION_TYPE, '}')) { + if (!$first) { + $this->stream->expect(Token::PUNCTUATION_TYPE, ',', 'A hash value must be followed by a comma'); + + // trailing ,? + if ($this->stream->current->test(Token::PUNCTUATION_TYPE, '}')) { + break; + } + } + $first = false; + + // a hash key can be: + // + // * a number -- 12 + // * a string -- 'a' + // * a name, which is equivalent to a string -- a + // * an expression, which must be enclosed in parentheses -- (1 + 2) + if ($this->stream->current->test(Token::STRING_TYPE) || $this->stream->current->test(Token::NAME_TYPE) || $this->stream->current->test(Token::NUMBER_TYPE)) { + $key = new Node\ConstantNode($this->stream->current->value); + $this->stream->next(); + } elseif ($this->stream->current->test(Token::PUNCTUATION_TYPE, '(')) { + $key = $this->parseExpression(); + } else { + $current = $this->stream->current; + + throw new SyntaxError(sprintf('A hash key must be a quoted string, a number, a name, or an expression enclosed in parentheses (unexpected token "%s" of value "%s".', $current->type, $current->value), $current->cursor, $this->stream->getExpression()); + } + + $this->stream->expect(Token::PUNCTUATION_TYPE, ':', 'A hash key must be followed by a colon (:)'); + $value = $this->parseExpression(); + + $node->addElement($value, $key); + } + $this->stream->expect(Token::PUNCTUATION_TYPE, '}', 'An opened hash is not properly closed'); + + return $node; + } + + /** + * @return Node\GetAttrNode|Node\Node + */ + public function parsePostfixExpression(Node\Node $node) + { + $token = $this->stream->current; + while (Token::PUNCTUATION_TYPE == $token->type) { + if ('.' === $token->value || '?.' === $token->value) { + $isNullSafe = '?.' === $token->value; + $this->stream->next(); + $token = $this->stream->current; + $this->stream->next(); + + if ( + Token::NAME_TYPE !== $token->type + // Operators like "not" and "matches" are valid method or property names, + // + // In other words, besides NAME_TYPE, OPERATOR_TYPE could also be parsed as a property or method. + // This is because operators are processed by the lexer prior to names. So "not" in "foo.not()" or "matches" in "foo.matches" will be recognized as an operator first. + // But in fact, "not" and "matches" in such expressions shall be parsed as method or property names. + // + // And this ONLY works if the operator consists of valid characters for a property or method name. + // + // Other types, such as STRING_TYPE and NUMBER_TYPE, can't be parsed as property nor method names. + // + // As a result, if $token is NOT an operator OR $token->value is NOT a valid property or method name, an exception shall be thrown. + && (Token::OPERATOR_TYPE !== $token->type || !preg_match('/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/A', $token->value)) + ) { + throw new SyntaxError('Expected name.', $token->cursor, $this->stream->getExpression()); + } + + $arg = new Node\ConstantNode($token->value, true, $isNullSafe); + + $arguments = new Node\ArgumentsNode(); + if ($this->stream->current->test(Token::PUNCTUATION_TYPE, '(')) { + $type = Node\GetAttrNode::METHOD_CALL; + foreach ($this->parseArguments()->nodes as $n) { + $arguments->addElement($n); + } + } else { + $type = Node\GetAttrNode::PROPERTY_CALL; + } + + $node = new Node\GetAttrNode($node, $arg, $arguments, $type); + } elseif ('[' === $token->value) { + $this->stream->next(); + $arg = $this->parseExpression(); + $this->stream->expect(Token::PUNCTUATION_TYPE, ']'); + + $node = new Node\GetAttrNode($node, $arg, new Node\ArgumentsNode(), Node\GetAttrNode::ARRAY_CALL); + } else { + break; + } + + $token = $this->stream->current; + } + + return $node; + } + + /** + * Parses arguments. + * + * @return Node\Node + */ + public function parseArguments() + { + $args = []; + $this->stream->expect(Token::PUNCTUATION_TYPE, '(', 'A list of arguments must begin with an opening parenthesis'); + while (!$this->stream->current->test(Token::PUNCTUATION_TYPE, ')')) { + if ($args) { + $this->stream->expect(Token::PUNCTUATION_TYPE, ',', 'Arguments must be separated by a comma'); + } + + $args[] = $this->parseExpression(); + } + $this->stream->expect(Token::PUNCTUATION_TYPE, ')', 'A list of arguments must be closed by a parenthesis'); + + return new Node\Node($args); + } +} diff --git a/vendor/symfony/expression-language/README.md b/vendor/symfony/expression-language/README.md new file mode 100644 index 0000000..2b2e3de --- /dev/null +++ b/vendor/symfony/expression-language/README.md @@ -0,0 +1,15 @@ +ExpressionLanguage Component +============================ + +The ExpressionLanguage component provides an engine that can compile and +evaluate expressions. An expression is a one-liner that returns a value +(mostly, but not limited to, Booleans). + +Resources +--------- + + * [Documentation](https://symfony.com/doc/current/components/expression_language/introduction.html) + * [Contributing](https://symfony.com/doc/current/contributing/index.html) + * [Report issues](https://github.com/symfony/symfony/issues) and + [send Pull Requests](https://github.com/symfony/symfony/pulls) + in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/vendor/symfony/expression-language/Resources/bin/generate_operator_regex.php b/vendor/symfony/expression-language/Resources/bin/generate_operator_regex.php new file mode 100644 index 0000000..179810e --- /dev/null +++ b/vendor/symfony/expression-language/Resources/bin/generate_operator_regex.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +if ('cli' !== \PHP_SAPI) { + throw new Exception('This script must be run from the command line.'); +} + +$operators = ['not', '!', 'or', '||', '&&', 'and', '|', '^', '&', '==', '===', '!=', '!==', '<', '>', '>=', '<=', 'not in', 'in', '..', '+', '-', '~', '*', '/', '%', 'contains', 'starts with', 'ends with', 'matches', '**']; +$operators = array_combine($operators, array_map('strlen', $operators)); +arsort($operators); + +$regex = []; +foreach ($operators as $operator => $length) { + // Collisions of character operators: + // - an operator that begins with a character must have a space or a parenthesis before or starting at the beginning of a string + // - an operator that ends with a character must be followed by a whitespace or a parenthesis + $regex[] = + (ctype_alpha($operator[0]) ? '(?<=^|[\s(])' : '') + .preg_quote($operator, '/') + .(ctype_alpha($operator[$length - 1]) ? '(?=[\s(])' : ''); +} + +echo '/'.implode('|', $regex).'/A'; diff --git a/vendor/symfony/expression-language/SerializedParsedExpression.php b/vendor/symfony/expression-language/SerializedParsedExpression.php new file mode 100644 index 0000000..5691907 --- /dev/null +++ b/vendor/symfony/expression-language/SerializedParsedExpression.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ExpressionLanguage; + +use Symfony\Component\ExpressionLanguage\Node\Node; + +/** + * Represents an already parsed expression. + * + * @author Fabien Potencier + */ +class SerializedParsedExpression extends ParsedExpression +{ + private string $nodes; + + /** + * @param string $expression An expression + * @param string $nodes The serialized nodes for the expression + */ + public function __construct(string $expression, string $nodes) + { + $this->expression = $expression; + $this->nodes = $nodes; + } + + /** + * @return Node + */ + public function getNodes() + { + return unserialize($this->nodes); + } +} diff --git a/vendor/symfony/expression-language/SyntaxError.php b/vendor/symfony/expression-language/SyntaxError.php new file mode 100644 index 0000000..e165dc2 --- /dev/null +++ b/vendor/symfony/expression-language/SyntaxError.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ExpressionLanguage; + +class SyntaxError extends \LogicException +{ + public function __construct(string $message, int $cursor = 0, string $expression = '', ?string $subject = null, ?array $proposals = null) + { + $message = sprintf('%s around position %d', rtrim($message, '.'), $cursor); + if ($expression) { + $message = sprintf('%s for expression `%s`', $message, $expression); + } + $message .= '.'; + + if (null !== $subject && null !== $proposals) { + $minScore = \INF; + foreach ($proposals as $proposal) { + $distance = levenshtein($subject, $proposal); + if ($distance < $minScore) { + $guess = $proposal; + $minScore = $distance; + } + } + + if (isset($guess) && $minScore < 3) { + $message .= sprintf(' Did you mean "%s"?', $guess); + } + } + + parent::__construct($message); + } +} diff --git a/vendor/symfony/expression-language/Token.php b/vendor/symfony/expression-language/Token.php new file mode 100644 index 0000000..99f721f --- /dev/null +++ b/vendor/symfony/expression-language/Token.php @@ -0,0 +1,58 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ExpressionLanguage; + +/** + * Represents a Token. + * + * @author Fabien Potencier + */ +class Token +{ + public $value; + public $type; + public $cursor; + + public const EOF_TYPE = 'end of expression'; + public const NAME_TYPE = 'name'; + public const NUMBER_TYPE = 'number'; + public const STRING_TYPE = 'string'; + public const OPERATOR_TYPE = 'operator'; + public const PUNCTUATION_TYPE = 'punctuation'; + + /** + * @param self::*_TYPE $type + * @param int|null $cursor The cursor position in the source + */ + public function __construct(string $type, string|int|float|null $value, ?int $cursor) + { + $this->type = $type; + $this->value = $value; + $this->cursor = $cursor; + } + + /** + * Returns a string representation of the token. + */ + public function __toString(): string + { + return sprintf('%3d %-11s %s', $this->cursor, strtoupper($this->type), $this->value); + } + + /** + * Tests the current token for a type and/or a value. + */ + public function test(string $type, ?string $value = null): bool + { + return $this->type === $type && (null === $value || $this->value == $value); + } +} diff --git a/vendor/symfony/expression-language/TokenStream.php b/vendor/symfony/expression-language/TokenStream.php new file mode 100644 index 0000000..9512a10 --- /dev/null +++ b/vendor/symfony/expression-language/TokenStream.php @@ -0,0 +1,87 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ExpressionLanguage; + +/** + * Represents a token stream. + * + * @author Fabien Potencier + */ +class TokenStream +{ + public $current; + + private array $tokens; + private int $position = 0; + private string $expression; + + public function __construct(array $tokens, string $expression = '') + { + $this->tokens = $tokens; + $this->current = $tokens[0]; + $this->expression = $expression; + } + + /** + * Returns a string representation of the token stream. + */ + public function __toString(): string + { + return implode("\n", $this->tokens); + } + + /** + * Sets the pointer to the next token and returns the old one. + * + * @return void + */ + public function next() + { + ++$this->position; + + if (!isset($this->tokens[$this->position])) { + throw new SyntaxError('Unexpected end of expression.', $this->current->cursor, $this->expression); + } + + $this->current = $this->tokens[$this->position]; + } + + /** + * @param string|null $message The syntax error message + * + * @return void + */ + public function expect(string $type, ?string $value = null, ?string $message = null) + { + $token = $this->current; + if (!$token->test($type, $value)) { + throw new SyntaxError(sprintf('%sUnexpected token "%s" of value "%s" ("%s" expected%s).', $message ? $message.'. ' : '', $token->type, $token->value, $type, $value ? sprintf(' with value "%s"', $value) : ''), $token->cursor, $this->expression); + } + $this->next(); + } + + /** + * Checks if end of stream was reached. + */ + public function isEOF(): bool + { + return Token::EOF_TYPE === $this->current->type; + } + + /** + * @internal + */ + public function getExpression(): string + { + return $this->expression; + } +} diff --git a/vendor/symfony/expression-language/composer.json b/vendor/symfony/expression-language/composer.json new file mode 100644 index 0000000..b123a5c --- /dev/null +++ b/vendor/symfony/expression-language/composer.json @@ -0,0 +1,31 @@ +{ + "name": "symfony/expression-language", + "type": "library", + "description": "Provides an engine that can compile and evaluate expressions", + "keywords": [], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/cache": "^5.4|^6.0|^7.0", + "symfony/service-contracts": "^2.5|^3" + }, + "autoload": { + "psr-4": { "Symfony\\Component\\ExpressionLanguage\\": "" }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "minimum-stability": "dev" +} diff --git a/vendor/symfony/service-contracts/Attribute/Required.php b/vendor/symfony/service-contracts/Attribute/Required.php new file mode 100644 index 0000000..9df8511 --- /dev/null +++ b/vendor/symfony/service-contracts/Attribute/Required.php @@ -0,0 +1,25 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Contracts\Service\Attribute; + +/** + * A required dependency. + * + * This attribute indicates that a property holds a required dependency. The annotated property or method should be + * considered during the instantiation process of the containing class. + * + * @author Alexander M. Turek + */ +#[\Attribute(\Attribute::TARGET_METHOD | \Attribute::TARGET_PROPERTY)] +final class Required +{ +} diff --git a/vendor/symfony/service-contracts/Attribute/SubscribedService.php b/vendor/symfony/service-contracts/Attribute/SubscribedService.php new file mode 100644 index 0000000..f850b84 --- /dev/null +++ b/vendor/symfony/service-contracts/Attribute/SubscribedService.php @@ -0,0 +1,47 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Contracts\Service\Attribute; + +use Symfony\Contracts\Service\ServiceMethodsSubscriberTrait; +use Symfony\Contracts\Service\ServiceSubscriberInterface; + +/** + * For use as the return value for {@see ServiceSubscriberInterface}. + * + * @example new SubscribedService('http_client', HttpClientInterface::class, false, new Target('githubApi')) + * + * Use with {@see ServiceMethodsSubscriberTrait} to mark a method's return type + * as a subscribed service. + * + * @author Kevin Bond + */ +#[\Attribute(\Attribute::TARGET_METHOD)] +final class SubscribedService +{ + /** @var object[] */ + public array $attributes; + + /** + * @param string|null $key The key to use for the service + * @param class-string|null $type The service class + * @param bool $nullable Whether the service is optional + * @param object|object[] $attributes One or more dependency injection attributes to use + */ + public function __construct( + public ?string $key = null, + public ?string $type = null, + public bool $nullable = false, + array|object $attributes = [], + ) { + $this->attributes = \is_array($attributes) ? $attributes : [$attributes]; + } +} diff --git a/vendor/symfony/service-contracts/CHANGELOG.md b/vendor/symfony/service-contracts/CHANGELOG.md new file mode 100644 index 0000000..7932e26 --- /dev/null +++ b/vendor/symfony/service-contracts/CHANGELOG.md @@ -0,0 +1,5 @@ +CHANGELOG +========= + +The changelog is maintained for all Symfony contracts at the following URL: +https://github.com/symfony/contracts/blob/main/CHANGELOG.md diff --git a/vendor/symfony/service-contracts/LICENSE b/vendor/symfony/service-contracts/LICENSE new file mode 100644 index 0000000..7536cae --- /dev/null +++ b/vendor/symfony/service-contracts/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2018-present Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/symfony/service-contracts/README.md b/vendor/symfony/service-contracts/README.md new file mode 100644 index 0000000..42841a5 --- /dev/null +++ b/vendor/symfony/service-contracts/README.md @@ -0,0 +1,9 @@ +Symfony Service Contracts +========================= + +A set of abstractions extracted out of the Symfony components. + +Can be used to build on semantics that the Symfony components proved useful and +that already have battle tested implementations. + +See https://github.com/symfony/contracts/blob/main/README.md for more information. diff --git a/vendor/symfony/service-contracts/ResetInterface.php b/vendor/symfony/service-contracts/ResetInterface.php new file mode 100644 index 0000000..a4f389b --- /dev/null +++ b/vendor/symfony/service-contracts/ResetInterface.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Contracts\Service; + +/** + * Provides a way to reset an object to its initial state. + * + * When calling the "reset()" method on an object, it should be put back to its + * initial state. This usually means clearing any internal buffers and forwarding + * the call to internal dependencies. All properties of the object should be put + * back to the same state it had when it was first ready to use. + * + * This method could be called, for example, to recycle objects that are used as + * services, so that they can be used to handle several requests in the same + * process loop (note that we advise making your services stateless instead of + * implementing this interface when possible.) + */ +interface ResetInterface +{ + /** + * @return void + */ + public function reset(); +} diff --git a/vendor/symfony/service-contracts/ServiceCollectionInterface.php b/vendor/symfony/service-contracts/ServiceCollectionInterface.php new file mode 100644 index 0000000..2333139 --- /dev/null +++ b/vendor/symfony/service-contracts/ServiceCollectionInterface.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Contracts\Service; + +/** + * A ServiceProviderInterface that is also countable and iterable. + * + * @author Kevin Bond + * + * @template-covariant T of mixed + * + * @extends ServiceProviderInterface + * @extends \IteratorAggregate + */ +interface ServiceCollectionInterface extends ServiceProviderInterface, \Countable, \IteratorAggregate +{ +} diff --git a/vendor/symfony/service-contracts/ServiceLocatorTrait.php b/vendor/symfony/service-contracts/ServiceLocatorTrait.php new file mode 100644 index 0000000..b62ec3e --- /dev/null +++ b/vendor/symfony/service-contracts/ServiceLocatorTrait.php @@ -0,0 +1,115 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Contracts\Service; + +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; + +// Help opcache.preload discover always-needed symbols +class_exists(ContainerExceptionInterface::class); +class_exists(NotFoundExceptionInterface::class); + +/** + * A trait to help implement ServiceProviderInterface. + * + * @author Robin Chalas + * @author Nicolas Grekas + */ +trait ServiceLocatorTrait +{ + private array $factories; + private array $loading = []; + private array $providedTypes; + + /** + * @param array $factories + */ + public function __construct(array $factories) + { + $this->factories = $factories; + } + + public function has(string $id): bool + { + return isset($this->factories[$id]); + } + + public function get(string $id): mixed + { + if (!isset($this->factories[$id])) { + throw $this->createNotFoundException($id); + } + + if (isset($this->loading[$id])) { + $ids = array_values($this->loading); + $ids = \array_slice($this->loading, array_search($id, $ids)); + $ids[] = $id; + + throw $this->createCircularReferenceException($id, $ids); + } + + $this->loading[$id] = $id; + try { + return $this->factories[$id]($this); + } finally { + unset($this->loading[$id]); + } + } + + public function getProvidedServices(): array + { + if (!isset($this->providedTypes)) { + $this->providedTypes = []; + + foreach ($this->factories as $name => $factory) { + if (!\is_callable($factory)) { + $this->providedTypes[$name] = '?'; + } else { + $type = (new \ReflectionFunction($factory))->getReturnType(); + + $this->providedTypes[$name] = $type ? ($type->allowsNull() ? '?' : '').($type instanceof \ReflectionNamedType ? $type->getName() : $type) : '?'; + } + } + } + + return $this->providedTypes; + } + + private function createNotFoundException(string $id): NotFoundExceptionInterface + { + if (!$alternatives = array_keys($this->factories)) { + $message = 'is empty...'; + } else { + $last = array_pop($alternatives); + if ($alternatives) { + $message = sprintf('only knows about the "%s" and "%s" services.', implode('", "', $alternatives), $last); + } else { + $message = sprintf('only knows about the "%s" service.', $last); + } + } + + if ($this->loading) { + $message = sprintf('The service "%s" has a dependency on a non-existent service "%s". This locator %s', end($this->loading), $id, $message); + } else { + $message = sprintf('Service "%s" not found: the current service locator %s', $id, $message); + } + + return new class($message) extends \InvalidArgumentException implements NotFoundExceptionInterface { + }; + } + + private function createCircularReferenceException(string $id, array $path): ContainerExceptionInterface + { + return new class(sprintf('Circular reference detected for service "%s", path: "%s".', $id, implode(' -> ', $path))) extends \RuntimeException implements ContainerExceptionInterface { + }; + } +} diff --git a/vendor/symfony/service-contracts/ServiceMethodsSubscriberTrait.php b/vendor/symfony/service-contracts/ServiceMethodsSubscriberTrait.php new file mode 100644 index 0000000..0d89d9f --- /dev/null +++ b/vendor/symfony/service-contracts/ServiceMethodsSubscriberTrait.php @@ -0,0 +1,80 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Contracts\Service; + +use Psr\Container\ContainerInterface; +use Symfony\Contracts\Service\Attribute\Required; +use Symfony\Contracts\Service\Attribute\SubscribedService; + +/** + * Implementation of ServiceSubscriberInterface that determines subscribed services + * from methods that have the #[SubscribedService] attribute. + * + * Service ids are available as "ClassName::methodName" so that the implementation + * of subscriber methods can be just `return $this->container->get(__METHOD__);`. + * + * @author Kevin Bond + */ +trait ServiceMethodsSubscriberTrait +{ + protected ContainerInterface $container; + + public static function getSubscribedServices(): array + { + $services = method_exists(get_parent_class(self::class) ?: '', __FUNCTION__) ? parent::getSubscribedServices() : []; + + foreach ((new \ReflectionClass(self::class))->getMethods() as $method) { + if (self::class !== $method->getDeclaringClass()->name) { + continue; + } + + if (!$attribute = $method->getAttributes(SubscribedService::class)[0] ?? null) { + continue; + } + + if ($method->isStatic() || $method->isAbstract() || $method->isGenerator() || $method->isInternal() || $method->getNumberOfRequiredParameters()) { + throw new \LogicException(sprintf('Cannot use "%s" on method "%s::%s()" (can only be used on non-static, non-abstract methods with no parameters).', SubscribedService::class, self::class, $method->name)); + } + + if (!$returnType = $method->getReturnType()) { + throw new \LogicException(sprintf('Cannot use "%s" on methods without a return type in "%s::%s()".', SubscribedService::class, $method->name, self::class)); + } + + /* @var SubscribedService $attribute */ + $attribute = $attribute->newInstance(); + $attribute->key ??= self::class.'::'.$method->name; + $attribute->type ??= $returnType instanceof \ReflectionNamedType ? $returnType->getName() : (string) $returnType; + $attribute->nullable = $returnType->allowsNull(); + + if ($attribute->attributes) { + $services[] = $attribute; + } else { + $services[$attribute->key] = ($attribute->nullable ? '?' : '').$attribute->type; + } + } + + return $services; + } + + #[Required] + public function setContainer(ContainerInterface $container): ?ContainerInterface + { + $ret = null; + if (method_exists(get_parent_class(self::class) ?: '', __FUNCTION__)) { + $ret = parent::setContainer($container); + } + + $this->container = $container; + + return $ret; + } +} diff --git a/vendor/symfony/service-contracts/ServiceProviderInterface.php b/vendor/symfony/service-contracts/ServiceProviderInterface.php new file mode 100644 index 0000000..2e71f00 --- /dev/null +++ b/vendor/symfony/service-contracts/ServiceProviderInterface.php @@ -0,0 +1,45 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Contracts\Service; + +use Psr\Container\ContainerInterface; + +/** + * A ServiceProviderInterface exposes the identifiers and the types of services provided by a container. + * + * @author Nicolas Grekas + * @author Mateusz Sip + * + * @template-covariant T of mixed + */ +interface ServiceProviderInterface extends ContainerInterface +{ + /** + * @return T + */ + public function get(string $id): mixed; + + public function has(string $id): bool; + + /** + * Returns an associative array of service types keyed by the identifiers provided by the current container. + * + * Examples: + * + * * ['logger' => 'Psr\Log\LoggerInterface'] means the object provides a service named "logger" that implements Psr\Log\LoggerInterface + * * ['foo' => '?'] means the container provides service name "foo" of unspecified type + * * ['bar' => '?Bar\Baz'] means the container provides a service "bar" of type Bar\Baz|null + * + * @return array The provided service types, keyed by service names + */ + public function getProvidedServices(): array; +} diff --git a/vendor/symfony/service-contracts/ServiceSubscriberInterface.php b/vendor/symfony/service-contracts/ServiceSubscriberInterface.php new file mode 100644 index 0000000..3da1916 --- /dev/null +++ b/vendor/symfony/service-contracts/ServiceSubscriberInterface.php @@ -0,0 +1,62 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Contracts\Service; + +use Symfony\Contracts\Service\Attribute\SubscribedService; + +/** + * A ServiceSubscriber exposes its dependencies via the static {@link getSubscribedServices} method. + * + * The getSubscribedServices method returns an array of service types required by such instances, + * optionally keyed by the service names used internally. Service types that start with an interrogation + * mark "?" are optional, while the other ones are mandatory service dependencies. + * + * The injected service locators SHOULD NOT allow access to any other services not specified by the method. + * + * It is expected that ServiceSubscriber instances consume PSR-11-based service locators internally. + * This interface does not dictate any injection method for these service locators, although constructor + * injection is recommended. + * + * @author Nicolas Grekas + */ +interface ServiceSubscriberInterface +{ + /** + * Returns an array of service types (or {@see SubscribedService} objects) required + * by such instances, optionally keyed by the service names used internally. + * + * For mandatory dependencies: + * + * * ['logger' => 'Psr\Log\LoggerInterface'] means the objects use the "logger" name + * internally to fetch a service which must implement Psr\Log\LoggerInterface. + * * ['loggers' => 'Psr\Log\LoggerInterface[]'] means the objects use the "loggers" name + * internally to fetch an iterable of Psr\Log\LoggerInterface instances. + * * ['Psr\Log\LoggerInterface'] is a shortcut for + * * ['Psr\Log\LoggerInterface' => 'Psr\Log\LoggerInterface'] + * + * otherwise: + * + * * ['logger' => '?Psr\Log\LoggerInterface'] denotes an optional dependency + * * ['loggers' => '?Psr\Log\LoggerInterface[]'] denotes an optional iterable dependency + * * ['?Psr\Log\LoggerInterface'] is a shortcut for + * * ['Psr\Log\LoggerInterface' => '?Psr\Log\LoggerInterface'] + * + * additionally, an array of {@see SubscribedService}'s can be returned: + * + * * [new SubscribedService('logger', Psr\Log\LoggerInterface::class)] + * * [new SubscribedService(type: Psr\Log\LoggerInterface::class, nullable: true)] + * * [new SubscribedService('http_client', HttpClientInterface::class, attributes: new Target('githubApi'))] + * + * @return string[]|SubscribedService[] The required service types, optionally keyed by service names + */ + public static function getSubscribedServices(): array; +} diff --git a/vendor/symfony/service-contracts/ServiceSubscriberTrait.php b/vendor/symfony/service-contracts/ServiceSubscriberTrait.php new file mode 100644 index 0000000..cc3bc32 --- /dev/null +++ b/vendor/symfony/service-contracts/ServiceSubscriberTrait.php @@ -0,0 +1,84 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Contracts\Service; + +use Psr\Container\ContainerInterface; +use Symfony\Contracts\Service\Attribute\Required; +use Symfony\Contracts\Service\Attribute\SubscribedService; + +trigger_deprecation('symfony/contracts', 'v3.5', '"%s" is deprecated, use "ServiceMethodsSubscriberTrait" instead.', ServiceSubscriberTrait::class); + +/** + * Implementation of ServiceSubscriberInterface that determines subscribed services + * from methods that have the #[SubscribedService] attribute. + * + * Service ids are available as "ClassName::methodName" so that the implementation + * of subscriber methods can be just `return $this->container->get(__METHOD__);`. + * + * @property ContainerInterface $container + * + * @author Kevin Bond + * + * @deprecated since symfony/contracts v3.5, use ServiceMethodsSubscriberTrait instead + */ +trait ServiceSubscriberTrait +{ + public static function getSubscribedServices(): array + { + $services = method_exists(get_parent_class(self::class) ?: '', __FUNCTION__) ? parent::getSubscribedServices() : []; + + foreach ((new \ReflectionClass(self::class))->getMethods() as $method) { + if (self::class !== $method->getDeclaringClass()->name) { + continue; + } + + if (!$attribute = $method->getAttributes(SubscribedService::class)[0] ?? null) { + continue; + } + + if ($method->isStatic() || $method->isAbstract() || $method->isGenerator() || $method->isInternal() || $method->getNumberOfRequiredParameters()) { + throw new \LogicException(sprintf('Cannot use "%s" on method "%s::%s()" (can only be used on non-static, non-abstract methods with no parameters).', SubscribedService::class, self::class, $method->name)); + } + + if (!$returnType = $method->getReturnType()) { + throw new \LogicException(sprintf('Cannot use "%s" on methods without a return type in "%s::%s()".', SubscribedService::class, $method->name, self::class)); + } + + /* @var SubscribedService $attribute */ + $attribute = $attribute->newInstance(); + $attribute->key ??= self::class.'::'.$method->name; + $attribute->type ??= $returnType instanceof \ReflectionNamedType ? $returnType->getName() : (string) $returnType; + $attribute->nullable = $returnType->allowsNull(); + + if ($attribute->attributes) { + $services[] = $attribute; + } else { + $services[$attribute->key] = ($attribute->nullable ? '?' : '').$attribute->type; + } + } + + return $services; + } + + #[Required] + public function setContainer(ContainerInterface $container): ?ContainerInterface + { + $ret = null; + if (method_exists(get_parent_class(self::class) ?: '', __FUNCTION__)) { + $ret = parent::setContainer($container); + } + + $this->container = $container; + + return $ret; + } +} diff --git a/vendor/symfony/service-contracts/Test/ServiceLocatorTest.php b/vendor/symfony/service-contracts/Test/ServiceLocatorTest.php new file mode 100644 index 0000000..07d12b4 --- /dev/null +++ b/vendor/symfony/service-contracts/Test/ServiceLocatorTest.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Contracts\Service\Test; + +class_alias(ServiceLocatorTestCase::class, ServiceLocatorTest::class); + +if (false) { + /** + * @deprecated since PHPUnit 9.6 + */ + class ServiceLocatorTest + { + } +} diff --git a/vendor/symfony/service-contracts/Test/ServiceLocatorTestCase.php b/vendor/symfony/service-contracts/Test/ServiceLocatorTestCase.php new file mode 100644 index 0000000..65a3fe3 --- /dev/null +++ b/vendor/symfony/service-contracts/Test/ServiceLocatorTestCase.php @@ -0,0 +1,96 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Contracts\Service\Test; + +use PHPUnit\Framework\TestCase; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\ContainerInterface; +use Psr\Container\NotFoundExceptionInterface; +use Symfony\Contracts\Service\ServiceLocatorTrait; + +abstract class ServiceLocatorTestCase extends TestCase +{ + protected function getServiceLocator(array $factories): ContainerInterface + { + return new class($factories) implements ContainerInterface { + use ServiceLocatorTrait; + }; + } + + public function testHas() + { + $locator = $this->getServiceLocator([ + 'foo' => fn () => 'bar', + 'bar' => fn () => 'baz', + fn () => 'dummy', + ]); + + $this->assertTrue($locator->has('foo')); + $this->assertTrue($locator->has('bar')); + $this->assertFalse($locator->has('dummy')); + } + + public function testGet() + { + $locator = $this->getServiceLocator([ + 'foo' => fn () => 'bar', + 'bar' => fn () => 'baz', + ]); + + $this->assertSame('bar', $locator->get('foo')); + $this->assertSame('baz', $locator->get('bar')); + } + + public function testGetDoesNotMemoize() + { + $i = 0; + $locator = $this->getServiceLocator([ + 'foo' => function () use (&$i) { + ++$i; + + return 'bar'; + }, + ]); + + $this->assertSame('bar', $locator->get('foo')); + $this->assertSame('bar', $locator->get('foo')); + $this->assertSame(2, $i); + } + + public function testThrowsOnUndefinedInternalService() + { + $locator = $this->getServiceLocator([ + 'foo' => function () use (&$locator) { return $locator->get('bar'); }, + ]); + + if (!$this->getExpectedException()) { + $this->expectException(NotFoundExceptionInterface::class); + $this->expectExceptionMessage('The service "foo" has a dependency on a non-existent service "bar". This locator only knows about the "foo" service.'); + } + + $locator->get('foo'); + } + + public function testThrowsOnCircularReference() + { + $locator = $this->getServiceLocator([ + 'foo' => function () use (&$locator) { return $locator->get('bar'); }, + 'bar' => function () use (&$locator) { return $locator->get('baz'); }, + 'baz' => function () use (&$locator) { return $locator->get('bar'); }, + ]); + + $this->expectException(ContainerExceptionInterface::class); + $this->expectExceptionMessage('Circular reference detected for service "bar", path: "bar -> baz -> bar".'); + + $locator->get('foo'); + } +} diff --git a/vendor/symfony/service-contracts/composer.json b/vendor/symfony/service-contracts/composer.json new file mode 100644 index 0000000..fc8674a --- /dev/null +++ b/vendor/symfony/service-contracts/composer.json @@ -0,0 +1,42 @@ +{ + "name": "symfony/service-contracts", + "type": "library", + "description": "Generic abstractions related to writing services", + "keywords": ["abstractions", "contracts", "decoupling", "interfaces", "interoperability", "standards"], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": ">=8.1", + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "autoload": { + "psr-4": { "Symfony\\Contracts\\Service\\": "" }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-main": "3.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + } +} diff --git a/vendor/symfony/var-exporter/CHANGELOG.md b/vendor/symfony/var-exporter/CHANGELOG.md new file mode 100644 index 0000000..74333ea --- /dev/null +++ b/vendor/symfony/var-exporter/CHANGELOG.md @@ -0,0 +1,30 @@ +CHANGELOG +========= + +7.2 +--- + + * Allow reinitializing lazy objects with a new initializer + +6.4 +--- + + * Deprecate per-property lazy-initializers + +6.2 +--- + + * Add support for lazy ghost objects and virtual proxies + * Add `Hydrator::hydrate()` + * Preserve PHP references also when using `Hydrator::hydrate()` or `Instantiator::instantiate()` + * Add support for hydrating from native (array) casts + +5.1.0 +----- + + * added argument `array &$foundClasses` to `VarExporter::export()` to ease with preloading exported values + +4.2.0 +----- + + * added the component diff --git a/vendor/symfony/var-exporter/Exception/ClassNotFoundException.php b/vendor/symfony/var-exporter/Exception/ClassNotFoundException.php new file mode 100644 index 0000000..2acecc4 --- /dev/null +++ b/vendor/symfony/var-exporter/Exception/ClassNotFoundException.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarExporter\Exception; + +class ClassNotFoundException extends \Exception implements ExceptionInterface +{ + public function __construct(string $class, ?\Throwable $previous = null) + { + parent::__construct(\sprintf('Class "%s" not found.', $class), 0, $previous); + } +} diff --git a/vendor/symfony/var-exporter/Exception/ExceptionInterface.php b/vendor/symfony/var-exporter/Exception/ExceptionInterface.php new file mode 100644 index 0000000..adfaed4 --- /dev/null +++ b/vendor/symfony/var-exporter/Exception/ExceptionInterface.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarExporter\Exception; + +interface ExceptionInterface extends \Throwable +{ +} diff --git a/vendor/symfony/var-exporter/Exception/LogicException.php b/vendor/symfony/var-exporter/Exception/LogicException.php new file mode 100644 index 0000000..619d055 --- /dev/null +++ b/vendor/symfony/var-exporter/Exception/LogicException.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarExporter\Exception; + +class LogicException extends \LogicException implements ExceptionInterface +{ +} diff --git a/vendor/symfony/var-exporter/Exception/NotInstantiableTypeException.php b/vendor/symfony/var-exporter/Exception/NotInstantiableTypeException.php new file mode 100644 index 0000000..bc2bcaa --- /dev/null +++ b/vendor/symfony/var-exporter/Exception/NotInstantiableTypeException.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarExporter\Exception; + +class NotInstantiableTypeException extends \Exception implements ExceptionInterface +{ + public function __construct(string $type, ?\Throwable $previous = null) + { + parent::__construct(\sprintf('Type "%s" is not instantiable.', $type), 0, $previous); + } +} diff --git a/vendor/symfony/var-exporter/Hydrator.php b/vendor/symfony/var-exporter/Hydrator.php new file mode 100644 index 0000000..5f456fb --- /dev/null +++ b/vendor/symfony/var-exporter/Hydrator.php @@ -0,0 +1,78 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarExporter; + +use Symfony\Component\VarExporter\Internal\Hydrator as InternalHydrator; + +/** + * Utility class to hydrate the properties of an object. + * + * @author Nicolas Grekas + */ +final class Hydrator +{ + /** + * Sets the properties of an object, including private and protected ones. + * + * For example: + * + * // Sets the public or protected $object->propertyName property + * Hydrator::hydrate($object, ['propertyName' => $propertyValue]); + * + * // Sets a private property defined on its parent Bar class: + * Hydrator::hydrate($object, ["\0Bar\0privateBarProperty" => $propertyValue]); + * + * // Alternative way to set the private $object->privateBarProperty property + * Hydrator::hydrate($object, [], [ + * Bar::class => ['privateBarProperty' => $propertyValue], + * ]); + * + * Instances of ArrayObject, ArrayIterator and SplObjectStorage can be hydrated + * by using the special "\0" property name to define their internal value: + * + * // Hydrates an SplObjectStorage where $info1 is attached to $obj1, etc. + * Hydrator::hydrate($object, ["\0" => [$obj1, $info1, $obj2, $info2...]]); + * + * // Hydrates an ArrayObject populated with $inputArray + * Hydrator::hydrate($object, ["\0" => [$inputArray]]); + * + * @template T of object + * + * @param T $instance The object to hydrate + * @param array $properties The properties to set on the instance + * @param array> $scopedProperties The properties to set on the instance, + * keyed by their declaring class + * + * @return T + */ + public static function hydrate(object $instance, array $properties = [], array $scopedProperties = []): object + { + if ($properties) { + $class = $instance::class; + $propertyScopes = InternalHydrator::$propertyScopes[$class] ??= InternalHydrator::getPropertyScopes($class); + + foreach ($properties as $name => &$value) { + [$scope, $name, $readonlyScope] = $propertyScopes[$name] ?? [$class, $name, $class]; + $scopedProperties[$readonlyScope ?? $scope][$name] = &$value; + } + unset($value); + } + + foreach ($scopedProperties as $scope => $properties) { + if ($properties) { + (InternalHydrator::$simpleHydrators[$scope] ??= InternalHydrator::getSimpleHydrator($scope))($properties, $instance); + } + } + + return $instance; + } +} diff --git a/vendor/symfony/var-exporter/Instantiator.php b/vendor/symfony/var-exporter/Instantiator.php new file mode 100644 index 0000000..10200c0 --- /dev/null +++ b/vendor/symfony/var-exporter/Instantiator.php @@ -0,0 +1,59 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarExporter; + +use Symfony\Component\VarExporter\Exception\ExceptionInterface; +use Symfony\Component\VarExporter\Exception\NotInstantiableTypeException; +use Symfony\Component\VarExporter\Internal\Registry; + +/** + * A utility class to create objects without calling their constructor. + * + * @author Nicolas Grekas + */ +final class Instantiator +{ + /** + * Creates an object and sets its properties without calling its constructor nor any other methods. + * + * @see Hydrator::hydrate() for examples + * + * @template T of object + * + * @param class-string $class The class of the instance to create + * @param array $properties The properties to set on the instance + * @param array> $scopedProperties The properties to set on the instance, + * keyed by their declaring class + * + * @return T + * + * @throws ExceptionInterface When the instance cannot be created + */ + public static function instantiate(string $class, array $properties = [], array $scopedProperties = []): object + { + $reflector = Registry::$reflectors[$class] ??= Registry::getClassReflector($class); + + if (Registry::$cloneable[$class]) { + $instance = clone Registry::$prototypes[$class]; + } elseif (Registry::$instantiableWithoutConstructor[$class]) { + $instance = $reflector->newInstanceWithoutConstructor(); + } elseif (null === Registry::$prototypes[$class]) { + throw new NotInstantiableTypeException($class); + } elseif ($reflector->implementsInterface('Serializable') && !method_exists($class, '__unserialize')) { + $instance = unserialize('C:'.\strlen($class).':"'.$class.'":0:{}'); + } else { + $instance = unserialize('O:'.\strlen($class).':"'.$class.'":0:{}'); + } + + return $properties || $scopedProperties ? Hydrator::hydrate($instance, $properties, $scopedProperties) : $instance; + } +} diff --git a/vendor/symfony/var-exporter/Internal/Exporter.php b/vendor/symfony/var-exporter/Internal/Exporter.php new file mode 100644 index 0000000..6544ae2 --- /dev/null +++ b/vendor/symfony/var-exporter/Internal/Exporter.php @@ -0,0 +1,418 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarExporter\Internal; + +use Symfony\Component\VarExporter\Exception\NotInstantiableTypeException; + +/** + * @author Nicolas Grekas + * + * @internal + */ +class Exporter +{ + /** + * Prepares an array of values for VarExporter. + * + * For performance this method is public and has no type-hints. + * + * @param array &$values + * @param \SplObjectStorage $objectsPool + * @param array &$refsPool + * @param int &$objectsCount + * @param bool &$valuesAreStatic + * + * @return array + * + * @throws NotInstantiableTypeException When a value cannot be serialized + */ + public static function prepare($values, $objectsPool, &$refsPool, &$objectsCount, &$valuesAreStatic) + { + $refs = $values; + foreach ($values as $k => $value) { + if (\is_resource($value)) { + throw new NotInstantiableTypeException(get_resource_type($value).' resource'); + } + $refs[$k] = $objectsPool; + + if ($isRef = !$valueIsStatic = $values[$k] !== $objectsPool) { + $values[$k] = &$value; // Break hard references to make $values completely + unset($value); // independent from the original structure + $refs[$k] = $value = $values[$k]; + if ($value instanceof Reference && 0 > $value->id) { + $valuesAreStatic = false; + ++$value->count; + continue; + } + $refsPool[] = [&$refs[$k], $value, &$value]; + $refs[$k] = $values[$k] = new Reference(-\count($refsPool), $value); + } + + if (\is_array($value)) { + if ($value) { + $value = self::prepare($value, $objectsPool, $refsPool, $objectsCount, $valueIsStatic); + } + goto handle_value; + } elseif (!\is_object($value) || $value instanceof \UnitEnum) { + goto handle_value; + } + + $valueIsStatic = false; + if (isset($objectsPool[$value])) { + ++$objectsCount; + $value = new Reference($objectsPool[$value][0]); + goto handle_value; + } + + $class = $value::class; + $reflector = Registry::$reflectors[$class] ??= Registry::getClassReflector($class); + $properties = []; + + if ($reflector->hasMethod('__serialize')) { + if (!$reflector->getMethod('__serialize')->isPublic()) { + throw new \Error(\sprintf('Call to %s method "%s::__serialize()".', $reflector->getMethod('__serialize')->isProtected() ? 'protected' : 'private', $class)); + } + + if (!\is_array($serializeProperties = $value->__serialize())) { + throw new \TypeError($class.'::__serialize() must return an array'); + } + + if ($reflector->hasMethod('__unserialize')) { + $properties = $serializeProperties; + } else { + foreach ($serializeProperties as $n => $v) { + $c = $reflector->hasProperty($n) && ($p = $reflector->getProperty($n))->isReadOnly() ? $p->class : 'stdClass'; + $properties[$c][$n] = $v; + } + } + + goto prepare_value; + } + + $sleep = null; + $proto = Registry::$prototypes[$class]; + + if (($value instanceof \ArrayIterator || $value instanceof \ArrayObject) && null !== $proto) { + // ArrayIterator and ArrayObject need special care because their "flags" + // option changes the behavior of the (array) casting operator. + [$arrayValue, $properties] = self::getArrayObjectProperties($value, $proto); + + // populates Registry::$prototypes[$class] with a new instance + Registry::getClassReflector($class, Registry::$instantiableWithoutConstructor[$class], Registry::$cloneable[$class]); + } elseif ($value instanceof \SplObjectStorage && Registry::$cloneable[$class] && null !== $proto) { + // By implementing Serializable, SplObjectStorage breaks + // internal references; let's deal with it on our own. + foreach (clone $value as $v) { + $properties[] = $v; + $properties[] = $value[$v]; + } + $properties = ['SplObjectStorage' => ["\0" => $properties]]; + $arrayValue = (array) $value; + } elseif ($value instanceof \Serializable + || $value instanceof \__PHP_Incomplete_Class + ) { + ++$objectsCount; + $objectsPool[$value] = [$id = \count($objectsPool), serialize($value), [], 0]; + $value = new Reference($id); + goto handle_value; + } else { + if (method_exists($class, '__sleep')) { + if (!\is_array($sleep = $value->__sleep())) { + trigger_error('serialize(): __sleep should return an array only containing the names of instance-variables to serialize', \E_USER_NOTICE); + $value = null; + goto handle_value; + } + $sleep = array_flip($sleep); + } + + $arrayValue = (array) $value; + } + + $proto = (array) $proto; + + foreach ($arrayValue as $name => $v) { + $i = 0; + $n = (string) $name; + if ('' === $n || "\0" !== $n[0]) { + $c = $reflector->hasProperty($n) && ($p = $reflector->getProperty($n))->isReadOnly() ? $p->class : 'stdClass'; + } elseif ('*' === $n[1]) { + $n = substr($n, 3); + $c = $reflector->getProperty($n)->class; + if ('Error' === $c) { + $c = 'TypeError'; + } elseif ('Exception' === $c) { + $c = 'ErrorException'; + } + } else { + $i = strpos($n, "\0", 2); + $c = substr($n, 1, $i - 1); + $n = substr($n, 1 + $i); + } + if (null !== $sleep) { + if (!isset($sleep[$name]) && (!isset($sleep[$n]) || ($i && $c !== $class))) { + unset($arrayValue[$name]); + continue; + } + unset($sleep[$name], $sleep[$n]); + } + if (!\array_key_exists($name, $proto) || $proto[$name] !== $v || "\x00Error\x00trace" === $name || "\x00Exception\x00trace" === $name) { + $properties[$c][$n] = $v; + } + } + if ($sleep) { + foreach ($sleep as $n => $v) { + trigger_error(\sprintf('serialize(): "%s" returned as member variable from __sleep() but does not exist', $n), \E_USER_NOTICE); + } + } + if (method_exists($class, '__unserialize')) { + $properties = $arrayValue; + } + + prepare_value: + $objectsPool[$value] = [$id = \count($objectsPool)]; + $properties = self::prepare($properties, $objectsPool, $refsPool, $objectsCount, $valueIsStatic); + ++$objectsCount; + $objectsPool[$value] = [$id, $class, $properties, method_exists($class, '__unserialize') ? -$objectsCount : (method_exists($class, '__wakeup') ? $objectsCount : 0)]; + + $value = new Reference($id); + + handle_value: + if ($isRef) { + unset($value); // Break the hard reference created above + } elseif (!$valueIsStatic) { + $values[$k] = $value; + } + $valuesAreStatic = $valueIsStatic && $valuesAreStatic; + } + + return $values; + } + + public static function export($value, $indent = '') + { + switch (true) { + case \is_int($value) || \is_float($value): return var_export($value, true); + case [] === $value: return '[]'; + case false === $value: return 'false'; + case true === $value: return 'true'; + case null === $value: return 'null'; + case '' === $value: return "''"; + case $value instanceof \UnitEnum: return '\\'.ltrim(var_export($value, true), '\\'); + } + + if ($value instanceof Reference) { + if (0 <= $value->id) { + return '$o['.$value->id.']'; + } + if (!$value->count) { + return self::export($value->value, $indent); + } + $value = -$value->id; + + return '&$r['.$value.']'; + } + $subIndent = $indent.' '; + + if (\is_string($value)) { + $code = \sprintf("'%s'", addcslashes($value, "'\\")); + + $code = preg_replace_callback("/((?:[\\0\\r\\n]|\u{202A}|\u{202B}|\u{202D}|\u{202E}|\u{2066}|\u{2067}|\u{2068}|\u{202C}|\u{2069})++)(.)/", function ($m) use ($subIndent) { + $m[1] = \sprintf('\'."%s".\'', str_replace( + ["\0", "\r", "\n", "\u{202A}", "\u{202B}", "\u{202D}", "\u{202E}", "\u{2066}", "\u{2067}", "\u{2068}", "\u{202C}", "\u{2069}", '\n\\'], + ['\0', '\r', '\n', '\u{202A}', '\u{202B}', '\u{202D}', '\u{202E}', '\u{2066}', '\u{2067}', '\u{2068}', '\u{202C}', '\u{2069}', '\n"'."\n".$subIndent.'."\\'], + $m[1] + )); + + if ("'" === $m[2]) { + return substr($m[1], 0, -2); + } + + if (str_ends_with($m[1], 'n".\'')) { + return substr_replace($m[1], "\n".$subIndent.".'".$m[2], -2); + } + + return $m[1].$m[2]; + }, $code, -1, $count); + + if ($count && str_starts_with($code, "''.")) { + $code = substr($code, 3); + } + + return $code; + } + + if (\is_array($value)) { + $j = -1; + $code = ''; + foreach ($value as $k => $v) { + $code .= $subIndent; + if (!\is_int($k) || 1 !== $k - $j) { + $code .= self::export($k, $subIndent).' => '; + } + if (\is_int($k) && $k > $j) { + $j = $k; + } + $code .= self::export($v, $subIndent).",\n"; + } + + return "[\n".$code.$indent.']'; + } + + if ($value instanceof Values) { + $code = $subIndent."\$r = [],\n"; + foreach ($value->values as $k => $v) { + $code .= $subIndent.'$r['.$k.'] = '.self::export($v, $subIndent).",\n"; + } + + return "[\n".$code.$indent.']'; + } + + if ($value instanceof Registry) { + return self::exportRegistry($value, $indent, $subIndent); + } + + if ($value instanceof Hydrator) { + return self::exportHydrator($value, $indent, $subIndent); + } + + throw new \UnexpectedValueException(\sprintf('Cannot export value of type "%s".', get_debug_type($value))); + } + + private static function exportRegistry(Registry $value, string $indent, string $subIndent): string + { + $code = ''; + $serializables = []; + $seen = []; + $prototypesAccess = 0; + $factoriesAccess = 0; + $r = '\\'.Registry::class; + $j = -1; + + foreach ($value->classes as $k => $class) { + if (':' === ($class[1] ?? null)) { + $serializables[$k] = $class; + continue; + } + if (!Registry::$instantiableWithoutConstructor[$class]) { + if (is_subclass_of($class, 'Serializable') && !method_exists($class, '__unserialize')) { + $serializables[$k] = 'C:'.\strlen($class).':"'.$class.'":0:{}'; + } else { + $serializables[$k] = 'O:'.\strlen($class).':"'.$class.'":0:{}'; + } + if (is_subclass_of($class, 'Throwable')) { + $eol = is_subclass_of($class, 'Error') ? "\0Error\0" : "\0Exception\0"; + $serializables[$k] = substr_replace($serializables[$k], '1:{s:'.(5 + \strlen($eol)).':"'.$eol.'trace";a:0:{}}', -4); + } + continue; + } + $code .= $subIndent.(1 !== $k - $j ? $k.' => ' : ''); + $j = $k; + $eol = ",\n"; + $c = '['.self::export($class).']'; + + if ($seen[$class] ?? false) { + if (Registry::$cloneable[$class]) { + ++$prototypesAccess; + $code .= 'clone $p'.$c; + } else { + ++$factoriesAccess; + $code .= '$f'.$c.'()'; + } + } else { + $seen[$class] = true; + if (Registry::$cloneable[$class]) { + $code .= 'clone ('.($prototypesAccess++ ? '$p' : '($p = &'.$r.'::$prototypes)').$c.' ?? '.$r.'::p'; + } else { + $code .= '('.($factoriesAccess++ ? '$f' : '($f = &'.$r.'::$factories)').$c.' ?? '.$r.'::f'; + $eol = '()'.$eol; + } + $code .= '('.substr($c, 1, -1).'))'; + } + $code .= $eol; + } + + if (1 === $prototypesAccess) { + $code = str_replace('($p = &'.$r.'::$prototypes)', $r.'::$prototypes', $code); + } + if (1 === $factoriesAccess) { + $code = str_replace('($f = &'.$r.'::$factories)', $r.'::$factories', $code); + } + if ('' !== $code) { + $code = "\n".$code.$indent; + } + + if ($serializables) { + $code = $r.'::unserialize(['.$code.'], '.self::export($serializables, $indent).')'; + } else { + $code = '['.$code.']'; + } + + return '$o = '.$code; + } + + private static function exportHydrator(Hydrator $value, string $indent, string $subIndent): string + { + $code = ''; + foreach ($value->properties as $class => $properties) { + $code .= $subIndent.' '.self::export($class).' => '.self::export($properties, $subIndent.' ').",\n"; + } + + $code = [ + self::export($value->registry, $subIndent), + self::export($value->values, $subIndent), + '' !== $code ? "[\n".$code.$subIndent.']' : '[]', + self::export($value->value, $subIndent), + self::export($value->wakeups, $subIndent), + ]; + + return '\\'.$value::class."::hydrate(\n".$subIndent.implode(",\n".$subIndent, $code)."\n".$indent.')'; + } + + /** + * @param \ArrayIterator|\ArrayObject $value + * @param \ArrayIterator|\ArrayObject $proto + */ + private static function getArrayObjectProperties($value, $proto): array + { + $reflector = $value instanceof \ArrayIterator ? 'ArrayIterator' : 'ArrayObject'; + $reflector = Registry::$reflectors[$reflector] ??= Registry::getClassReflector($reflector); + + $properties = [ + $arrayValue = (array) $value, + $reflector->getMethod('getFlags')->invoke($value), + $value instanceof \ArrayObject ? $reflector->getMethod('getIteratorClass')->invoke($value) : 'ArrayIterator', + ]; + + $reflector = $reflector->getMethod('setFlags'); + $reflector->invoke($proto, \ArrayObject::STD_PROP_LIST); + + if ($properties[1] & \ArrayObject::STD_PROP_LIST) { + $reflector->invoke($value, 0); + $properties[0] = (array) $value; + } else { + $reflector->invoke($value, \ArrayObject::STD_PROP_LIST); + $arrayValue = (array) $value; + } + $reflector->invoke($value, $properties[1]); + + if ([[], 0, 'ArrayIterator'] === $properties) { + $properties = []; + } else { + if ('ArrayIterator' === $properties[2]) { + unset($properties[2]); + } + $properties = [$reflector->class => ["\0" => $properties]]; + } + + return [$arrayValue, $properties]; + } +} diff --git a/vendor/symfony/var-exporter/Internal/Hydrator.php b/vendor/symfony/var-exporter/Internal/Hydrator.php new file mode 100644 index 0000000..4092363 --- /dev/null +++ b/vendor/symfony/var-exporter/Internal/Hydrator.php @@ -0,0 +1,298 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarExporter\Internal; + +use Symfony\Component\VarExporter\Exception\ClassNotFoundException; + +/** + * @author Nicolas Grekas + * + * @internal + */ +class Hydrator +{ + public static array $hydrators = []; + public static array $simpleHydrators = []; + public static array $propertyScopes = []; + + public function __construct( + public readonly Registry $registry, + public readonly ?Values $values, + public readonly array $properties, + public readonly mixed $value, + public readonly array $wakeups, + ) { + } + + public static function hydrate($objects, $values, $properties, $value, $wakeups) + { + foreach ($properties as $class => $vars) { + (self::$hydrators[$class] ??= self::getHydrator($class))($vars, $objects); + } + foreach ($wakeups as $k => $v) { + if (\is_array($v)) { + $objects[-$k]->__unserialize($v); + } else { + $objects[$v]->__wakeup(); + } + } + + return $value; + } + + public static function getHydrator($class) + { + $baseHydrator = self::$hydrators['stdClass'] ??= static function ($properties, $objects) { + foreach ($properties as $name => $values) { + foreach ($values as $i => $v) { + $objects[$i]->$name = $v; + } + } + }; + + switch ($class) { + case 'stdClass': + return $baseHydrator; + + case 'ErrorException': + return $baseHydrator->bindTo(null, new class extends \ErrorException { + }); + + case 'TypeError': + return $baseHydrator->bindTo(null, new class extends \Error { + }); + + case 'SplObjectStorage': + return static function ($properties, $objects) { + foreach ($properties as $name => $values) { + if ("\0" === $name) { + foreach ($values as $i => $v) { + for ($j = 0; $j < \count($v); ++$j) { + $objects[$i]->attach($v[$j], $v[++$j]); + } + } + continue; + } + foreach ($values as $i => $v) { + $objects[$i]->$name = $v; + } + } + }; + } + + if (!class_exists($class) && !interface_exists($class, false) && !trait_exists($class, false)) { + throw new ClassNotFoundException($class); + } + $classReflector = new \ReflectionClass($class); + + switch ($class) { + case 'ArrayIterator': + case 'ArrayObject': + $constructor = $classReflector->getConstructor()->invokeArgs(...); + + return static function ($properties, $objects) use ($constructor) { + foreach ($properties as $name => $values) { + if ("\0" !== $name) { + foreach ($values as $i => $v) { + $objects[$i]->$name = $v; + } + } + } + foreach ($properties["\0"] ?? [] as $i => $v) { + $constructor($objects[$i], $v); + } + }; + } + + if (!$classReflector->isInternal()) { + return $baseHydrator->bindTo(null, $class); + } + + if ($classReflector->name !== $class) { + return self::$hydrators[$classReflector->name] ??= self::getHydrator($classReflector->name); + } + + $propertySetters = []; + foreach ($classReflector->getProperties() as $propertyReflector) { + if (!$propertyReflector->isStatic()) { + $propertySetters[$propertyReflector->name] = $propertyReflector->setValue(...); + } + } + + if (!$propertySetters) { + return $baseHydrator; + } + + return static function ($properties, $objects) use ($propertySetters) { + foreach ($properties as $name => $values) { + if ($setValue = $propertySetters[$name] ?? null) { + foreach ($values as $i => $v) { + $setValue($objects[$i], $v); + } + continue; + } + foreach ($values as $i => $v) { + $objects[$i]->$name = $v; + } + } + }; + } + + public static function getSimpleHydrator($class) + { + $baseHydrator = self::$simpleHydrators['stdClass'] ??= (function ($properties, $object) { + $readonly = (array) $this; + + foreach ($properties as $name => &$value) { + $object->$name = $value; + + if (!($readonly[$name] ?? false)) { + $object->$name = &$value; + } + } + })->bindTo(new \stdClass()); + + switch ($class) { + case 'stdClass': + return $baseHydrator; + + case 'ErrorException': + return $baseHydrator->bindTo(new \stdClass(), new class extends \ErrorException { + }); + + case 'TypeError': + return $baseHydrator->bindTo(new \stdClass(), new class extends \Error { + }); + + case 'SplObjectStorage': + return static function ($properties, $object) { + foreach ($properties as $name => &$value) { + if ("\0" !== $name) { + $object->$name = $value; + $object->$name = &$value; + continue; + } + for ($i = 0; $i < \count($value); ++$i) { + $object->attach($value[$i], $value[++$i]); + } + } + }; + } + + if (!class_exists($class) && !interface_exists($class, false) && !trait_exists($class, false)) { + throw new ClassNotFoundException($class); + } + $classReflector = new \ReflectionClass($class); + + switch ($class) { + case 'ArrayIterator': + case 'ArrayObject': + $constructor = $classReflector->getConstructor()->invokeArgs(...); + + return static function ($properties, $object) use ($constructor) { + foreach ($properties as $name => &$value) { + if ("\0" === $name) { + $constructor($object, $value); + } else { + $object->$name = $value; + $object->$name = &$value; + } + } + }; + } + + if (!$classReflector->isInternal()) { + $readonly = new \stdClass(); + foreach ($classReflector->getProperties(\ReflectionProperty::IS_READONLY) as $propertyReflector) { + if ($class === $propertyReflector->class) { + $readonly->{$propertyReflector->name} = true; + } + } + + return $baseHydrator->bindTo($readonly, $class); + } + + if ($classReflector->name !== $class) { + return self::$simpleHydrators[$classReflector->name] ??= self::getSimpleHydrator($classReflector->name); + } + + $propertySetters = []; + foreach ($classReflector->getProperties() as $propertyReflector) { + if (!$propertyReflector->isStatic()) { + $propertySetters[$propertyReflector->name] = $propertyReflector->setValue(...); + } + } + + if (!$propertySetters) { + return $baseHydrator; + } + + return static function ($properties, $object) use ($propertySetters) { + foreach ($properties as $name => &$value) { + if ($setValue = $propertySetters[$name] ?? null) { + $setValue($object, $value); + } else { + $object->$name = $value; + $object->$name = &$value; + } + } + }; + } + + public static function getPropertyScopes($class): array + { + $propertyScopes = []; + $r = new \ReflectionClass($class); + + foreach ($r->getProperties() as $property) { + $flags = $property->getModifiers(); + + if (\ReflectionProperty::IS_STATIC & $flags) { + continue; + } + $name = $property->name; + $readonlyScope = null; + + if (\ReflectionProperty::IS_PRIVATE & $flags) { + if ($flags & \ReflectionProperty::IS_READONLY) { + $readonlyScope = $class; + } + $propertyScopes["\0$class\0$name"] = $propertyScopes[$name] = [$class, $name, $readonlyScope, $property]; + + continue; + } + if ($flags & \ReflectionProperty::IS_READONLY) { + $readonlyScope = $property->class; + } + $propertyScopes[$name] = [$class, $name, $readonlyScope, $property]; + + if (\ReflectionProperty::IS_PROTECTED & $flags) { + $propertyScopes["\0*\0$name"] = $propertyScopes[$name]; + } + } + + while ($r = $r->getParentClass()) { + $class = $r->name; + + foreach ($r->getProperties(\ReflectionProperty::IS_PRIVATE) as $property) { + if (!$property->isStatic()) { + $name = $property->name; + $readonlyScope = $property->isReadOnly() ? $class : null; + $propertyScopes["\0$class\0$name"] = [$class, $name, $readonlyScope, $property]; + $propertyScopes[$name] ??= [$class, $name, $readonlyScope, $property]; + } + } + } + + return $propertyScopes; + } +} diff --git a/vendor/symfony/var-exporter/Internal/LazyObjectRegistry.php b/vendor/symfony/var-exporter/Internal/LazyObjectRegistry.php new file mode 100644 index 0000000..f6450ce --- /dev/null +++ b/vendor/symfony/var-exporter/Internal/LazyObjectRegistry.php @@ -0,0 +1,138 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarExporter\Internal; + +/** + * Stores the state of lazy objects and caches related reflection information. + * + * As a micro-optimization, this class uses no type declarations. + * + * @internal + */ +class LazyObjectRegistry +{ + /** + * @var array + */ + public static array $classReflectors = []; + + /** + * @var array> + */ + public static array $defaultProperties = []; + + /** + * @var array> + */ + public static array $classResetters = []; + + /** + * @var array + */ + public static array $classAccessors = []; + + /** + * @var array + */ + public static array $parentMethods = []; + + public static ?\Closure $noInitializerState = null; + + public static function getClassResetters($class) + { + $classProperties = []; + + if ((self::$classReflectors[$class] ??= new \ReflectionClass($class))->isInternal()) { + $propertyScopes = []; + } else { + $propertyScopes = Hydrator::$propertyScopes[$class] ??= Hydrator::getPropertyScopes($class); + } + + foreach ($propertyScopes as $key => [$scope, $name, $readonlyScope]) { + $propertyScopes[$k = "\0$scope\0$name"] ?? $propertyScopes[$k = "\0*\0$name"] ?? $k = $name; + + if ($k === $key && "\0$class\0lazyObjectState" !== $k) { + $classProperties[$readonlyScope ?? $scope][$name] = $key; + } + } + + $resetters = []; + foreach ($classProperties as $scope => $properties) { + $resetters[] = \Closure::bind(static function ($instance, $skippedProperties) use ($properties) { + foreach ($properties as $name => $key) { + if (!\array_key_exists($key, $skippedProperties)) { + unset($instance->$name); + } + } + }, null, $scope); + } + + return $resetters; + } + + public static function getClassAccessors($class) + { + return \Closure::bind(static fn () => [ + 'get' => static function &($instance, $name, $readonly) { + if (!$readonly) { + return $instance->$name; + } + $value = $instance->$name; + + return $value; + }, + 'set' => static function ($instance, $name, $value) { + $instance->$name = $value; + }, + 'isset' => static fn ($instance, $name) => isset($instance->$name), + 'unset' => static function ($instance, $name) { + unset($instance->$name); + }, + ], null, \Closure::class === $class ? null : $class)(); + } + + public static function getParentMethods($class) + { + $parent = get_parent_class($class); + $methods = []; + + foreach (['set', 'isset', 'unset', 'clone', 'serialize', 'unserialize', 'sleep', 'wakeup', 'destruct', 'get'] as $method) { + if (!$parent || !method_exists($parent, '__'.$method)) { + $methods[$method] = false; + } else { + $m = new \ReflectionMethod($parent, '__'.$method); + $methods[$method] = !$m->isAbstract() && !$m->isPrivate(); + } + } + + $methods['get'] = $methods['get'] ? ($m->returnsReference() ? 2 : 1) : 0; + + return $methods; + } + + public static function getScope($propertyScopes, $class, $property, $readonlyScope = null) + { + if (null === $readonlyScope && !isset($propertyScopes[$k = "\0$class\0$property"]) && !isset($propertyScopes[$k = "\0*\0$property"])) { + return null; + } + $frame = debug_backtrace(\DEBUG_BACKTRACE_PROVIDE_OBJECT | \DEBUG_BACKTRACE_IGNORE_ARGS, 3)[2]; + + if (\ReflectionProperty::class === $scope = $frame['class'] ?? \Closure::class) { + $scope = $frame['object']->class; + } + if (null === $readonlyScope && '*' === $k[1] && ($class === $scope || (is_subclass_of($class, $scope) && !isset($propertyScopes["\0$scope\0$property"])))) { + return null; + } + + return $scope; + } +} diff --git a/vendor/symfony/var-exporter/Internal/LazyObjectState.php b/vendor/symfony/var-exporter/Internal/LazyObjectState.php new file mode 100644 index 0000000..30fbff1 --- /dev/null +++ b/vendor/symfony/var-exporter/Internal/LazyObjectState.php @@ -0,0 +1,97 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarExporter\Internal; + +use Symfony\Component\VarExporter\Hydrator as PublicHydrator; + +/** + * Keeps the state of lazy objects. + * + * As a micro-optimization, this class uses no type declarations. + * + * @internal + */ +class LazyObjectState +{ + public const STATUS_UNINITIALIZED_FULL = 1; + public const STATUS_UNINITIALIZED_PARTIAL = 2; + public const STATUS_INITIALIZED_FULL = 3; + public const STATUS_INITIALIZED_PARTIAL = 4; + + /** + * @var self::STATUS_* + */ + public int $status = self::STATUS_UNINITIALIZED_FULL; + + public object $realInstance; + + /** + * @param array $skippedProperties + */ + public function __construct( + public \Closure $initializer, + public array $skippedProperties = [], + ) { + } + + public function initialize($instance, $propertyName, $propertyScope) + { + if (self::STATUS_UNINITIALIZED_FULL !== $this->status) { + return $this->status; + } + + $this->status = self::STATUS_INITIALIZED_PARTIAL; + + try { + if ($defaultProperties = array_diff_key(LazyObjectRegistry::$defaultProperties[$instance::class], $this->skippedProperties)) { + PublicHydrator::hydrate($instance, $defaultProperties); + } + + ($this->initializer)($instance); + } catch (\Throwable $e) { + $this->status = self::STATUS_UNINITIALIZED_FULL; + $this->reset($instance); + + throw $e; + } + + return $this->status = self::STATUS_INITIALIZED_FULL; + } + + public function reset($instance): void + { + $class = $instance::class; + $propertyScopes = Hydrator::$propertyScopes[$class] ??= Hydrator::getPropertyScopes($class); + $skippedProperties = $this->skippedProperties; + $properties = (array) $instance; + + foreach ($propertyScopes as $key => [$scope, $name, $readonlyScope]) { + $propertyScopes[$k = "\0$scope\0$name"] ?? $propertyScopes[$k = "\0*\0$name"] ?? $k = $name; + + if ($k === $key && (null !== $readonlyScope || !\array_key_exists($k, $properties))) { + $skippedProperties[$k] = true; + } + } + + foreach (LazyObjectRegistry::$classResetters[$class] as $reset) { + $reset($instance, $skippedProperties); + } + + foreach ((array) $instance as $name => $value) { + if ("\0" !== ($name[0] ?? '') && !\array_key_exists($name, $skippedProperties)) { + unset($instance->$name); + } + } + + $this->status = self::STATUS_UNINITIALIZED_FULL; + } +} diff --git a/vendor/symfony/var-exporter/Internal/LazyObjectTrait.php b/vendor/symfony/var-exporter/Internal/LazyObjectTrait.php new file mode 100644 index 0000000..4a6f232 --- /dev/null +++ b/vendor/symfony/var-exporter/Internal/LazyObjectTrait.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarExporter\Internal; + +use Symfony\Component\Serializer\Attribute\Ignore; + +if (\PHP_VERSION_ID >= 80300) { + /** + * @internal + */ + trait LazyObjectTrait + { + #[Ignore] + private readonly LazyObjectState $lazyObjectState; + } +} else { + /** + * @internal + */ + trait LazyObjectTrait + { + #[Ignore] + private LazyObjectState $lazyObjectState; + } +} diff --git a/vendor/symfony/var-exporter/Internal/Reference.php b/vendor/symfony/var-exporter/Internal/Reference.php new file mode 100644 index 0000000..2c7bd7b --- /dev/null +++ b/vendor/symfony/var-exporter/Internal/Reference.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarExporter\Internal; + +/** + * @author Nicolas Grekas + * + * @internal + */ +class Reference +{ + public int $count = 0; + + public function __construct( + public readonly int $id, + public readonly mixed $value = null, + ) { + } +} diff --git a/vendor/symfony/var-exporter/Internal/Registry.php b/vendor/symfony/var-exporter/Internal/Registry.php new file mode 100644 index 0000000..9c41684 --- /dev/null +++ b/vendor/symfony/var-exporter/Internal/Registry.php @@ -0,0 +1,142 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarExporter\Internal; + +use Symfony\Component\VarExporter\Exception\ClassNotFoundException; +use Symfony\Component\VarExporter\Exception\NotInstantiableTypeException; + +/** + * @author Nicolas Grekas + * + * @internal + */ +class Registry +{ + public static array $reflectors = []; + public static array $prototypes = []; + public static array $factories = []; + public static array $cloneable = []; + public static array $instantiableWithoutConstructor = []; + + public function __construct( + public readonly array $classes, + ) { + } + + public static function unserialize($objects, $serializables) + { + $unserializeCallback = ini_set('unserialize_callback_func', __CLASS__.'::getClassReflector'); + + try { + foreach ($serializables as $k => $v) { + $objects[$k] = unserialize($v); + } + } finally { + ini_set('unserialize_callback_func', $unserializeCallback); + } + + return $objects; + } + + public static function p($class) + { + self::getClassReflector($class, true, true); + + return self::$prototypes[$class]; + } + + public static function f($class) + { + $reflector = self::$reflectors[$class] ??= self::getClassReflector($class, true, false); + + return self::$factories[$class] = [$reflector, 'newInstanceWithoutConstructor'](...); + } + + public static function getClassReflector($class, $instantiableWithoutConstructor = false, $cloneable = null) + { + if (!($isClass = class_exists($class)) && !interface_exists($class, false) && !trait_exists($class, false)) { + throw new ClassNotFoundException($class); + } + $reflector = new \ReflectionClass($class); + + if ($instantiableWithoutConstructor) { + $proto = $reflector->newInstanceWithoutConstructor(); + } elseif (!$isClass || $reflector->isAbstract()) { + throw new NotInstantiableTypeException($class); + } elseif ($reflector->name !== $class) { + $reflector = self::$reflectors[$name = $reflector->name] ??= self::getClassReflector($name, false, $cloneable); + self::$cloneable[$class] = self::$cloneable[$name]; + self::$instantiableWithoutConstructor[$class] = self::$instantiableWithoutConstructor[$name]; + self::$prototypes[$class] = self::$prototypes[$name]; + + return $reflector; + } else { + try { + $proto = $reflector->newInstanceWithoutConstructor(); + $instantiableWithoutConstructor = true; + } catch (\ReflectionException) { + $proto = $reflector->implementsInterface('Serializable') && !method_exists($class, '__unserialize') ? 'C:' : 'O:'; + if ('C:' === $proto && !$reflector->getMethod('unserialize')->isInternal()) { + $proto = null; + } else { + try { + $proto = @unserialize($proto.\strlen($class).':"'.$class.'":0:{}'); + } catch (\Exception $e) { + if (__FILE__ !== $e->getFile()) { + throw $e; + } + throw new NotInstantiableTypeException($class, $e); + } + if (false === $proto) { + throw new NotInstantiableTypeException($class); + } + } + } + if (null !== $proto && !$proto instanceof \Throwable && !$proto instanceof \Serializable && !method_exists($class, '__sleep') && !method_exists($class, '__serialize')) { + try { + serialize($proto); + } catch (\Exception $e) { + throw new NotInstantiableTypeException($class, $e); + } + } + } + + if (null === $cloneable) { + if (($proto instanceof \Reflector || $proto instanceof \ReflectionGenerator || $proto instanceof \ReflectionType || $proto instanceof \IteratorIterator || $proto instanceof \RecursiveIteratorIterator) && (!$proto instanceof \Serializable && !method_exists($proto, '__wakeup') && !method_exists($class, '__unserialize'))) { + throw new NotInstantiableTypeException($class); + } + + $cloneable = $reflector->isCloneable() && !$reflector->hasMethod('__clone'); + } + + self::$cloneable[$class] = $cloneable; + self::$instantiableWithoutConstructor[$class] = $instantiableWithoutConstructor; + self::$prototypes[$class] = $proto; + + if ($proto instanceof \Throwable) { + static $setTrace; + + if (null === $setTrace) { + $setTrace = [ + new \ReflectionProperty(\Error::class, 'trace'), + new \ReflectionProperty(\Exception::class, 'trace'), + ]; + $setTrace[0] = $setTrace[0]->setValue(...); + $setTrace[1] = $setTrace[1]->setValue(...); + } + + $setTrace[$proto instanceof \Exception]($proto, []); + } + + return $reflector; + } +} diff --git a/vendor/symfony/var-exporter/Internal/Values.php b/vendor/symfony/var-exporter/Internal/Values.php new file mode 100644 index 0000000..4f20a82 --- /dev/null +++ b/vendor/symfony/var-exporter/Internal/Values.php @@ -0,0 +1,25 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarExporter\Internal; + +/** + * @author Nicolas Grekas + * + * @internal + */ +class Values +{ + public function __construct( + public readonly array $values, + ) { + } +} diff --git a/vendor/symfony/var-exporter/LICENSE b/vendor/symfony/var-exporter/LICENSE new file mode 100644 index 0000000..7536cae --- /dev/null +++ b/vendor/symfony/var-exporter/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2018-present Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/symfony/var-exporter/LazyGhostTrait.php b/vendor/symfony/var-exporter/LazyGhostTrait.php new file mode 100644 index 0000000..72a96d4 --- /dev/null +++ b/vendor/symfony/var-exporter/LazyGhostTrait.php @@ -0,0 +1,363 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarExporter; + +use Symfony\Component\Serializer\Attribute\Ignore; +use Symfony\Component\VarExporter\Internal\Hydrator; +use Symfony\Component\VarExporter\Internal\LazyObjectRegistry as Registry; +use Symfony\Component\VarExporter\Internal\LazyObjectState; +use Symfony\Component\VarExporter\Internal\LazyObjectTrait; + +trait LazyGhostTrait +{ + use LazyObjectTrait; + + /** + * Creates a lazy-loading ghost instance. + * + * Skipped properties should be indexed by their array-cast identifier, see + * https://php.net/manual/language.types.array#language.types.array.casting + * + * @param \Closure(static):void $initializer The closure should initialize the object it receives as argument + * @param array|null $skippedProperties An array indexed by the properties to skip, a.k.a. the ones + * that the initializer doesn't initialize, if any + * @param static|null $instance + */ + public static function createLazyGhost(\Closure $initializer, ?array $skippedProperties = null, ?object $instance = null): static + { + if (self::class !== $class = $instance ? $instance::class : static::class) { + $skippedProperties["\0".self::class."\0lazyObjectState"] = true; + } + + if (!isset(Registry::$defaultProperties[$class])) { + Registry::$classReflectors[$class] ??= new \ReflectionClass($class); + $instance ??= Registry::$classReflectors[$class]->newInstanceWithoutConstructor(); + Registry::$defaultProperties[$class] ??= (array) $instance; + Registry::$classResetters[$class] ??= Registry::getClassResetters($class); + + if (self::class === $class && \defined($class.'::LAZY_OBJECT_PROPERTY_SCOPES')) { + Hydrator::$propertyScopes[$class] ??= $class::LAZY_OBJECT_PROPERTY_SCOPES; + } + } else { + $instance ??= Registry::$classReflectors[$class]->newInstanceWithoutConstructor(); + } + + if (isset($instance->lazyObjectState)) { + $instance->lazyObjectState->initializer = $initializer; + $instance->lazyObjectState->skippedProperties = $skippedProperties ??= []; + + if (LazyObjectState::STATUS_UNINITIALIZED_FULL !== $instance->lazyObjectState->status) { + $instance->lazyObjectState->reset($instance); + } + + return $instance; + } + + $instance->lazyObjectState = new LazyObjectState($initializer, $skippedProperties ??= []); + + foreach (Registry::$classResetters[$class] as $reset) { + $reset($instance, $skippedProperties); + } + + return $instance; + } + + /** + * Returns whether the object is initialized. + * + * @param bool $partial Whether partially initialized objects should be considered as initialized + */ + #[Ignore] + public function isLazyObjectInitialized(bool $partial = false): bool + { + if (!$state = $this->lazyObjectState ?? null) { + return true; + } + + return LazyObjectState::STATUS_INITIALIZED_FULL === $state->status; + } + + /** + * Forces initialization of a lazy object and returns it. + */ + public function initializeLazyObject(): static + { + if (!$state = $this->lazyObjectState ?? null) { + return $this; + } + + if (LazyObjectState::STATUS_UNINITIALIZED_FULL === $state->status) { + $state->initialize($this, '', null); + } + + return $this; + } + + /** + * @return bool Returns false when the object cannot be reset, ie when it's not a lazy object + */ + public function resetLazyObject(): bool + { + if (!$state = $this->lazyObjectState ?? null) { + return false; + } + + if (LazyObjectState::STATUS_UNINITIALIZED_FULL !== $state->status) { + $state->reset($this); + } + + return true; + } + + public function &__get($name): mixed + { + $propertyScopes = Hydrator::$propertyScopes[$this::class] ??= Hydrator::getPropertyScopes($this::class); + $scope = null; + + if ([$class, , $readonlyScope] = $propertyScopes[$name] ?? null) { + $scope = Registry::getScope($propertyScopes, $class, $name); + $state = $this->lazyObjectState ?? null; + + if ($state && (null === $scope || isset($propertyScopes["\0$scope\0$name"]))) { + if (LazyObjectState::STATUS_INITIALIZED_FULL === $state->status) { + // Work around php/php-src#12695 + $property = null === $scope ? $name : "\0$scope\0$name"; + $property = $propertyScopes[$property][3] + ?? Hydrator::$propertyScopes[$this::class][$property][3] = new \ReflectionProperty($scope ?? $class, $name); + } else { + $property = null; + } + + if ($property?->isInitialized($this) ?? LazyObjectState::STATUS_UNINITIALIZED_PARTIAL !== $state->initialize($this, $name, $readonlyScope ?? $scope)) { + goto get_in_scope; + } + } + } + + if ($parent = (Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['get']) { + if (2 === $parent) { + return parent::__get($name); + } + $value = parent::__get($name); + + return $value; + } + + if (null === $class) { + $frame = debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS, 1)[0]; + trigger_error(\sprintf('Undefined property: %s::$%s in %s on line %s', $this::class, $name, $frame['file'], $frame['line']), \E_USER_NOTICE); + } + + get_in_scope: + + try { + if (null === $scope) { + if (null === $readonlyScope) { + return $this->$name; + } + $value = $this->$name; + + return $value; + } + $accessor = Registry::$classAccessors[$scope] ??= Registry::getClassAccessors($scope); + + return $accessor['get']($this, $name, null !== $readonlyScope); + } catch (\Error $e) { + if (\Error::class !== $e::class || !str_starts_with($e->getMessage(), 'Cannot access uninitialized non-nullable property')) { + throw $e; + } + + try { + if (null === $scope) { + $this->$name = []; + + return $this->$name; + } + + $accessor['set']($this, $name, []); + + return $accessor['get']($this, $name, null !== $readonlyScope); + } catch (\Error) { + if (preg_match('/^Cannot access uninitialized non-nullable property ([^ ]++) by reference$/', $e->getMessage(), $matches)) { + throw new \Error('Typed property '.$matches[1].' must not be accessed before initialization', $e->getCode(), $e->getPrevious()); + } + + throw $e; + } + } + } + + public function __set($name, $value): void + { + $propertyScopes = Hydrator::$propertyScopes[$this::class] ??= Hydrator::getPropertyScopes($this::class); + $scope = null; + + if ([$class, , $readonlyScope] = $propertyScopes[$name] ?? null) { + $scope = Registry::getScope($propertyScopes, $class, $name, $readonlyScope); + $state = $this->lazyObjectState ?? null; + + if ($state && ($readonlyScope === $scope || isset($propertyScopes["\0$scope\0$name"])) + && LazyObjectState::STATUS_INITIALIZED_FULL !== $state->status + ) { + if (LazyObjectState::STATUS_UNINITIALIZED_FULL === $state->status) { + $state->initialize($this, $name, $readonlyScope ?? $scope); + } + goto set_in_scope; + } + } + + if ((Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['set']) { + parent::__set($name, $value); + + return; + } + + set_in_scope: + + if (null === $scope) { + $this->$name = $value; + } else { + $accessor = Registry::$classAccessors[$scope] ??= Registry::getClassAccessors($scope); + $accessor['set']($this, $name, $value); + } + } + + public function __isset($name): bool + { + $propertyScopes = Hydrator::$propertyScopes[$this::class] ??= Hydrator::getPropertyScopes($this::class); + $scope = null; + + if ([$class, , $readonlyScope] = $propertyScopes[$name] ?? null) { + $scope = Registry::getScope($propertyScopes, $class, $name); + $state = $this->lazyObjectState ?? null; + + if ($state && (null === $scope || isset($propertyScopes["\0$scope\0$name"])) + && LazyObjectState::STATUS_INITIALIZED_FULL !== $state->status + && LazyObjectState::STATUS_UNINITIALIZED_PARTIAL !== $state->initialize($this, $name, $readonlyScope ?? $scope) + ) { + goto isset_in_scope; + } + } + + if ((Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['isset']) { + return parent::__isset($name); + } + + isset_in_scope: + + if (null === $scope) { + return isset($this->$name); + } + $accessor = Registry::$classAccessors[$scope] ??= Registry::getClassAccessors($scope); + + return $accessor['isset']($this, $name); + } + + public function __unset($name): void + { + $propertyScopes = Hydrator::$propertyScopes[$this::class] ??= Hydrator::getPropertyScopes($this::class); + $scope = null; + + if ([$class, , $readonlyScope] = $propertyScopes[$name] ?? null) { + $scope = Registry::getScope($propertyScopes, $class, $name, $readonlyScope); + $state = $this->lazyObjectState ?? null; + + if ($state && ($readonlyScope === $scope || isset($propertyScopes["\0$scope\0$name"])) + && LazyObjectState::STATUS_INITIALIZED_FULL !== $state->status + ) { + if (LazyObjectState::STATUS_UNINITIALIZED_FULL === $state->status) { + $state->initialize($this, $name, $readonlyScope ?? $scope); + } + goto unset_in_scope; + } + } + + if ((Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['unset']) { + parent::__unset($name); + + return; + } + + unset_in_scope: + + if (null === $scope) { + unset($this->$name); + } else { + $accessor = Registry::$classAccessors[$scope] ??= Registry::getClassAccessors($scope); + $accessor['unset']($this, $name); + } + } + + public function __clone(): void + { + if ($state = $this->lazyObjectState ?? null) { + $this->lazyObjectState = clone $state; + } + + if ((Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['clone']) { + parent::__clone(); + } + } + + public function __serialize(): array + { + $class = self::class; + + if ((Registry::$parentMethods[$class] ??= Registry::getParentMethods($class))['serialize']) { + $properties = parent::__serialize(); + } else { + $this->initializeLazyObject(); + $properties = (array) $this; + } + unset($properties["\0$class\0lazyObjectState"]); + + if (Registry::$parentMethods[$class]['serialize'] || !Registry::$parentMethods[$class]['sleep']) { + return $properties; + } + + $scope = get_parent_class($class); + $data = []; + + foreach (parent::__sleep() as $name) { + $value = $properties[$k = $name] ?? $properties[$k = "\0*\0$name"] ?? $properties[$k = "\0$class\0$name"] ?? $properties[$k = "\0$scope\0$name"] ?? $k = null; + + if (null === $k) { + trigger_error(\sprintf('serialize(): "%s" returned as member variable from __sleep() but does not exist', $name), \E_USER_NOTICE); + } else { + $data[$k] = $value; + } + } + + return $data; + } + + public function __destruct() + { + $state = $this->lazyObjectState ?? null; + + if (LazyObjectState::STATUS_UNINITIALIZED_FULL === $state?->status) { + return; + } + + if ((Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['destruct']) { + parent::__destruct(); + } + } + + #[Ignore] + private function setLazyObjectAsInitialized(bool $initialized): void + { + if ($state = $this->lazyObjectState ?? null) { + $state->status = $initialized ? LazyObjectState::STATUS_INITIALIZED_FULL : LazyObjectState::STATUS_UNINITIALIZED_FULL; + } + } +} diff --git a/vendor/symfony/var-exporter/LazyObjectInterface.php b/vendor/symfony/var-exporter/LazyObjectInterface.php new file mode 100644 index 0000000..3422dc6 --- /dev/null +++ b/vendor/symfony/var-exporter/LazyObjectInterface.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarExporter; + +interface LazyObjectInterface +{ + /** + * Returns whether the object is initialized. + * + * @param bool $partial Whether partially initialized objects should be considered as initialized + */ + public function isLazyObjectInitialized(bool $partial = false): bool; + + /** + * Forces initialization of a lazy object and returns it. + */ + public function initializeLazyObject(): object; + + /** + * @return bool Returns false when the object cannot be reset, ie when it's not a lazy object + */ + public function resetLazyObject(): bool; +} diff --git a/vendor/symfony/var-exporter/LazyProxyTrait.php b/vendor/symfony/var-exporter/LazyProxyTrait.php new file mode 100644 index 0000000..795e4d7 --- /dev/null +++ b/vendor/symfony/var-exporter/LazyProxyTrait.php @@ -0,0 +1,366 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarExporter; + +use Symfony\Component\Serializer\Attribute\Ignore; +use Symfony\Component\VarExporter\Hydrator as PublicHydrator; +use Symfony\Component\VarExporter\Internal\Hydrator; +use Symfony\Component\VarExporter\Internal\LazyObjectRegistry as Registry; +use Symfony\Component\VarExporter\Internal\LazyObjectState; +use Symfony\Component\VarExporter\Internal\LazyObjectTrait; + +trait LazyProxyTrait +{ + use LazyObjectTrait; + + /** + * Creates a lazy-loading virtual proxy. + * + * @param \Closure():object $initializer Returns the proxied object + * @param static|null $instance + */ + public static function createLazyProxy(\Closure $initializer, ?object $instance = null): static + { + if (self::class !== $class = $instance ? $instance::class : static::class) { + $skippedProperties = ["\0".self::class."\0lazyObjectState" => true]; + } + + if (!isset(Registry::$defaultProperties[$class])) { + Registry::$classReflectors[$class] ??= new \ReflectionClass($class); + $instance ??= Registry::$classReflectors[$class]->newInstanceWithoutConstructor(); + Registry::$defaultProperties[$class] ??= (array) $instance; + Registry::$classResetters[$class] ??= Registry::getClassResetters($class); + + if (self::class === $class && \defined($class.'::LAZY_OBJECT_PROPERTY_SCOPES')) { + Hydrator::$propertyScopes[$class] ??= $class::LAZY_OBJECT_PROPERTY_SCOPES; + } + } else { + $instance ??= Registry::$classReflectors[$class]->newInstanceWithoutConstructor(); + } + + if (isset($instance->lazyObjectState)) { + $instance->lazyObjectState->initializer = $initializer; + unset($instance->lazyObjectState->realInstance); + + return $instance; + } + + $instance->lazyObjectState = new LazyObjectState($initializer); + + foreach (Registry::$classResetters[$class] as $reset) { + $reset($instance, $skippedProperties ??= []); + } + + return $instance; + } + + /** + * Returns whether the object is initialized. + * + * @param bool $partial Whether partially initialized objects should be considered as initialized + */ + #[Ignore] + public function isLazyObjectInitialized(bool $partial = false): bool + { + return !isset($this->lazyObjectState) || isset($this->lazyObjectState->realInstance) || Registry::$noInitializerState === $this->lazyObjectState->initializer; + } + + /** + * Forces initialization of a lazy object and returns it. + */ + public function initializeLazyObject(): parent + { + if ($state = $this->lazyObjectState ?? null) { + return $state->realInstance ??= ($state->initializer)(); + } + + return $this; + } + + /** + * @return bool Returns false when the object cannot be reset, ie when it's not a lazy object + */ + public function resetLazyObject(): bool + { + if (!isset($this->lazyObjectState) || Registry::$noInitializerState === $this->lazyObjectState->initializer) { + return false; + } + + unset($this->lazyObjectState->realInstance); + + return true; + } + + public function &__get($name): mixed + { + $propertyScopes = Hydrator::$propertyScopes[$this::class] ??= Hydrator::getPropertyScopes($this::class); + $scope = null; + $instance = $this; + + if ([$class, , $readonlyScope] = $propertyScopes[$name] ?? null) { + $scope = Registry::getScope($propertyScopes, $class, $name); + + if (null === $scope || isset($propertyScopes["\0$scope\0$name"])) { + if ($state = $this->lazyObjectState ?? null) { + $instance = $state->realInstance ??= ($state->initializer)(); + } + $parent = 2; + goto get_in_scope; + } + } + $parent = (Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['get']; + + if ($state = $this->lazyObjectState ?? null) { + $instance = $state->realInstance ??= ($state->initializer)(); + } else { + if (2 === $parent) { + return parent::__get($name); + } + $value = parent::__get($name); + + return $value; + } + + if (!$parent && null === $class && !\array_key_exists($name, (array) $instance)) { + $frame = debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS, 1)[0]; + trigger_error(\sprintf('Undefined property: %s::$%s in %s on line %s', $instance::class, $name, $frame['file'], $frame['line']), \E_USER_NOTICE); + } + + get_in_scope: + + try { + if (null === $scope) { + if (null === $readonlyScope && 1 !== $parent) { + return $instance->$name; + } + $value = $instance->$name; + + return $value; + } + $accessor = Registry::$classAccessors[$scope] ??= Registry::getClassAccessors($scope); + + return $accessor['get']($instance, $name, null !== $readonlyScope || 1 === $parent); + } catch (\Error $e) { + if (\Error::class !== $e::class || !str_starts_with($e->getMessage(), 'Cannot access uninitialized non-nullable property')) { + throw $e; + } + + try { + if (null === $scope) { + $instance->$name = []; + + return $instance->$name; + } + + $accessor['set']($instance, $name, []); + + return $accessor['get']($instance, $name, null !== $readonlyScope || 1 === $parent); + } catch (\Error) { + throw $e; + } + } + } + + public function __set($name, $value): void + { + $propertyScopes = Hydrator::$propertyScopes[$this::class] ??= Hydrator::getPropertyScopes($this::class); + $scope = null; + $instance = $this; + + if ([$class, , $readonlyScope] = $propertyScopes[$name] ?? null) { + $scope = Registry::getScope($propertyScopes, $class, $name, $readonlyScope); + + if ($readonlyScope === $scope || isset($propertyScopes["\0$scope\0$name"])) { + if ($state = $this->lazyObjectState ?? null) { + $instance = $state->realInstance ??= ($state->initializer)(); + } + goto set_in_scope; + } + } + + if ($state = $this->lazyObjectState ?? null) { + $instance = $state->realInstance ??= ($state->initializer)(); + } elseif ((Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['set']) { + parent::__set($name, $value); + + return; + } + + set_in_scope: + + if (null === $scope) { + $instance->$name = $value; + } else { + $accessor = Registry::$classAccessors[$scope] ??= Registry::getClassAccessors($scope); + $accessor['set']($instance, $name, $value); + } + } + + public function __isset($name): bool + { + $propertyScopes = Hydrator::$propertyScopes[$this::class] ??= Hydrator::getPropertyScopes($this::class); + $scope = null; + $instance = $this; + + if ([$class] = $propertyScopes[$name] ?? null) { + $scope = Registry::getScope($propertyScopes, $class, $name); + + if (null === $scope || isset($propertyScopes["\0$scope\0$name"])) { + if ($state = $this->lazyObjectState ?? null) { + $instance = $state->realInstance ??= ($state->initializer)(); + } + goto isset_in_scope; + } + } + + if ($state = $this->lazyObjectState ?? null) { + $instance = $state->realInstance ??= ($state->initializer)(); + } elseif ((Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['isset']) { + return parent::__isset($name); + } + + isset_in_scope: + + if (null === $scope) { + return isset($instance->$name); + } + $accessor = Registry::$classAccessors[$scope] ??= Registry::getClassAccessors($scope); + + return $accessor['isset']($instance, $name); + } + + public function __unset($name): void + { + $propertyScopes = Hydrator::$propertyScopes[$this::class] ??= Hydrator::getPropertyScopes($this::class); + $scope = null; + $instance = $this; + + if ([$class, , $readonlyScope] = $propertyScopes[$name] ?? null) { + $scope = Registry::getScope($propertyScopes, $class, $name, $readonlyScope); + + if ($readonlyScope === $scope || isset($propertyScopes["\0$scope\0$name"])) { + if ($state = $this->lazyObjectState ?? null) { + $instance = $state->realInstance ??= ($state->initializer)(); + } + goto unset_in_scope; + } + } + + if ($state = $this->lazyObjectState ?? null) { + $instance = $state->realInstance ??= ($state->initializer)(); + } elseif ((Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['unset']) { + parent::__unset($name); + + return; + } + + unset_in_scope: + + if (null === $scope) { + unset($instance->$name); + } else { + $accessor = Registry::$classAccessors[$scope] ??= Registry::getClassAccessors($scope); + $accessor['unset']($instance, $name); + } + } + + public function __clone(): void + { + if (!isset($this->lazyObjectState)) { + if ((Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['clone']) { + parent::__clone(); + } + + return; + } + + $this->lazyObjectState = clone $this->lazyObjectState; + + if (isset($this->lazyObjectState->realInstance)) { + $this->lazyObjectState->realInstance = clone $this->lazyObjectState->realInstance; + } + } + + public function __serialize(): array + { + $class = self::class; + $state = $this->lazyObjectState ?? null; + + if (!$state && (Registry::$parentMethods[$class] ??= Registry::getParentMethods($class))['serialize']) { + $properties = parent::__serialize(); + } else { + $properties = (array) $this; + + if ($state) { + unset($properties["\0$class\0lazyObjectState"]); + $properties["\0$class\0lazyObjectReal"] = $state->realInstance ??= ($state->initializer)(); + } + } + + if ($state || Registry::$parentMethods[$class]['serialize'] || !Registry::$parentMethods[$class]['sleep']) { + return $properties; + } + + $scope = get_parent_class($class); + $data = []; + + foreach (parent::__sleep() as $name) { + $value = $properties[$k = $name] ?? $properties[$k = "\0*\0$name"] ?? $properties[$k = "\0$class\0$name"] ?? $properties[$k = "\0$scope\0$name"] ?? $k = null; + + if (null === $k) { + trigger_error(\sprintf('serialize(): "%s" returned as member variable from __sleep() but does not exist', $name), \E_USER_NOTICE); + } else { + $data[$k] = $value; + } + } + + return $data; + } + + public function __unserialize(array $data): void + { + $class = self::class; + + if ($instance = $data["\0$class\0lazyObjectReal"] ?? null) { + unset($data["\0$class\0lazyObjectReal"]); + + foreach (Registry::$classResetters[$class] ??= Registry::getClassResetters($class) as $reset) { + $reset($this, $data); + } + + if ($data) { + PublicHydrator::hydrate($this, $data); + } + $this->lazyObjectState = new LazyObjectState(Registry::$noInitializerState ??= static fn () => throw new \LogicException('Lazy proxy has no initializer.')); + $this->lazyObjectState->realInstance = $instance; + } elseif ((Registry::$parentMethods[$class] ??= Registry::getParentMethods($class))['unserialize']) { + parent::__unserialize($data); + } else { + PublicHydrator::hydrate($this, $data); + + if (Registry::$parentMethods[$class]['wakeup']) { + parent::__wakeup(); + } + } + } + + public function __destruct() + { + if (isset($this->lazyObjectState)) { + return; + } + + if ((Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['destruct']) { + parent::__destruct(); + } + } +} diff --git a/vendor/symfony/var-exporter/ProxyHelper.php b/vendor/symfony/var-exporter/ProxyHelper.php new file mode 100644 index 0000000..e0cc84f --- /dev/null +++ b/vendor/symfony/var-exporter/ProxyHelper.php @@ -0,0 +1,412 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarExporter; + +use Symfony\Component\VarExporter\Exception\LogicException; +use Symfony\Component\VarExporter\Internal\Hydrator; +use Symfony\Component\VarExporter\Internal\LazyObjectRegistry; + +/** + * @author Nicolas Grekas + */ +final class ProxyHelper +{ + /** + * Helps generate lazy-loading ghost objects. + * + * @throws LogicException When the class is incompatible with ghost objects + */ + public static function generateLazyGhost(\ReflectionClass $class): string + { + if (\PHP_VERSION_ID < 80300 && $class->isReadOnly()) { + throw new LogicException(\sprintf('Cannot generate lazy ghost with PHP < 8.3: class "%s" is readonly.', $class->name)); + } + if ($class->isFinal()) { + throw new LogicException(\sprintf('Cannot generate lazy ghost: class "%s" is final.', $class->name)); + } + if ($class->isInterface() || $class->isAbstract()) { + throw new LogicException(\sprintf('Cannot generate lazy ghost: "%s" is not a concrete class.', $class->name)); + } + if (\stdClass::class !== $class->name && $class->isInternal()) { + throw new LogicException(\sprintf('Cannot generate lazy ghost: class "%s" is internal.', $class->name)); + } + if ($class->hasMethod('__get') && 'mixed' !== (self::exportType($class->getMethod('__get')) ?? 'mixed')) { + throw new LogicException(\sprintf('Cannot generate lazy ghost: return type of method "%s::__get()" should be "mixed".', $class->name)); + } + + static $traitMethods; + $traitMethods ??= (new \ReflectionClass(LazyGhostTrait::class))->getMethods(); + + foreach ($traitMethods as $method) { + if ($class->hasMethod($method->name) && $class->getMethod($method->name)->isFinal()) { + throw new LogicException(\sprintf('Cannot generate lazy ghost: method "%s::%s()" is final.', $class->name, $method->name)); + } + } + + $parent = $class; + while ($parent = $parent->getParentClass()) { + if (\stdClass::class !== $parent->name && $parent->isInternal()) { + throw new LogicException(\sprintf('Cannot generate lazy ghost: class "%s" extends "%s" which is internal.', $class->name, $parent->name)); + } + } + $propertyScopes = self::exportPropertyScopes($class->name); + + return <<name} implements \Symfony\Component\VarExporter\LazyObjectInterface + { + use \Symfony\Component\VarExporter\LazyGhostTrait; + + private const LAZY_OBJECT_PROPERTY_SCOPES = {$propertyScopes}; + } + + // Help opcache.preload discover always-needed symbols + class_exists(\Symfony\Component\VarExporter\Internal\Hydrator::class); + class_exists(\Symfony\Component\VarExporter\Internal\LazyObjectRegistry::class); + class_exists(\Symfony\Component\VarExporter\Internal\LazyObjectState::class); + + EOPHP; + } + + /** + * Helps generate lazy-loading virtual proxies. + * + * @param \ReflectionClass[] $interfaces + * + * @throws LogicException When the class is incompatible with virtual proxies + */ + public static function generateLazyProxy(?\ReflectionClass $class, array $interfaces = []): string + { + if (!class_exists($class?->name ?? \stdClass::class, false)) { + throw new LogicException(\sprintf('Cannot generate lazy proxy: "%s" is not a class.', $class->name)); + } + if ($class?->isFinal()) { + throw new LogicException(\sprintf('Cannot generate lazy proxy: class "%s" is final.', $class->name)); + } + if (\PHP_VERSION_ID < 80300 && $class?->isReadOnly()) { + throw new LogicException(\sprintf('Cannot generate lazy proxy with PHP < 8.3: class "%s" is readonly.', $class->name)); + } + + $methodReflectors = [$class?->getMethods(\ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PROTECTED) ?? []]; + foreach ($interfaces as $interface) { + if (!$interface->isInterface()) { + throw new LogicException(\sprintf('Cannot generate lazy proxy: "%s" is not an interface.', $interface->name)); + } + $methodReflectors[] = $interface->getMethods(); + } + $methodReflectors = array_merge(...$methodReflectors); + + $extendsInternalClass = false; + if ($parent = $class) { + do { + $extendsInternalClass = \stdClass::class !== $parent->name && $parent->isInternal(); + } while (!$extendsInternalClass && $parent = $parent->getParentClass()); + } + $methodsHaveToBeProxied = $extendsInternalClass; + $methods = []; + + foreach ($methodReflectors as $method) { + if ('__get' !== strtolower($method->name) || 'mixed' === ($type = self::exportType($method) ?? 'mixed')) { + continue; + } + $methodsHaveToBeProxied = true; + $trait = new \ReflectionMethod(LazyProxyTrait::class, '__get'); + $body = \array_slice(file($trait->getFileName()), $trait->getStartLine() - 1, $trait->getEndLine() - $trait->getStartLine()); + $body[0] = str_replace('): mixed', '): '.$type, $body[0]); + $methods['__get'] = strtr(implode('', $body).' }', [ + 'Hydrator' => '\\'.Hydrator::class, + 'Registry' => '\\'.LazyObjectRegistry::class, + ]); + break; + } + + foreach ($methodReflectors as $method) { + if (($method->isStatic() && !$method->isAbstract()) || isset($methods[$lcName = strtolower($method->name)])) { + continue; + } + if ($method->isFinal()) { + if ($extendsInternalClass || $methodsHaveToBeProxied || method_exists(LazyProxyTrait::class, $method->name)) { + throw new LogicException(\sprintf('Cannot generate lazy proxy: method "%s::%s()" is final.', $class->name, $method->name)); + } + continue; + } + if (method_exists(LazyProxyTrait::class, $method->name) || ($method->isProtected() && !$method->isAbstract())) { + continue; + } + + $signature = self::exportSignature($method, true, $args); + $parentCall = $method->isAbstract() ? "throw new \BadMethodCallException('Cannot forward abstract method \"{$method->class}::{$method->name}()\".')" : "parent::{$method->name}({$args})"; + + if ($method->isStatic()) { + $body = " $parentCall;"; + } elseif (str_ends_with($signature, '): never') || str_ends_with($signature, '): void')) { + $body = <<lazyObjectState)) { + (\$this->lazyObjectState->realInstance ??= (\$this->lazyObjectState->initializer)())->{$method->name}({$args}); + } else { + {$parentCall}; + } + EOPHP; + } else { + if (!$methodsHaveToBeProxied && !$method->isAbstract()) { + // Skip proxying methods that might return $this + foreach (preg_split('/[()|&]++/', self::exportType($method) ?? 'static') as $type) { + if (\in_array($type = ltrim($type, '?'), ['static', 'object'], true)) { + continue 2; + } + foreach ([$class, ...$interfaces] as $r) { + if ($r && is_a($r->name, $type, true)) { + continue 3; + } + } + } + } + + $body = <<lazyObjectState)) { + return (\$this->lazyObjectState->realInstance ??= (\$this->lazyObjectState->initializer)())->{$method->name}({$args}); + } + + return {$parentCall}; + EOPHP; + } + $methods[$lcName] = " {$signature}\n {\n{$body}\n }"; + } + + $types = $interfaces = array_unique(array_column($interfaces, 'name')); + $interfaces[] = LazyObjectInterface::class; + $interfaces = implode(', \\', $interfaces); + $parent = $class ? ' extends \\'.$class->name : ''; + array_unshift($types, $class ? 'parent' : ''); + $type = ltrim(implode('&\\', $types), '&'); + + if (!$class) { + $trait = new \ReflectionMethod(LazyProxyTrait::class, 'initializeLazyObject'); + $body = \array_slice(file($trait->getFileName()), $trait->getStartLine() - 1, $trait->getEndLine() - $trait->getStartLine()); + $body[0] = str_replace('): parent', '): '.$type, $body[0]); + $methods = ['initializeLazyObject' => implode('', $body).' }'] + $methods; + } + $body = $methods ? "\n".implode("\n\n", $methods)."\n" : ''; + $propertyScopes = $class ? self::exportPropertyScopes($class->name) : '[]'; + + if ( + $class?->hasMethod('__unserialize') + && !$class->getMethod('__unserialize')->getParameters()[0]->getType() + ) { + // fix contravariance type problem when $class declares a `__unserialize()` method without typehint. + $lazyProxyTraitStatement = <<__doUnserialize(\$data); + } + + EOPHP; + } else { + $lazyProxyTraitStatement = <<class : $function->getNamespaceName().'\\'; + $namespace = substr($namespace, 0, strrpos($namespace, '\\') ?: 0); + foreach ($function->getParameters() as $param) { + $parameters[] = ($param->getAttributes(\SensitiveParameter::class) ? '#[\SensitiveParameter] ' : '') + .($withParameterTypes && $param->hasType() ? self::exportType($param).' ' : '') + .($param->isPassedByReference() ? '&' : '') + .($param->isVariadic() ? '...' : '').'$'.$param->name + .($param->isOptional() && !$param->isVariadic() ? ' = '.self::exportDefault($param, $namespace) : ''); + if ($param->isPassedByReference()) { + $byRefIndex = 1 + $param->getPosition(); + } + $args .= ($param->isVariadic() ? '...$' : '$').$param->name.', '; + } + + if (!$param || !$byRefIndex) { + $args = '...\func_get_args()'; + } elseif ($param->isVariadic()) { + $args = substr($args, 0, -2); + } else { + $args = explode(', ', $args, 1 + $byRefIndex); + $args[$byRefIndex] = \sprintf('...\array_slice(\func_get_args(), %d)', $byRefIndex); + $args = implode(', ', $args); + } + + $signature = 'function '.($function->returnsReference() ? '&' : '') + .($function->isClosure() ? '' : $function->name).'('.implode(', ', $parameters).')'; + + if ($function instanceof \ReflectionMethod) { + $signature = ($function->isPublic() ? 'public ' : ($function->isProtected() ? 'protected ' : 'private ')) + .($function->isStatic() ? 'static ' : '').$signature; + } + if ($function->hasReturnType()) { + $signature .= ': '.self::exportType($function); + } + + static $getPrototype; + $getPrototype ??= (new \ReflectionMethod(\ReflectionMethod::class, 'getPrototype'))->invoke(...); + + while ($function) { + if ($function->hasTentativeReturnType()) { + return '#[\ReturnTypeWillChange] '.$signature; + } + + try { + $function = $function instanceof \ReflectionMethod && $function->isAbstract() ? false : $getPrototype($function); + } catch (\ReflectionException) { + break; + } + } + + return $signature; + } + + public static function exportType(\ReflectionFunctionAbstract|\ReflectionProperty|\ReflectionParameter $owner, bool $noBuiltin = false, ?\ReflectionType $type = null): ?string + { + if (!$type ??= $owner instanceof \ReflectionFunctionAbstract ? $owner->getReturnType() : $owner->getType()) { + return null; + } + $class = null; + $types = []; + if ($type instanceof \ReflectionUnionType) { + $reflectionTypes = $type->getTypes(); + $glue = '|'; + } elseif ($type instanceof \ReflectionIntersectionType) { + $reflectionTypes = $type->getTypes(); + $glue = '&'; + } else { + $reflectionTypes = [$type]; + $glue = null; + } + + foreach ($reflectionTypes as $type) { + if ($type instanceof \ReflectionIntersectionType) { + if ('' !== $name = '('.self::exportType($owner, $noBuiltin, $type).')') { + $types[] = $name; + } + continue; + } + $name = $type->getName(); + + if ($noBuiltin && $type->isBuiltin()) { + continue; + } + if (\in_array($name, ['parent', 'self'], true) && $class ??= $owner->getDeclaringClass()) { + $name = 'parent' === $name ? ($class->getParentClass() ?: null)?->name ?? 'parent' : $class->name; + } + + $types[] = ($noBuiltin || $type->isBuiltin() || 'static' === $name ? '' : '\\').$name; + } + + if (!$types) { + return ''; + } + if (null === $glue) { + return (!$noBuiltin && $type->allowsNull() && !\in_array($name, ['mixed', 'null'], true) ? '?' : '').$types[0]; + } + sort($types); + + return implode($glue, $types); + } + + private static function exportPropertyScopes(string $parent): string + { + $propertyScopes = Hydrator::$propertyScopes[$parent] ??= Hydrator::getPropertyScopes($parent); + uksort($propertyScopes, 'strnatcmp'); + foreach ($propertyScopes as $k => $v) { + unset($propertyScopes[$k][3]); + } + $propertyScopes = VarExporter::export($propertyScopes); + $propertyScopes = str_replace(VarExporter::export($parent), 'parent::class', $propertyScopes); + $propertyScopes = preg_replace("/(?|(,)\n( ) |\n |,\n (\]))/", '$1$2', $propertyScopes); + + return str_replace("\n", "\n ", $propertyScopes); + } + + private static function exportDefault(\ReflectionParameter $param, $namespace): string + { + $default = rtrim(substr(explode('$'.$param->name.' = ', (string) $param, 2)[1] ?? '', 0, -2)); + + if (\in_array($default, ['', 'NULL'], true)) { + return 'null'; + } + if (str_ends_with($default, "...'") && preg_match("/^'(?:[^'\\\\]*+(?:\\\\.)*+)*+'$/", $default)) { + return VarExporter::export($param->getDefaultValue()); + } + + $regexp = "/(\"(?:[^\"\\\\]*+(?:\\\\.)*+)*+\"|'(?:[^'\\\\]*+(?:\\\\.)*+)*+')/"; + $parts = preg_split($regexp, $default, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY); + + $regexp = '/([\[\( ]|^)([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:\\\\[a-zA-Z0-9_\x7f-\xff]++)*+)(\(?)(?!: )/'; + $callback = (false !== strpbrk($default, "\\:('") && $class = $param->getDeclaringClass()) + ? fn ($m) => $m[1].match ($m[2]) { + 'new', 'false', 'true', 'null' => $m[2], + 'NULL' => 'null', + 'self' => '\\'.$class->name, + 'namespace\\parent', + 'parent' => ($parent = $class->getParentClass()) ? '\\'.$parent->name : 'parent', + default => self::exportSymbol($m[2], '(' !== $m[3], $namespace), + }.$m[3] + : fn ($m) => $m[1].match ($m[2]) { + 'new', 'false', 'true', 'null', 'self', 'parent' => $m[2], + 'NULL' => 'null', + default => self::exportSymbol($m[2], '(' !== $m[3], $namespace), + }.$m[3]; + + return implode('', array_map(fn ($part) => match ($part[0]) { + '"' => $part, // for internal classes only + "'" => false !== strpbrk($part, "\\\0\r\n") ? '"'.substr(str_replace(['$', "\0", "\r", "\n"], ['\$', '\0', '\r', '\n'], $part), 1, -1).'"' : $part, + default => preg_replace_callback($regexp, $callback, $part), + }, $parts)); + } + + private static function exportSymbol(string $symbol, bool $mightBeRootConst, string $namespace): string + { + if (!$mightBeRootConst + || false === ($ns = strrpos($symbol, '\\')) + || substr($symbol, 0, $ns) !== $namespace + || \defined($symbol) + || !\defined(substr($symbol, $ns + 1)) + ) { + return '\\'.$symbol; + } + + return '\\'.substr($symbol, $ns + 1); + } +} diff --git a/vendor/symfony/var-exporter/README.md b/vendor/symfony/var-exporter/README.md new file mode 100644 index 0000000..7195270 --- /dev/null +++ b/vendor/symfony/var-exporter/README.md @@ -0,0 +1,137 @@ +VarExporter Component +===================== + +The VarExporter component provides various tools to deal with the internal state +of objects: + +- `VarExporter::export()` allows exporting any serializable PHP data structure to + plain PHP code. While doing so, it preserves all the semantics associated with + the serialization mechanism of PHP (`__wakeup`, `__sleep`, `Serializable`, + `__serialize`, `__unserialize`); +- `Instantiator::instantiate()` creates an object and sets its properties without + calling its constructor nor any other methods; +- `Hydrator::hydrate()` can set the properties of an existing object; +- `Lazy*Trait` can make a class behave as a lazy-loading ghost or virtual proxy. + +VarExporter::export() +--------------------- + +The reason to use `VarExporter::export()` *vs* `serialize()` or +[igbinary](https://github.com/igbinary/igbinary) is performance: thanks to +OPcache, the resulting code is significantly faster and more memory efficient +than using `unserialize()` or `igbinary_unserialize()`. + +Unlike `var_export()`, this works on any serializable PHP value. + +It also provides a few improvements over `var_export()`/`serialize()`: + + * the output is PSR-2 compatible; + * the output can be re-indented without messing up with `\r` or `\n` in the data; + * missing classes throw a `ClassNotFoundException` instead of being unserialized + to `PHP_Incomplete_Class` objects; + * references involving `SplObjectStorage`, `ArrayObject` or `ArrayIterator` + instances are preserved; + * `Reflection*`, `IteratorIterator` and `RecursiveIteratorIterator` classes + throw an exception when being serialized (their unserialized version is broken + anyway, see https://bugs.php.net/76737). + +Instantiator and Hydrator +------------------------- + +`Instantiator::instantiate($class)` creates an object of the given class without +calling its constructor nor any other methods. + +`Hydrator::hydrate()` sets the properties of an existing object, including +private and protected ones. For example: + +```php +// Sets the public or protected $object->propertyName property +Hydrator::hydrate($object, ['propertyName' => $propertyValue]); + +// Sets a private property defined on its parent Bar class: +Hydrator::hydrate($object, ["\0Bar\0privateBarProperty" => $propertyValue]); + +// Alternative way to set the private $object->privateBarProperty property +Hydrator::hydrate($object, [], [ + Bar::class => ['privateBarProperty' => $propertyValue], +]); +``` + +`Lazy*Trait` +------------ + +The component provides two lazy-loading patterns: ghost objects and virtual +proxies (see https://martinfowler.com/eaaCatalog/lazyLoad.html for reference). + +Ghost objects work only with concrete and non-internal classes. In the generic +case, they are not compatible with using factories in their initializer. + +Virtual proxies work with concrete, abstract or internal classes. They provide an +API that looks like the actual objects and forward calls to them. They can cause +identity problems because proxies might not be seen as equivalents to the actual +objects they proxy. + +Because of this identity problem, ghost objects should be preferred when +possible. Exceptions thrown by the `ProxyHelper` class can help decide when it +can be used or not. + +Ghost objects and virtual proxies both provide implementations for the +`LazyObjectInterface` which allows resetting them to their initial state or to +forcibly initialize them when needed. Note that resetting a ghost object skips +its read-only properties. You should use a virtual proxy to reset read-only +properties. + +### `LazyGhostTrait` + +By using `LazyGhostTrait` either directly in your classes or by using +`ProxyHelper::generateLazyGhost()`, you can make their instances lazy-loadable. +This works by creating these instances empty and by computing their state only +when accessing a property. + +```php +class FooLazyGhost extends Foo +{ + use LazyGhostTrait; +} + +$foo = FooLazyGhost::createLazyGhost(initializer: function (Foo $instance): void { + // [...] Use whatever heavy logic you need here + // to compute the $dependencies of the $instance + $instance->__construct(...$dependencies); + // [...] Call setters, etc. if needed +}); + +// $foo is now a lazy-loading ghost object. The initializer will +// be called only when and if a *property* is accessed. +``` + +### `LazyProxyTrait` + +Alternatively, `LazyProxyTrait` can be used to create virtual proxies: + +```php +$proxyCode = ProxyHelper::generateLazyProxy(new ReflectionClass(Foo::class)); +// $proxyCode contains the reference to LazyProxyTrait +// and should be dumped into a file in production envs +eval('class FooLazyProxy'.$proxyCode); + +$foo = FooLazyProxy::createLazyProxy(initializer: function (): Foo { + // [...] Use whatever heavy logic you need here + // to compute the $dependencies of the $instance + $instance = new Foo(...$dependencies); + // [...] Call setters, etc. if needed + + return $instance; +}); +// $foo is now a lazy-loading virtual proxy object. The initializer will +// be called only when and if a *method* is called. +``` + +Resources +--------- + + * [Documentation](https://symfony.com/doc/current/components/var_exporter.html) + * [Contributing](https://symfony.com/doc/current/contributing/index.html) + * [Report issues](https://github.com/symfony/symfony/issues) and + [send Pull Requests](https://github.com/symfony/symfony/pulls) + in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/vendor/symfony/var-exporter/VarExporter.php b/vendor/symfony/var-exporter/VarExporter.php new file mode 100644 index 0000000..606a9fd --- /dev/null +++ b/vendor/symfony/var-exporter/VarExporter.php @@ -0,0 +1,114 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarExporter; + +use Symfony\Component\VarExporter\Exception\ExceptionInterface; +use Symfony\Component\VarExporter\Internal\Exporter; +use Symfony\Component\VarExporter\Internal\Hydrator; +use Symfony\Component\VarExporter\Internal\Registry; +use Symfony\Component\VarExporter\Internal\Values; + +/** + * Exports serializable PHP values to PHP code. + * + * VarExporter allows serializing PHP data structures to plain PHP code (like var_export()) + * while preserving all the semantics associated with serialize() (unlike var_export()). + * + * By leveraging OPcache, the generated PHP code is faster than doing the same with unserialize(). + * + * @author Nicolas Grekas + */ +final class VarExporter +{ + /** + * Exports a serializable PHP value to PHP code. + * + * @param bool &$isStaticValue Set to true after execution if the provided value is static, false otherwise + * @param array &$foundClasses Classes found in the value are added to this list as both keys and values + * + * @throws ExceptionInterface When the provided value cannot be serialized + */ + public static function export(mixed $value, ?bool &$isStaticValue = null, array &$foundClasses = []): string + { + $isStaticValue = true; + + if (!\is_object($value) && !(\is_array($value) && $value) && !\is_resource($value) || $value instanceof \UnitEnum) { + return Exporter::export($value); + } + + $objectsPool = new \SplObjectStorage(); + $refsPool = []; + $objectsCount = 0; + + try { + $value = Exporter::prepare([$value], $objectsPool, $refsPool, $objectsCount, $isStaticValue)[0]; + } finally { + $references = []; + foreach ($refsPool as $i => $v) { + if ($v[0]->count) { + $references[1 + $i] = $v[2]; + } + $v[0] = $v[1]; + } + } + + if ($isStaticValue) { + return Exporter::export($value); + } + + $classes = []; + $values = []; + $states = []; + foreach ($objectsPool as $i => $v) { + [, $class, $values[], $wakeup] = $objectsPool[$v]; + $foundClasses[$class] = $classes[] = $class; + + if (0 < $wakeup) { + $states[$wakeup] = $i; + } elseif (0 > $wakeup) { + $states[-$wakeup] = [$i, array_pop($values)]; + $values[] = []; + } + } + ksort($states); + + $wakeups = [null]; + foreach ($states as $v) { + if (\is_array($v)) { + $wakeups[-$v[0]] = $v[1]; + } else { + $wakeups[] = $v; + } + } + + if (null === $wakeups[0]) { + unset($wakeups[0]); + } + + $properties = []; + foreach ($values as $i => $vars) { + foreach ($vars as $class => $values) { + foreach ($values as $name => $v) { + $properties[$class][$name][$i] = $v; + } + } + } + + if ($classes || $references) { + $value = new Hydrator(new Registry($classes), $references ? new Values($references) : null, $properties, $value, $wakeups); + } else { + $isStaticValue = true; + } + + return Exporter::export($value); + } +} diff --git a/vendor/symfony/var-exporter/composer.json b/vendor/symfony/var-exporter/composer.json new file mode 100644 index 0000000..f3a227e --- /dev/null +++ b/vendor/symfony/var-exporter/composer.json @@ -0,0 +1,33 @@ +{ + "name": "symfony/var-exporter", + "type": "library", + "description": "Allows exporting any serializable PHP data structure to plain PHP code", + "keywords": ["export", "serialize", "instantiate", "hydrate", "construct", "clone", "lazy-loading", "proxy"], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": ">=8.2" + }, + "require-dev": { + "symfony/property-access": "^6.4|^7.0", + "symfony/serializer": "^6.4|^7.0", + "symfony/var-dumper": "^6.4|^7.0" + }, + "autoload": { + "psr-4": { "Symfony\\Component\\VarExporter\\": "" }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "minimum-stability": "dev" +}