diff --git a/advancedcontentfilter/composer.lock b/advancedcontentfilter/composer.lock index 83d61074..6dbd17ba 100644 --- a/advancedcontentfilter/composer.lock +++ b/advancedcontentfilter/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "3e87f0369e4799fc35d98f399c67f1e9", + "content-hash": "a7276eb2d2108a26699f69c750d02d27", "packages": [ { "name": "nikic/fast-route", @@ -100,27 +100,22 @@ }, { "name": "psr/container", - "version": "2.0.2", + "version": "1.1.2", "source": { "type": "git", "url": "https://github.com/php-fig/container.git", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" + "reference": "513e0666f7216c7459170d56df27dfcefe1689ea" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea", + "reference": "513e0666f7216c7459170d56df27dfcefe1689ea", "shasum": "" }, "require": { "php": ">=7.4.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, "autoload": { "psr-4": { "Psr\\Container\\": "src/" @@ -145,7 +140,7 @@ "container-interop", "psr" ], - "time": "2021-11-05T16:47:00+00:00" + "time": "2021-11-05T16:50:12+00:00" }, { "name": "psr/http-factory", @@ -201,16 +196,16 @@ }, { "name": "psr/http-message", - "version": "1.1", + "version": "2.0", "source": { "type": "git", "url": "https://github.com/php-fig/http-message.git", - "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba" + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/cb6ce4845ce34a8ad9e68117c10ee90a29919eba", - "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", "shasum": "" }, "require": { @@ -219,7 +214,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { @@ -234,7 +229,7 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "homepage": "https://www.php-fig.org/" } ], "description": "Common interface for HTTP messages", @@ -247,7 +242,7 @@ "request", "response" ], - "time": "2023-04-04T09:50:52+00:00" + "time": "2023-04-04T09:54:51+00:00" }, { "name": "psr/http-server-handler", @@ -402,66 +397,18 @@ ], "time": "2021-05-03T11:20:27+00:00" }, - { - "name": "psr/simple-cache", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/php-fig/simple-cache.git", - "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", - "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\SimpleCache\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Common interfaces for simple caching", - "keywords": [ - "cache", - "caching", - "psr", - "psr-16", - "simple-cache" - ], - "time": "2017-10-23T01:57:42+00:00" - }, { "name": "slim/slim", - "version": "4.12.0", + "version": "4.13.0", "source": { "type": "git", "url": "https://github.com/slimphp/Slim.git", - "reference": "e9e99c2b24398b967841c6c4c3048622cc7e2b18" + "reference": "038fd5713d5a41636fdff0e8dcceedecdd17fc17" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/slimphp/Slim/zipball/e9e99c2b24398b967841c6c4c3048622cc7e2b18", - "reference": "e9e99c2b24398b967841c6c4c3048622cc7e2b18", + "url": "https://api.github.com/repos/slimphp/Slim/zipball/038fd5713d5a41636fdff0e8dcceedecdd17fc17", + "reference": "038fd5713d5a41636fdff0e8dcceedecdd17fc17", "shasum": "" }, "require": { @@ -470,7 +417,7 @@ "php": "^7.4 || ^8.0", "psr/container": "^1.0 || ^2.0", "psr/http-factory": "^1.0", - "psr/http-message": "^1.1", + "psr/http-message": "^1.1 || ^2.0", "psr/http-server-handler": "^1.0", "psr/http-server-middleware": "^1.0", "psr/log": "^1.1 || ^2.0 || ^3.0" @@ -478,19 +425,19 @@ "require-dev": { "adriansuter/php-autoload-override": "^1.4", "ext-simplexml": "*", - "guzzlehttp/psr7": "^2.5", + "guzzlehttp/psr7": "^2.6", "httpsoft/http-message": "^1.1", "httpsoft/http-server-request": "^1.1", - "laminas/laminas-diactoros": "^2.17", + "laminas/laminas-diactoros": "^2.17 || ^3", "nyholm/psr7": "^1.8", - "nyholm/psr7-server": "^1.0", - "phpspec/prophecy": "^1.17", - "phpspec/prophecy-phpunit": "^2.0", + "nyholm/psr7-server": "^1.1", + "phpspec/prophecy": "^1.19", + "phpspec/prophecy-phpunit": "^2.1", "phpstan/phpstan": "^1.10", "phpunit/phpunit": "^9.6", "slim/http": "^1.3", "slim/psr7": "^1.6", - "squizlabs/php_codesniffer": "^3.7" + "squizlabs/php_codesniffer": "^3.9" }, "suggest": { "ext-simplexml": "Needed to support XML format in BodyParsingMiddleware", @@ -553,41 +500,54 @@ "type": "tidelift" } ], - "time": "2023-07-23T04:54:29+00:00" + "time": "2024-03-03T21:25:30+00:00" }, { "name": "symfony/cache", - "version": "v3.4.47", + "version": "v4.4.48", "source": { "type": "git", "url": "https://github.com/symfony/cache.git", - "reference": "a7a14c4832760bd1fbd31be2859ffedc9b6ff813" + "reference": "3b98ed664887ad197b8ede3da2432787212eb915" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/a7a14c4832760bd1fbd31be2859ffedc9b6ff813", - "reference": "a7a14c4832760bd1fbd31be2859ffedc9b6ff813", + "url": "https://api.github.com/repos/symfony/cache/zipball/3b98ed664887ad197b8ede3da2432787212eb915", + "reference": "3b98ed664887ad197b8ede3da2432787212eb915", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8", - "psr/cache": "~1.0", - "psr/log": "~1.0", - "psr/simple-cache": "^1.0", - "symfony/polyfill-apcu": "~1.1" + "php": ">=7.1.3", + "psr/cache": "^1.0|^2.0", + "psr/log": "^1|^2|^3", + "symfony/cache-contracts": "^1.1.7|^2", + "symfony/polyfill-php73": "^1.9", + "symfony/polyfill-php80": "^1.16", + "symfony/service-contracts": "^1.1|^2", + "symfony/var-exporter": "^4.2|^5.0" }, "conflict": { - "symfony/var-dumper": "<3.3" + "doctrine/dbal": "<2.7", + "symfony/dependency-injection": "<3.4", + "symfony/http-kernel": "<4.4|>=5.0", + "symfony/var-dumper": "<4.4" }, "provide": { - "psr/cache-implementation": "1.0", - "psr/simple-cache-implementation": "1.0" + "psr/cache-implementation": "1.0|2.0", + "psr/simple-cache-implementation": "1.0|2.0", + "symfony/cache-implementation": "1.0|2.0" }, "require-dev": { "cache/integration-tests": "dev-master", - "doctrine/cache": "^1.6", - "doctrine/dbal": "^2.4|^3.0", - "predis/predis": "^1.0" + "doctrine/cache": "^1.6|^2.0", + "doctrine/dbal": "^2.7|^3.0", + "predis/predis": "^1.1", + "psr/simple-cache": "^1.0|^2.0", + "symfony/config": "^4.2|^5.0", + "symfony/dependency-injection": "^3.4|^4.1|^5.0", + "symfony/filesystem": "^4.4|^5.0", + "symfony/http-kernel": "^4.4", + "symfony/var-dumper": "^4.4|^5.0" }, "type": "library", "autoload": { @@ -612,7 +572,7 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony Cache component with PSR-6, PSR-16, and tags", + "description": "Provides extended PSR-6, PSR-16 (and tags) implementations", "homepage": "https://symfony.com", "keywords": [ "caching", @@ -632,7 +592,147 @@ "type": "tidelift" } ], - "time": "2020-10-24T10:57:07+00:00" + "time": "2022-10-17T20:21:54+00:00" + }, + { + "name": "symfony/cache-contracts", + "version": "v2.5.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/cache-contracts.git", + "reference": "64be4a7acb83b6f2bf6de9a02cee6dad41277ebc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/64be4a7acb83b6f2bf6de9a02cee6dad41277ebc", + "reference": "64be4a7acb83b6f2bf6de9a02cee6dad41277ebc", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "psr/cache": "^1.0|^2.0|^3.0" + }, + "suggest": { + "symfony/cache-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.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" + ], + "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": "2022-01-02T09:53:40+00:00" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v2.5.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/e8b495ea28c1d97b5e0c121748d6f9b53d075c66", + "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.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", + "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": "2022-01-02T09:53:40+00:00" }, { "name": "symfony/expression-language", @@ -694,80 +794,6 @@ ], "time": "2020-10-24T10:57:07+00:00" }, - { - "name": "symfony/polyfill-apcu", - "version": "v1.28.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-apcu.git", - "reference": "c6c2c0f5f4cb0b100c5dfea807ef5cd27bbe9899" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-apcu/zipball/c6c2c0f5f4cb0b100c5dfea807ef5cd27bbe9899", - "reference": "c6c2c0f5f4cb0b100c5dfea807ef5cd27bbe9899", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Apcu\\": "" - } - }, - "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": "Symfony polyfill backporting apcu_* functions to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "apcu", - "compatibility", - "polyfill", - "portable", - "shim" - ], - "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": "2023-01-26T09:26:14+00:00" - }, { "name": "symfony/polyfill-php70", "version": "v1.20.0", @@ -832,6 +858,306 @@ } ], "time": "2020-10-23T14:02:19+00:00" + }, + { + "name": "symfony/polyfill-php73", + "version": "v1.29.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php73.git", + "reference": "21bd091060673a1177ae842c0ef8fe30893114d2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/21bd091060673a1177ae842c0ef8fe30893114d2", + "reference": "21bd091060673a1177ae842c0ef8fe30893114d2", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php73\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "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": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "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-01-29T20:11:03+00:00" + }, + { + "name": "symfony/polyfill-php80", + "version": "v1.29.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/87b68208d5c1188808dd7839ee1e6c8ec3b02f1b", + "reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php80\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "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-01-29T20:11:03+00:00" + }, + { + "name": "symfony/service-contracts", + "version": "v2.5.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/4b426aac47d6427cc1a1d0f7e2ac724627f5966c", + "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "psr/container": "^1.1", + "symfony/deprecation-contracts": "^2.1|^3" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "suggest": { + "symfony/service-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + } + }, + "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" + ], + "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": "2022-05-30T19:17:29+00:00" + }, + { + "name": "symfony/var-exporter", + "version": "v5.4.35", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-exporter.git", + "reference": "abb0a151b62d6b07e816487e20040464af96cae7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/abb0a151b62d6b07e816487e20040464af96cae7", + "reference": "abb0a151b62d6b07e816487e20040464af96cae7", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/polyfill-php80": "^1.16" + }, + "require-dev": { + "symfony/var-dumper": "^4.4.9|^5.0.9|^6.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", + "serialize" + ], + "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-01-23T13:51:25+00:00" } ], "packages-dev": [], @@ -840,9 +1166,10 @@ "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, - "platform": { - "php": ">=5.6.0" - }, + "platform": [], "platform-dev": [], + "platform-overrides": { + "php": "7.4" + }, "plugin-api-version": "1.1.0" } diff --git a/advancedcontentfilter/vendor/composer/autoload_classmap.php b/advancedcontentfilter/vendor/composer/autoload_classmap.php index aa3de8a3..9f79be5c 100644 --- a/advancedcontentfilter/vendor/composer/autoload_classmap.php +++ b/advancedcontentfilter/vendor/composer/autoload_classmap.php @@ -6,6 +6,7 @@ $vendorDir = dirname(dirname(__FILE__)); $baseDir = dirname($vendorDir); return array( + 'Attribute' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Attribute.php', 'FastRoute\\BadRouteException' => $vendorDir . '/nikic/fast-route/src/BadRouteException.php', 'FastRoute\\DataGenerator' => $vendorDir . '/nikic/fast-route/src/DataGenerator.php', 'FastRoute\\DataGenerator\\CharCountBased' => $vendorDir . '/nikic/fast-route/src/DataGenerator/CharCountBased.php', @@ -23,6 +24,8 @@ return array( 'FastRoute\\RouteCollector' => $vendorDir . '/nikic/fast-route/src/RouteCollector.php', 'FastRoute\\RouteParser' => $vendorDir . '/nikic/fast-route/src/RouteParser.php', 'FastRoute\\RouteParser\\Std' => $vendorDir . '/nikic/fast-route/src/RouteParser/Std.php', + 'JsonException' => $vendorDir . '/symfony/polyfill-php73/Resources/stubs/JsonException.php', + 'PhpToken' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php', 'Psr\\Cache\\CacheException' => $vendorDir . '/psr/cache/src/CacheException.php', 'Psr\\Cache\\CacheItemInterface' => $vendorDir . '/psr/cache/src/CacheItemInterface.php', 'Psr\\Cache\\CacheItemPoolInterface' => $vendorDir . '/psr/cache/src/CacheItemPoolInterface.php', @@ -56,9 +59,6 @@ return array( 'Psr\\Log\\Test\\DummyTest' => $vendorDir . '/psr/log/Psr/Log/Test/DummyTest.php', 'Psr\\Log\\Test\\LoggerInterfaceTest' => $vendorDir . '/psr/log/Psr/Log/Test/LoggerInterfaceTest.php', 'Psr\\Log\\Test\\TestLogger' => $vendorDir . '/psr/log/Psr/Log/Test/TestLogger.php', - 'Psr\\SimpleCache\\CacheException' => $vendorDir . '/psr/simple-cache/src/CacheException.php', - 'Psr\\SimpleCache\\CacheInterface' => $vendorDir . '/psr/simple-cache/src/CacheInterface.php', - 'Psr\\SimpleCache\\InvalidArgumentException' => $vendorDir . '/psr/simple-cache/src/InvalidArgumentException.php', 'Slim\\App' => $vendorDir . '/slim/slim/Slim/App.php', 'Slim\\CallableResolver' => $vendorDir . '/slim/slim/Slim/CallableResolver.php', 'Slim\\Error\\AbstractErrorRenderer' => $vendorDir . '/slim/slim/Slim/Error/AbstractErrorRenderer.php', @@ -75,6 +75,7 @@ return array( 'Slim\\Exception\\HttpNotFoundException' => $vendorDir . '/slim/slim/Slim/Exception/HttpNotFoundException.php', 'Slim\\Exception\\HttpNotImplementedException' => $vendorDir . '/slim/slim/Slim/Exception/HttpNotImplementedException.php', 'Slim\\Exception\\HttpSpecializedException' => $vendorDir . '/slim/slim/Slim/Exception/HttpSpecializedException.php', + 'Slim\\Exception\\HttpTooManyRequestsException' => $vendorDir . '/slim/slim/Slim/Exception/HttpTooManyRequestsException.php', 'Slim\\Exception\\HttpUnauthorizedException' => $vendorDir . '/slim/slim/Slim/Exception/HttpUnauthorizedException.php', 'Slim\\Factory\\AppFactory' => $vendorDir . '/slim/slim/Slim/Factory/AppFactory.php', 'Slim\\Factory\\Psr17\\GuzzlePsr17Factory' => $vendorDir . '/slim/slim/Slim/Factory/Psr17/GuzzlePsr17Factory.php', @@ -130,20 +131,25 @@ return array( 'Slim\\Routing\\RouteResolver' => $vendorDir . '/slim/slim/Slim/Routing/RouteResolver.php', 'Slim\\Routing\\RouteRunner' => $vendorDir . '/slim/slim/Slim/Routing/RouteRunner.php', 'Slim\\Routing\\RoutingResults' => $vendorDir . '/slim/slim/Slim/Routing/RoutingResults.php', + 'Stringable' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Stringable.php', 'Symfony\\Component\\Cache\\Adapter\\AbstractAdapter' => $vendorDir . '/symfony/cache/Adapter/AbstractAdapter.php', + 'Symfony\\Component\\Cache\\Adapter\\AbstractTagAwareAdapter' => $vendorDir . '/symfony/cache/Adapter/AbstractTagAwareAdapter.php', 'Symfony\\Component\\Cache\\Adapter\\AdapterInterface' => $vendorDir . '/symfony/cache/Adapter/AdapterInterface.php', 'Symfony\\Component\\Cache\\Adapter\\ApcuAdapter' => $vendorDir . '/symfony/cache/Adapter/ApcuAdapter.php', 'Symfony\\Component\\Cache\\Adapter\\ArrayAdapter' => $vendorDir . '/symfony/cache/Adapter/ArrayAdapter.php', 'Symfony\\Component\\Cache\\Adapter\\ChainAdapter' => $vendorDir . '/symfony/cache/Adapter/ChainAdapter.php', 'Symfony\\Component\\Cache\\Adapter\\DoctrineAdapter' => $vendorDir . '/symfony/cache/Adapter/DoctrineAdapter.php', 'Symfony\\Component\\Cache\\Adapter\\FilesystemAdapter' => $vendorDir . '/symfony/cache/Adapter/FilesystemAdapter.php', + 'Symfony\\Component\\Cache\\Adapter\\FilesystemTagAwareAdapter' => $vendorDir . '/symfony/cache/Adapter/FilesystemTagAwareAdapter.php', 'Symfony\\Component\\Cache\\Adapter\\MemcachedAdapter' => $vendorDir . '/symfony/cache/Adapter/MemcachedAdapter.php', 'Symfony\\Component\\Cache\\Adapter\\NullAdapter' => $vendorDir . '/symfony/cache/Adapter/NullAdapter.php', 'Symfony\\Component\\Cache\\Adapter\\PdoAdapter' => $vendorDir . '/symfony/cache/Adapter/PdoAdapter.php', 'Symfony\\Component\\Cache\\Adapter\\PhpArrayAdapter' => $vendorDir . '/symfony/cache/Adapter/PhpArrayAdapter.php', 'Symfony\\Component\\Cache\\Adapter\\PhpFilesAdapter' => $vendorDir . '/symfony/cache/Adapter/PhpFilesAdapter.php', 'Symfony\\Component\\Cache\\Adapter\\ProxyAdapter' => $vendorDir . '/symfony/cache/Adapter/ProxyAdapter.php', + 'Symfony\\Component\\Cache\\Adapter\\Psr16Adapter' => $vendorDir . '/symfony/cache/Adapter/Psr16Adapter.php', 'Symfony\\Component\\Cache\\Adapter\\RedisAdapter' => $vendorDir . '/symfony/cache/Adapter/RedisAdapter.php', + 'Symfony\\Component\\Cache\\Adapter\\RedisTagAwareAdapter' => $vendorDir . '/symfony/cache/Adapter/RedisTagAwareAdapter.php', 'Symfony\\Component\\Cache\\Adapter\\SimpleCacheAdapter' => $vendorDir . '/symfony/cache/Adapter/SimpleCacheAdapter.php', 'Symfony\\Component\\Cache\\Adapter\\TagAwareAdapter' => $vendorDir . '/symfony/cache/Adapter/TagAwareAdapter.php', 'Symfony\\Component\\Cache\\Adapter\\TagAwareAdapterInterface' => $vendorDir . '/symfony/cache/Adapter/TagAwareAdapterInterface.php', @@ -152,10 +158,21 @@ return array( 'Symfony\\Component\\Cache\\Adapter\\TraceableTagAwareAdapter' => $vendorDir . '/symfony/cache/Adapter/TraceableTagAwareAdapter.php', 'Symfony\\Component\\Cache\\CacheItem' => $vendorDir . '/symfony/cache/CacheItem.php', 'Symfony\\Component\\Cache\\DataCollector\\CacheDataCollector' => $vendorDir . '/symfony/cache/DataCollector/CacheDataCollector.php', + 'Symfony\\Component\\Cache\\DependencyInjection\\CacheCollectorPass' => $vendorDir . '/symfony/cache/DependencyInjection/CacheCollectorPass.php', + 'Symfony\\Component\\Cache\\DependencyInjection\\CachePoolClearerPass' => $vendorDir . '/symfony/cache/DependencyInjection/CachePoolClearerPass.php', + 'Symfony\\Component\\Cache\\DependencyInjection\\CachePoolPass' => $vendorDir . '/symfony/cache/DependencyInjection/CachePoolPass.php', + 'Symfony\\Component\\Cache\\DependencyInjection\\CachePoolPrunerPass' => $vendorDir . '/symfony/cache/DependencyInjection/CachePoolPrunerPass.php', 'Symfony\\Component\\Cache\\DoctrineProvider' => $vendorDir . '/symfony/cache/DoctrineProvider.php', 'Symfony\\Component\\Cache\\Exception\\CacheException' => $vendorDir . '/symfony/cache/Exception/CacheException.php', 'Symfony\\Component\\Cache\\Exception\\InvalidArgumentException' => $vendorDir . '/symfony/cache/Exception/InvalidArgumentException.php', + 'Symfony\\Component\\Cache\\Exception\\LogicException' => $vendorDir . '/symfony/cache/Exception/LogicException.php', + 'Symfony\\Component\\Cache\\LockRegistry' => $vendorDir . '/symfony/cache/LockRegistry.php', + 'Symfony\\Component\\Cache\\Marshaller\\DefaultMarshaller' => $vendorDir . '/symfony/cache/Marshaller/DefaultMarshaller.php', + 'Symfony\\Component\\Cache\\Marshaller\\DeflateMarshaller' => $vendorDir . '/symfony/cache/Marshaller/DeflateMarshaller.php', + 'Symfony\\Component\\Cache\\Marshaller\\MarshallerInterface' => $vendorDir . '/symfony/cache/Marshaller/MarshallerInterface.php', + 'Symfony\\Component\\Cache\\Marshaller\\TagAwareMarshaller' => $vendorDir . '/symfony/cache/Marshaller/TagAwareMarshaller.php', 'Symfony\\Component\\Cache\\PruneableInterface' => $vendorDir . '/symfony/cache/PruneableInterface.php', + 'Symfony\\Component\\Cache\\Psr16Cache' => $vendorDir . '/symfony/cache/Psr16Cache.php', 'Symfony\\Component\\Cache\\ResettableInterface' => $vendorDir . '/symfony/cache/ResettableInterface.php', 'Symfony\\Component\\Cache\\Simple\\AbstractCache' => $vendorDir . '/symfony/cache/Simple/AbstractCache.php', 'Symfony\\Component\\Cache\\Simple\\ApcuCache' => $vendorDir . '/symfony/cache/Simple/ApcuCache.php', @@ -172,17 +189,22 @@ return array( 'Symfony\\Component\\Cache\\Simple\\RedisCache' => $vendorDir . '/symfony/cache/Simple/RedisCache.php', 'Symfony\\Component\\Cache\\Simple\\TraceableCache' => $vendorDir . '/symfony/cache/Simple/TraceableCache.php', 'Symfony\\Component\\Cache\\Simple\\TraceableCacheEvent' => $vendorDir . '/symfony/cache/Simple/TraceableCache.php', + 'Symfony\\Component\\Cache\\Traits\\AbstractAdapterTrait' => $vendorDir . '/symfony/cache/Traits/AbstractAdapterTrait.php', 'Symfony\\Component\\Cache\\Traits\\AbstractTrait' => $vendorDir . '/symfony/cache/Traits/AbstractTrait.php', 'Symfony\\Component\\Cache\\Traits\\ApcuTrait' => $vendorDir . '/symfony/cache/Traits/ApcuTrait.php', 'Symfony\\Component\\Cache\\Traits\\ArrayTrait' => $vendorDir . '/symfony/cache/Traits/ArrayTrait.php', + 'Symfony\\Component\\Cache\\Traits\\ContractsTrait' => $vendorDir . '/symfony/cache/Traits/ContractsTrait.php', 'Symfony\\Component\\Cache\\Traits\\DoctrineTrait' => $vendorDir . '/symfony/cache/Traits/DoctrineTrait.php', 'Symfony\\Component\\Cache\\Traits\\FilesystemCommonTrait' => $vendorDir . '/symfony/cache/Traits/FilesystemCommonTrait.php', 'Symfony\\Component\\Cache\\Traits\\FilesystemTrait' => $vendorDir . '/symfony/cache/Traits/FilesystemTrait.php', + 'Symfony\\Component\\Cache\\Traits\\LazyValue' => $vendorDir . '/symfony/cache/Traits/PhpFilesTrait.php', 'Symfony\\Component\\Cache\\Traits\\MemcachedTrait' => $vendorDir . '/symfony/cache/Traits/MemcachedTrait.php', 'Symfony\\Component\\Cache\\Traits\\PdoTrait' => $vendorDir . '/symfony/cache/Traits/PdoTrait.php', 'Symfony\\Component\\Cache\\Traits\\PhpArrayTrait' => $vendorDir . '/symfony/cache/Traits/PhpArrayTrait.php', 'Symfony\\Component\\Cache\\Traits\\PhpFilesTrait' => $vendorDir . '/symfony/cache/Traits/PhpFilesTrait.php', 'Symfony\\Component\\Cache\\Traits\\ProxyTrait' => $vendorDir . '/symfony/cache/Traits/ProxyTrait.php', + 'Symfony\\Component\\Cache\\Traits\\RedisClusterNodeProxy' => $vendorDir . '/symfony/cache/Traits/RedisClusterNodeProxy.php', + 'Symfony\\Component\\Cache\\Traits\\RedisClusterProxy' => $vendorDir . '/symfony/cache/Traits/RedisClusterProxy.php', 'Symfony\\Component\\Cache\\Traits\\RedisProxy' => $vendorDir . '/symfony/cache/Traits/RedisProxy.php', 'Symfony\\Component\\Cache\\Traits\\RedisTrait' => $vendorDir . '/symfony/cache/Traits/RedisTrait.php', 'Symfony\\Component\\ExpressionLanguage\\Compiler' => $vendorDir . '/symfony/expression-language/Compiler.php', @@ -210,5 +232,32 @@ return array( 'Symfony\\Component\\ExpressionLanguage\\SyntaxError' => $vendorDir . '/symfony/expression-language/SyntaxError.php', 'Symfony\\Component\\ExpressionLanguage\\Token' => $vendorDir . '/symfony/expression-language/Token.php', 'Symfony\\Component\\ExpressionLanguage\\TokenStream' => $vendorDir . '/symfony/expression-language/TokenStream.php', - 'Symfony\\Polyfill\\Apcu\\Apcu' => $vendorDir . '/symfony/polyfill-apcu/Apcu.php', + 'Symfony\\Component\\VarExporter\\Exception\\ClassNotFoundException' => $vendorDir . '/symfony/var-exporter/Exception/ClassNotFoundException.php', + 'Symfony\\Component\\VarExporter\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/var-exporter/Exception/ExceptionInterface.php', + 'Symfony\\Component\\VarExporter\\Exception\\NotInstantiableTypeException' => $vendorDir . '/symfony/var-exporter/Exception/NotInstantiableTypeException.php', + 'Symfony\\Component\\VarExporter\\Instantiator' => $vendorDir . '/symfony/var-exporter/Instantiator.php', + 'Symfony\\Component\\VarExporter\\Internal\\Exporter' => $vendorDir . '/symfony/var-exporter/Internal/Exporter.php', + 'Symfony\\Component\\VarExporter\\Internal\\Hydrator' => $vendorDir . '/symfony/var-exporter/Internal/Hydrator.php', + 'Symfony\\Component\\VarExporter\\Internal\\Reference' => $vendorDir . '/symfony/var-exporter/Internal/Reference.php', + 'Symfony\\Component\\VarExporter\\Internal\\Registry' => $vendorDir . '/symfony/var-exporter/Internal/Registry.php', + 'Symfony\\Component\\VarExporter\\Internal\\Values' => $vendorDir . '/symfony/var-exporter/Internal/Values.php', + 'Symfony\\Component\\VarExporter\\VarExporter' => $vendorDir . '/symfony/var-exporter/VarExporter.php', + 'Symfony\\Contracts\\Cache\\CacheInterface' => $vendorDir . '/symfony/cache-contracts/CacheInterface.php', + 'Symfony\\Contracts\\Cache\\CacheTrait' => $vendorDir . '/symfony/cache-contracts/CacheTrait.php', + 'Symfony\\Contracts\\Cache\\CallbackInterface' => $vendorDir . '/symfony/cache-contracts/CallbackInterface.php', + 'Symfony\\Contracts\\Cache\\ItemInterface' => $vendorDir . '/symfony/cache-contracts/ItemInterface.php', + 'Symfony\\Contracts\\Cache\\TagAwareCacheInterface' => $vendorDir . '/symfony/cache-contracts/TagAwareCacheInterface.php', + 'Symfony\\Contracts\\Service\\Attribute\\Required' => $vendorDir . '/symfony/service-contracts/Attribute/Required.php', + 'Symfony\\Contracts\\Service\\Attribute\\SubscribedService' => $vendorDir . '/symfony/service-contracts/Attribute/SubscribedService.php', + 'Symfony\\Contracts\\Service\\ResetInterface' => $vendorDir . '/symfony/service-contracts/ResetInterface.php', + 'Symfony\\Contracts\\Service\\ServiceLocatorTrait' => $vendorDir . '/symfony/service-contracts/ServiceLocatorTrait.php', + 'Symfony\\Contracts\\Service\\ServiceProviderInterface' => $vendorDir . '/symfony/service-contracts/ServiceProviderInterface.php', + 'Symfony\\Contracts\\Service\\ServiceSubscriberInterface' => $vendorDir . '/symfony/service-contracts/ServiceSubscriberInterface.php', + 'Symfony\\Contracts\\Service\\ServiceSubscriberTrait' => $vendorDir . '/symfony/service-contracts/ServiceSubscriberTrait.php', + 'Symfony\\Contracts\\Service\\Test\\ServiceLocatorTest' => $vendorDir . '/symfony/service-contracts/Test/ServiceLocatorTest.php', + 'Symfony\\Polyfill\\Php73\\Php73' => $vendorDir . '/symfony/polyfill-php73/Php73.php', + 'Symfony\\Polyfill\\Php80\\Php80' => $vendorDir . '/symfony/polyfill-php80/Php80.php', + 'Symfony\\Polyfill\\Php80\\PhpToken' => $vendorDir . '/symfony/polyfill-php80/PhpToken.php', + 'UnhandledMatchError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php', + 'ValueError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/ValueError.php', ); diff --git a/advancedcontentfilter/vendor/composer/autoload_files.php b/advancedcontentfilter/vendor/composer/autoload_files.php index a6b8b352..a5d3b964 100644 --- a/advancedcontentfilter/vendor/composer/autoload_files.php +++ b/advancedcontentfilter/vendor/composer/autoload_files.php @@ -6,6 +6,8 @@ $vendorDir = dirname(dirname(__FILE__)); $baseDir = dirname($vendorDir); return array( - '32dcc8afd4335739640db7d200c1971d' => $vendorDir . '/symfony/polyfill-apcu/bootstrap.php', + 'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php', + '6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php', + '0d59ee240a4cd96ddbb4ff164fccea4d' => $vendorDir . '/symfony/polyfill-php73/bootstrap.php', '253c157292f75eb38082b5acb06f3f01' => $vendorDir . '/nikic/fast-route/src/functions.php', ); diff --git a/advancedcontentfilter/vendor/composer/autoload_psr4.php b/advancedcontentfilter/vendor/composer/autoload_psr4.php index 87606585..3d716d56 100644 --- a/advancedcontentfilter/vendor/composer/autoload_psr4.php +++ b/advancedcontentfilter/vendor/composer/autoload_psr4.php @@ -6,11 +6,14 @@ $vendorDir = dirname(dirname(__FILE__)); $baseDir = dirname($vendorDir); return array( - 'Symfony\\Polyfill\\Apcu\\' => array($vendorDir . '/symfony/polyfill-apcu'), + 'Symfony\\Polyfill\\Php80\\' => array($vendorDir . '/symfony/polyfill-php80'), + 'Symfony\\Polyfill\\Php73\\' => array($vendorDir . '/symfony/polyfill-php73'), + 'Symfony\\Contracts\\Service\\' => 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'), 'Slim\\' => array($vendorDir . '/slim/slim/Slim'), - 'Psr\\SimpleCache\\' => array($vendorDir . '/psr/simple-cache/src'), 'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'), 'Psr\\Http\\Server\\' => array($vendorDir . '/psr/http-server-handler/src', $vendorDir . '/psr/http-server-middleware/src'), 'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-factory/src', $vendorDir . '/psr/http-message/src'), diff --git a/advancedcontentfilter/vendor/composer/autoload_static.php b/advancedcontentfilter/vendor/composer/autoload_static.php index 917d3d90..57172a1a 100644 --- a/advancedcontentfilter/vendor/composer/autoload_static.php +++ b/advancedcontentfilter/vendor/composer/autoload_static.php @@ -7,21 +7,26 @@ namespace Composer\Autoload; class ComposerStaticInitAdvancedContentFilterAddon { public static $files = array ( - '32dcc8afd4335739640db7d200c1971d' => __DIR__ . '/..' . '/symfony/polyfill-apcu/bootstrap.php', + 'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php', + '6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php', + '0d59ee240a4cd96ddbb4ff164fccea4d' => __DIR__ . '/..' . '/symfony/polyfill-php73/bootstrap.php', '253c157292f75eb38082b5acb06f3f01' => __DIR__ . '/..' . '/nikic/fast-route/src/functions.php', ); public static $prefixLengthsPsr4 = array ( 'S' => array ( - 'Symfony\\Polyfill\\Apcu\\' => 22, + 'Symfony\\Polyfill\\Php80\\' => 23, + 'Symfony\\Polyfill\\Php73\\' => 23, + 'Symfony\\Contracts\\Service\\' => 26, + 'Symfony\\Contracts\\Cache\\' => 24, + 'Symfony\\Component\\VarExporter\\' => 30, 'Symfony\\Component\\ExpressionLanguage\\' => 37, 'Symfony\\Component\\Cache\\' => 24, 'Slim\\' => 5, ), 'P' => array ( - 'Psr\\SimpleCache\\' => 16, 'Psr\\Log\\' => 8, 'Psr\\Http\\Server\\' => 16, 'Psr\\Http\\Message\\' => 17, @@ -35,9 +40,25 @@ class ComposerStaticInitAdvancedContentFilterAddon ); public static $prefixDirsPsr4 = array ( - 'Symfony\\Polyfill\\Apcu\\' => + 'Symfony\\Polyfill\\Php80\\' => array ( - 0 => __DIR__ . '/..' . '/symfony/polyfill-apcu', + 0 => __DIR__ . '/..' . '/symfony/polyfill-php80', + ), + 'Symfony\\Polyfill\\Php73\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/polyfill-php73', + ), + '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 ( @@ -51,10 +72,6 @@ class ComposerStaticInitAdvancedContentFilterAddon array ( 0 => __DIR__ . '/..' . '/slim/slim/Slim', ), - 'Psr\\SimpleCache\\' => - array ( - 0 => __DIR__ . '/..' . '/psr/simple-cache/src', - ), 'Psr\\Log\\' => array ( 0 => __DIR__ . '/..' . '/psr/log/Psr/Log', @@ -84,6 +101,7 @@ class ComposerStaticInitAdvancedContentFilterAddon ); public static $classMap = array ( + 'Attribute' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Attribute.php', 'FastRoute\\BadRouteException' => __DIR__ . '/..' . '/nikic/fast-route/src/BadRouteException.php', 'FastRoute\\DataGenerator' => __DIR__ . '/..' . '/nikic/fast-route/src/DataGenerator.php', 'FastRoute\\DataGenerator\\CharCountBased' => __DIR__ . '/..' . '/nikic/fast-route/src/DataGenerator/CharCountBased.php', @@ -101,6 +119,8 @@ class ComposerStaticInitAdvancedContentFilterAddon 'FastRoute\\RouteCollector' => __DIR__ . '/..' . '/nikic/fast-route/src/RouteCollector.php', 'FastRoute\\RouteParser' => __DIR__ . '/..' . '/nikic/fast-route/src/RouteParser.php', 'FastRoute\\RouteParser\\Std' => __DIR__ . '/..' . '/nikic/fast-route/src/RouteParser/Std.php', + 'JsonException' => __DIR__ . '/..' . '/symfony/polyfill-php73/Resources/stubs/JsonException.php', + 'PhpToken' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php', 'Psr\\Cache\\CacheException' => __DIR__ . '/..' . '/psr/cache/src/CacheException.php', 'Psr\\Cache\\CacheItemInterface' => __DIR__ . '/..' . '/psr/cache/src/CacheItemInterface.php', 'Psr\\Cache\\CacheItemPoolInterface' => __DIR__ . '/..' . '/psr/cache/src/CacheItemPoolInterface.php', @@ -134,9 +154,6 @@ class ComposerStaticInitAdvancedContentFilterAddon 'Psr\\Log\\Test\\DummyTest' => __DIR__ . '/..' . '/psr/log/Psr/Log/Test/DummyTest.php', 'Psr\\Log\\Test\\LoggerInterfaceTest' => __DIR__ . '/..' . '/psr/log/Psr/Log/Test/LoggerInterfaceTest.php', 'Psr\\Log\\Test\\TestLogger' => __DIR__ . '/..' . '/psr/log/Psr/Log/Test/TestLogger.php', - 'Psr\\SimpleCache\\CacheException' => __DIR__ . '/..' . '/psr/simple-cache/src/CacheException.php', - 'Psr\\SimpleCache\\CacheInterface' => __DIR__ . '/..' . '/psr/simple-cache/src/CacheInterface.php', - 'Psr\\SimpleCache\\InvalidArgumentException' => __DIR__ . '/..' . '/psr/simple-cache/src/InvalidArgumentException.php', 'Slim\\App' => __DIR__ . '/..' . '/slim/slim/Slim/App.php', 'Slim\\CallableResolver' => __DIR__ . '/..' . '/slim/slim/Slim/CallableResolver.php', 'Slim\\Error\\AbstractErrorRenderer' => __DIR__ . '/..' . '/slim/slim/Slim/Error/AbstractErrorRenderer.php', @@ -153,6 +170,7 @@ class ComposerStaticInitAdvancedContentFilterAddon 'Slim\\Exception\\HttpNotFoundException' => __DIR__ . '/..' . '/slim/slim/Slim/Exception/HttpNotFoundException.php', 'Slim\\Exception\\HttpNotImplementedException' => __DIR__ . '/..' . '/slim/slim/Slim/Exception/HttpNotImplementedException.php', 'Slim\\Exception\\HttpSpecializedException' => __DIR__ . '/..' . '/slim/slim/Slim/Exception/HttpSpecializedException.php', + 'Slim\\Exception\\HttpTooManyRequestsException' => __DIR__ . '/..' . '/slim/slim/Slim/Exception/HttpTooManyRequestsException.php', 'Slim\\Exception\\HttpUnauthorizedException' => __DIR__ . '/..' . '/slim/slim/Slim/Exception/HttpUnauthorizedException.php', 'Slim\\Factory\\AppFactory' => __DIR__ . '/..' . '/slim/slim/Slim/Factory/AppFactory.php', 'Slim\\Factory\\Psr17\\GuzzlePsr17Factory' => __DIR__ . '/..' . '/slim/slim/Slim/Factory/Psr17/GuzzlePsr17Factory.php', @@ -208,20 +226,25 @@ class ComposerStaticInitAdvancedContentFilterAddon 'Slim\\Routing\\RouteResolver' => __DIR__ . '/..' . '/slim/slim/Slim/Routing/RouteResolver.php', 'Slim\\Routing\\RouteRunner' => __DIR__ . '/..' . '/slim/slim/Slim/Routing/RouteRunner.php', 'Slim\\Routing\\RoutingResults' => __DIR__ . '/..' . '/slim/slim/Slim/Routing/RoutingResults.php', + 'Stringable' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Stringable.php', 'Symfony\\Component\\Cache\\Adapter\\AbstractAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/AbstractAdapter.php', + 'Symfony\\Component\\Cache\\Adapter\\AbstractTagAwareAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/AbstractTagAwareAdapter.php', 'Symfony\\Component\\Cache\\Adapter\\AdapterInterface' => __DIR__ . '/..' . '/symfony/cache/Adapter/AdapterInterface.php', 'Symfony\\Component\\Cache\\Adapter\\ApcuAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/ApcuAdapter.php', 'Symfony\\Component\\Cache\\Adapter\\ArrayAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/ArrayAdapter.php', 'Symfony\\Component\\Cache\\Adapter\\ChainAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/ChainAdapter.php', 'Symfony\\Component\\Cache\\Adapter\\DoctrineAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/DoctrineAdapter.php', 'Symfony\\Component\\Cache\\Adapter\\FilesystemAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/FilesystemAdapter.php', + 'Symfony\\Component\\Cache\\Adapter\\FilesystemTagAwareAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/FilesystemTagAwareAdapter.php', 'Symfony\\Component\\Cache\\Adapter\\MemcachedAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/MemcachedAdapter.php', 'Symfony\\Component\\Cache\\Adapter\\NullAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/NullAdapter.php', 'Symfony\\Component\\Cache\\Adapter\\PdoAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/PdoAdapter.php', 'Symfony\\Component\\Cache\\Adapter\\PhpArrayAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/PhpArrayAdapter.php', 'Symfony\\Component\\Cache\\Adapter\\PhpFilesAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/PhpFilesAdapter.php', 'Symfony\\Component\\Cache\\Adapter\\ProxyAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/ProxyAdapter.php', + 'Symfony\\Component\\Cache\\Adapter\\Psr16Adapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/Psr16Adapter.php', 'Symfony\\Component\\Cache\\Adapter\\RedisAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/RedisAdapter.php', + 'Symfony\\Component\\Cache\\Adapter\\RedisTagAwareAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/RedisTagAwareAdapter.php', 'Symfony\\Component\\Cache\\Adapter\\SimpleCacheAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/SimpleCacheAdapter.php', 'Symfony\\Component\\Cache\\Adapter\\TagAwareAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/TagAwareAdapter.php', 'Symfony\\Component\\Cache\\Adapter\\TagAwareAdapterInterface' => __DIR__ . '/..' . '/symfony/cache/Adapter/TagAwareAdapterInterface.php', @@ -230,10 +253,21 @@ class ComposerStaticInitAdvancedContentFilterAddon 'Symfony\\Component\\Cache\\Adapter\\TraceableTagAwareAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/TraceableTagAwareAdapter.php', 'Symfony\\Component\\Cache\\CacheItem' => __DIR__ . '/..' . '/symfony/cache/CacheItem.php', 'Symfony\\Component\\Cache\\DataCollector\\CacheDataCollector' => __DIR__ . '/..' . '/symfony/cache/DataCollector/CacheDataCollector.php', + 'Symfony\\Component\\Cache\\DependencyInjection\\CacheCollectorPass' => __DIR__ . '/..' . '/symfony/cache/DependencyInjection/CacheCollectorPass.php', + 'Symfony\\Component\\Cache\\DependencyInjection\\CachePoolClearerPass' => __DIR__ . '/..' . '/symfony/cache/DependencyInjection/CachePoolClearerPass.php', + 'Symfony\\Component\\Cache\\DependencyInjection\\CachePoolPass' => __DIR__ . '/..' . '/symfony/cache/DependencyInjection/CachePoolPass.php', + 'Symfony\\Component\\Cache\\DependencyInjection\\CachePoolPrunerPass' => __DIR__ . '/..' . '/symfony/cache/DependencyInjection/CachePoolPrunerPass.php', 'Symfony\\Component\\Cache\\DoctrineProvider' => __DIR__ . '/..' . '/symfony/cache/DoctrineProvider.php', 'Symfony\\Component\\Cache\\Exception\\CacheException' => __DIR__ . '/..' . '/symfony/cache/Exception/CacheException.php', 'Symfony\\Component\\Cache\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/symfony/cache/Exception/InvalidArgumentException.php', + 'Symfony\\Component\\Cache\\Exception\\LogicException' => __DIR__ . '/..' . '/symfony/cache/Exception/LogicException.php', + 'Symfony\\Component\\Cache\\LockRegistry' => __DIR__ . '/..' . '/symfony/cache/LockRegistry.php', + 'Symfony\\Component\\Cache\\Marshaller\\DefaultMarshaller' => __DIR__ . '/..' . '/symfony/cache/Marshaller/DefaultMarshaller.php', + 'Symfony\\Component\\Cache\\Marshaller\\DeflateMarshaller' => __DIR__ . '/..' . '/symfony/cache/Marshaller/DeflateMarshaller.php', + 'Symfony\\Component\\Cache\\Marshaller\\MarshallerInterface' => __DIR__ . '/..' . '/symfony/cache/Marshaller/MarshallerInterface.php', + 'Symfony\\Component\\Cache\\Marshaller\\TagAwareMarshaller' => __DIR__ . '/..' . '/symfony/cache/Marshaller/TagAwareMarshaller.php', 'Symfony\\Component\\Cache\\PruneableInterface' => __DIR__ . '/..' . '/symfony/cache/PruneableInterface.php', + 'Symfony\\Component\\Cache\\Psr16Cache' => __DIR__ . '/..' . '/symfony/cache/Psr16Cache.php', 'Symfony\\Component\\Cache\\ResettableInterface' => __DIR__ . '/..' . '/symfony/cache/ResettableInterface.php', 'Symfony\\Component\\Cache\\Simple\\AbstractCache' => __DIR__ . '/..' . '/symfony/cache/Simple/AbstractCache.php', 'Symfony\\Component\\Cache\\Simple\\ApcuCache' => __DIR__ . '/..' . '/symfony/cache/Simple/ApcuCache.php', @@ -250,17 +284,22 @@ class ComposerStaticInitAdvancedContentFilterAddon 'Symfony\\Component\\Cache\\Simple\\RedisCache' => __DIR__ . '/..' . '/symfony/cache/Simple/RedisCache.php', 'Symfony\\Component\\Cache\\Simple\\TraceableCache' => __DIR__ . '/..' . '/symfony/cache/Simple/TraceableCache.php', 'Symfony\\Component\\Cache\\Simple\\TraceableCacheEvent' => __DIR__ . '/..' . '/symfony/cache/Simple/TraceableCache.php', + 'Symfony\\Component\\Cache\\Traits\\AbstractAdapterTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/AbstractAdapterTrait.php', 'Symfony\\Component\\Cache\\Traits\\AbstractTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/AbstractTrait.php', 'Symfony\\Component\\Cache\\Traits\\ApcuTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/ApcuTrait.php', 'Symfony\\Component\\Cache\\Traits\\ArrayTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/ArrayTrait.php', + 'Symfony\\Component\\Cache\\Traits\\ContractsTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/ContractsTrait.php', 'Symfony\\Component\\Cache\\Traits\\DoctrineTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/DoctrineTrait.php', 'Symfony\\Component\\Cache\\Traits\\FilesystemCommonTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/FilesystemCommonTrait.php', 'Symfony\\Component\\Cache\\Traits\\FilesystemTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/FilesystemTrait.php', + 'Symfony\\Component\\Cache\\Traits\\LazyValue' => __DIR__ . '/..' . '/symfony/cache/Traits/PhpFilesTrait.php', 'Symfony\\Component\\Cache\\Traits\\MemcachedTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/MemcachedTrait.php', 'Symfony\\Component\\Cache\\Traits\\PdoTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/PdoTrait.php', 'Symfony\\Component\\Cache\\Traits\\PhpArrayTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/PhpArrayTrait.php', 'Symfony\\Component\\Cache\\Traits\\PhpFilesTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/PhpFilesTrait.php', 'Symfony\\Component\\Cache\\Traits\\ProxyTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/ProxyTrait.php', + 'Symfony\\Component\\Cache\\Traits\\RedisClusterNodeProxy' => __DIR__ . '/..' . '/symfony/cache/Traits/RedisClusterNodeProxy.php', + 'Symfony\\Component\\Cache\\Traits\\RedisClusterProxy' => __DIR__ . '/..' . '/symfony/cache/Traits/RedisClusterProxy.php', 'Symfony\\Component\\Cache\\Traits\\RedisProxy' => __DIR__ . '/..' . '/symfony/cache/Traits/RedisProxy.php', 'Symfony\\Component\\Cache\\Traits\\RedisTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/RedisTrait.php', 'Symfony\\Component\\ExpressionLanguage\\Compiler' => __DIR__ . '/..' . '/symfony/expression-language/Compiler.php', @@ -288,7 +327,34 @@ class ComposerStaticInitAdvancedContentFilterAddon 'Symfony\\Component\\ExpressionLanguage\\SyntaxError' => __DIR__ . '/..' . '/symfony/expression-language/SyntaxError.php', 'Symfony\\Component\\ExpressionLanguage\\Token' => __DIR__ . '/..' . '/symfony/expression-language/Token.php', 'Symfony\\Component\\ExpressionLanguage\\TokenStream' => __DIR__ . '/..' . '/symfony/expression-language/TokenStream.php', - 'Symfony\\Polyfill\\Apcu\\Apcu' => __DIR__ . '/..' . '/symfony/polyfill-apcu/Apcu.php', + 'Symfony\\Component\\VarExporter\\Exception\\ClassNotFoundException' => __DIR__ . '/..' . '/symfony/var-exporter/Exception/ClassNotFoundException.php', + 'Symfony\\Component\\VarExporter\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/symfony/var-exporter/Exception/ExceptionInterface.php', + 'Symfony\\Component\\VarExporter\\Exception\\NotInstantiableTypeException' => __DIR__ . '/..' . '/symfony/var-exporter/Exception/NotInstantiableTypeException.php', + 'Symfony\\Component\\VarExporter\\Instantiator' => __DIR__ . '/..' . '/symfony/var-exporter/Instantiator.php', + 'Symfony\\Component\\VarExporter\\Internal\\Exporter' => __DIR__ . '/..' . '/symfony/var-exporter/Internal/Exporter.php', + 'Symfony\\Component\\VarExporter\\Internal\\Hydrator' => __DIR__ . '/..' . '/symfony/var-exporter/Internal/Hydrator.php', + 'Symfony\\Component\\VarExporter\\Internal\\Reference' => __DIR__ . '/..' . '/symfony/var-exporter/Internal/Reference.php', + 'Symfony\\Component\\VarExporter\\Internal\\Registry' => __DIR__ . '/..' . '/symfony/var-exporter/Internal/Registry.php', + 'Symfony\\Component\\VarExporter\\Internal\\Values' => __DIR__ . '/..' . '/symfony/var-exporter/Internal/Values.php', + 'Symfony\\Component\\VarExporter\\VarExporter' => __DIR__ . '/..' . '/symfony/var-exporter/VarExporter.php', + 'Symfony\\Contracts\\Cache\\CacheInterface' => __DIR__ . '/..' . '/symfony/cache-contracts/CacheInterface.php', + 'Symfony\\Contracts\\Cache\\CacheTrait' => __DIR__ . '/..' . '/symfony/cache-contracts/CacheTrait.php', + 'Symfony\\Contracts\\Cache\\CallbackInterface' => __DIR__ . '/..' . '/symfony/cache-contracts/CallbackInterface.php', + 'Symfony\\Contracts\\Cache\\ItemInterface' => __DIR__ . '/..' . '/symfony/cache-contracts/ItemInterface.php', + 'Symfony\\Contracts\\Cache\\TagAwareCacheInterface' => __DIR__ . '/..' . '/symfony/cache-contracts/TagAwareCacheInterface.php', + 'Symfony\\Contracts\\Service\\Attribute\\Required' => __DIR__ . '/..' . '/symfony/service-contracts/Attribute/Required.php', + 'Symfony\\Contracts\\Service\\Attribute\\SubscribedService' => __DIR__ . '/..' . '/symfony/service-contracts/Attribute/SubscribedService.php', + 'Symfony\\Contracts\\Service\\ResetInterface' => __DIR__ . '/..' . '/symfony/service-contracts/ResetInterface.php', + 'Symfony\\Contracts\\Service\\ServiceLocatorTrait' => __DIR__ . '/..' . '/symfony/service-contracts/ServiceLocatorTrait.php', + 'Symfony\\Contracts\\Service\\ServiceProviderInterface' => __DIR__ . '/..' . '/symfony/service-contracts/ServiceProviderInterface.php', + 'Symfony\\Contracts\\Service\\ServiceSubscriberInterface' => __DIR__ . '/..' . '/symfony/service-contracts/ServiceSubscriberInterface.php', + 'Symfony\\Contracts\\Service\\ServiceSubscriberTrait' => __DIR__ . '/..' . '/symfony/service-contracts/ServiceSubscriberTrait.php', + 'Symfony\\Contracts\\Service\\Test\\ServiceLocatorTest' => __DIR__ . '/..' . '/symfony/service-contracts/Test/ServiceLocatorTest.php', + 'Symfony\\Polyfill\\Php73\\Php73' => __DIR__ . '/..' . '/symfony/polyfill-php73/Php73.php', + 'Symfony\\Polyfill\\Php80\\Php80' => __DIR__ . '/..' . '/symfony/polyfill-php80/Php80.php', + 'Symfony\\Polyfill\\Php80\\PhpToken' => __DIR__ . '/..' . '/symfony/polyfill-php80/PhpToken.php', + 'UnhandledMatchError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php', + 'ValueError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/ValueError.php', ); public static function getInitializer(ClassLoader $loader) diff --git a/advancedcontentfilter/vendor/composer/installed.json b/advancedcontentfilter/vendor/composer/installed.json index 1a84a8fd..07e02c7f 100644 --- a/advancedcontentfilter/vendor/composer/installed.json +++ b/advancedcontentfilter/vendor/composer/installed.json @@ -97,29 +97,24 @@ }, { "name": "psr/container", - "version": "2.0.2", - "version_normalized": "2.0.2.0", + "version": "1.1.2", + "version_normalized": "1.1.2.0", "source": { "type": "git", "url": "https://github.com/php-fig/container.git", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" + "reference": "513e0666f7216c7459170d56df27dfcefe1689ea" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea", + "reference": "513e0666f7216c7459170d56df27dfcefe1689ea", "shasum": "" }, "require": { "php": ">=7.4.0" }, - "time": "2021-11-05T16:47:00+00:00", + "time": "2021-11-05T16:50:12+00:00", "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, "installation-source": "dist", "autoload": { "psr-4": { @@ -202,27 +197,27 @@ }, { "name": "psr/http-message", - "version": "1.1", - "version_normalized": "1.1.0.0", + "version": "2.0", + "version_normalized": "2.0.0.0", "source": { "type": "git", "url": "https://github.com/php-fig/http-message.git", - "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba" + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/cb6ce4845ce34a8ad9e68117c10ee90a29919eba", - "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", "shasum": "" }, "require": { "php": "^7.2 || ^8.0" }, - "time": "2023-04-04T09:50:52+00:00", + "time": "2023-04-04T09:54:51+00:00", "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1.x-dev" + "dev-master": "2.0.x-dev" } }, "installation-source": "dist", @@ -238,7 +233,7 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "homepage": "https://www.php-fig.org/" } ], "description": "Common interface for HTTP messages", @@ -411,69 +406,19 @@ "psr-3" ] }, - { - "name": "psr/simple-cache", - "version": "1.0.1", - "version_normalized": "1.0.1.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/simple-cache.git", - "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", - "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "time": "2017-10-23T01:57:42+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Psr\\SimpleCache\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Common interfaces for simple caching", - "keywords": [ - "cache", - "caching", - "psr", - "psr-16", - "simple-cache" - ] - }, { "name": "slim/slim", - "version": "4.12.0", - "version_normalized": "4.12.0.0", + "version": "4.13.0", + "version_normalized": "4.13.0.0", "source": { "type": "git", "url": "https://github.com/slimphp/Slim.git", - "reference": "e9e99c2b24398b967841c6c4c3048622cc7e2b18" + "reference": "038fd5713d5a41636fdff0e8dcceedecdd17fc17" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/slimphp/Slim/zipball/e9e99c2b24398b967841c6c4c3048622cc7e2b18", - "reference": "e9e99c2b24398b967841c6c4c3048622cc7e2b18", + "url": "https://api.github.com/repos/slimphp/Slim/zipball/038fd5713d5a41636fdff0e8dcceedecdd17fc17", + "reference": "038fd5713d5a41636fdff0e8dcceedecdd17fc17", "shasum": "" }, "require": { @@ -482,7 +427,7 @@ "php": "^7.4 || ^8.0", "psr/container": "^1.0 || ^2.0", "psr/http-factory": "^1.0", - "psr/http-message": "^1.1", + "psr/http-message": "^1.1 || ^2.0", "psr/http-server-handler": "^1.0", "psr/http-server-middleware": "^1.0", "psr/log": "^1.1 || ^2.0 || ^3.0" @@ -490,19 +435,19 @@ "require-dev": { "adriansuter/php-autoload-override": "^1.4", "ext-simplexml": "*", - "guzzlehttp/psr7": "^2.5", + "guzzlehttp/psr7": "^2.6", "httpsoft/http-message": "^1.1", "httpsoft/http-server-request": "^1.1", - "laminas/laminas-diactoros": "^2.17", + "laminas/laminas-diactoros": "^2.17 || ^3", "nyholm/psr7": "^1.8", - "nyholm/psr7-server": "^1.0", - "phpspec/prophecy": "^1.17", - "phpspec/prophecy-phpunit": "^2.0", + "nyholm/psr7-server": "^1.1", + "phpspec/prophecy": "^1.19", + "phpspec/prophecy-phpunit": "^2.1", "phpstan/phpstan": "^1.10", "phpunit/phpunit": "^9.6", "slim/http": "^1.3", "slim/psr7": "^1.6", - "squizlabs/php_codesniffer": "^3.7" + "squizlabs/php_codesniffer": "^3.9" }, "suggest": { "ext-simplexml": "Needed to support XML format in BodyParsingMiddleware", @@ -510,7 +455,7 @@ "php-di/php-di": "PHP-DI is the recommended container library to be used with Slim", "slim/psr7": "Slim PSR-7 implementation. See https://www.slimframework.com/docs/v4/start/installation.html for more information." }, - "time": "2023-07-23T04:54:29+00:00", + "time": "2024-03-03T21:25:30+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -570,40 +515,53 @@ }, { "name": "symfony/cache", - "version": "v3.4.47", - "version_normalized": "3.4.47.0", + "version": "v4.4.48", + "version_normalized": "4.4.48.0", "source": { "type": "git", "url": "https://github.com/symfony/cache.git", - "reference": "a7a14c4832760bd1fbd31be2859ffedc9b6ff813" + "reference": "3b98ed664887ad197b8ede3da2432787212eb915" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/a7a14c4832760bd1fbd31be2859ffedc9b6ff813", - "reference": "a7a14c4832760bd1fbd31be2859ffedc9b6ff813", + "url": "https://api.github.com/repos/symfony/cache/zipball/3b98ed664887ad197b8ede3da2432787212eb915", + "reference": "3b98ed664887ad197b8ede3da2432787212eb915", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8", - "psr/cache": "~1.0", - "psr/log": "~1.0", - "psr/simple-cache": "^1.0", - "symfony/polyfill-apcu": "~1.1" + "php": ">=7.1.3", + "psr/cache": "^1.0|^2.0", + "psr/log": "^1|^2|^3", + "symfony/cache-contracts": "^1.1.7|^2", + "symfony/polyfill-php73": "^1.9", + "symfony/polyfill-php80": "^1.16", + "symfony/service-contracts": "^1.1|^2", + "symfony/var-exporter": "^4.2|^5.0" }, "conflict": { - "symfony/var-dumper": "<3.3" + "doctrine/dbal": "<2.7", + "symfony/dependency-injection": "<3.4", + "symfony/http-kernel": "<4.4|>=5.0", + "symfony/var-dumper": "<4.4" }, "provide": { - "psr/cache-implementation": "1.0", - "psr/simple-cache-implementation": "1.0" + "psr/cache-implementation": "1.0|2.0", + "psr/simple-cache-implementation": "1.0|2.0", + "symfony/cache-implementation": "1.0|2.0" }, "require-dev": { "cache/integration-tests": "dev-master", - "doctrine/cache": "^1.6", - "doctrine/dbal": "^2.4|^3.0", - "predis/predis": "^1.0" + "doctrine/cache": "^1.6|^2.0", + "doctrine/dbal": "^2.7|^3.0", + "predis/predis": "^1.1", + "psr/simple-cache": "^1.0|^2.0", + "symfony/config": "^4.2|^5.0", + "symfony/dependency-injection": "^3.4|^4.1|^5.0", + "symfony/filesystem": "^4.4|^5.0", + "symfony/http-kernel": "^4.4", + "symfony/var-dumper": "^4.4|^5.0" }, - "time": "2020-10-24T10:57:07+00:00", + "time": "2022-10-17T20:21:54+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -628,7 +586,7 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony Cache component with PSR-6, PSR-16, and tags", + "description": "Provides extended PSR-6, PSR-16 (and tags) implementations", "homepage": "https://symfony.com", "keywords": [ "caching", @@ -649,6 +607,150 @@ } ] }, + { + "name": "symfony/cache-contracts", + "version": "v2.5.2", + "version_normalized": "2.5.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/cache-contracts.git", + "reference": "64be4a7acb83b6f2bf6de9a02cee6dad41277ebc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/64be4a7acb83b6f2bf6de9a02cee6dad41277ebc", + "reference": "64be4a7acb83b6f2bf6de9a02cee6dad41277ebc", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "psr/cache": "^1.0|^2.0|^3.0" + }, + "suggest": { + "symfony/cache-implementation": "" + }, + "time": "2022-01-02T09:53:40+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.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" + ], + "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" + } + ] + }, + { + "name": "symfony/deprecation-contracts", + "version": "v2.5.2", + "version_normalized": "2.5.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/e8b495ea28c1d97b5e0c121748d6f9b53d075c66", + "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "time": "2022-01-02T09:53:40+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.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", + "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" + } + ] + }, { "name": "symfony/expression-language", "version": "v3.4.47", @@ -711,82 +813,6 @@ } ] }, - { - "name": "symfony/polyfill-apcu", - "version": "v1.28.0", - "version_normalized": "1.28.0.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-apcu.git", - "reference": "c6c2c0f5f4cb0b100c5dfea807ef5cd27bbe9899" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-apcu/zipball/c6c2c0f5f4cb0b100c5dfea807ef5cd27bbe9899", - "reference": "c6c2c0f5f4cb0b100c5dfea807ef5cd27bbe9899", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "time": "2023-01-26T09:26:14+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "installation-source": "dist", - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Apcu\\": "" - } - }, - "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": "Symfony polyfill backporting apcu_* functions to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "apcu", - "compatibility", - "polyfill", - "portable", - "shim" - ], - "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" - } - ] - }, { "name": "symfony/polyfill-php70", "version": "v1.20.0", @@ -852,5 +878,313 @@ "type": "tidelift" } ] + }, + { + "name": "symfony/polyfill-php73", + "version": "v1.29.0", + "version_normalized": "1.29.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php73.git", + "reference": "21bd091060673a1177ae842c0ef8fe30893114d2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/21bd091060673a1177ae842c0ef8fe30893114d2", + "reference": "21bd091060673a1177ae842c0ef8fe30893114d2", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "time": "2024-01-29T20:11:03+00:00", + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "installation-source": "dist", + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php73\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "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": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "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" + } + ] + }, + { + "name": "symfony/polyfill-php80", + "version": "v1.29.0", + "version_normalized": "1.29.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/87b68208d5c1188808dd7839ee1e6c8ec3b02f1b", + "reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "time": "2024-01-29T20:11:03+00:00", + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "installation-source": "dist", + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php80\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "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" + } + ] + }, + { + "name": "symfony/service-contracts", + "version": "v2.5.2", + "version_normalized": "2.5.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/4b426aac47d6427cc1a1d0f7e2ac724627f5966c", + "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "psr/container": "^1.1", + "symfony/deprecation-contracts": "^2.1|^3" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "suggest": { + "symfony/service-implementation": "" + }, + "time": "2022-05-30T19:17:29+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + } + }, + "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" + ], + "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" + } + ] + }, + { + "name": "symfony/var-exporter", + "version": "v5.4.35", + "version_normalized": "5.4.35.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-exporter.git", + "reference": "abb0a151b62d6b07e816487e20040464af96cae7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/abb0a151b62d6b07e816487e20040464af96cae7", + "reference": "abb0a151b62d6b07e816487e20040464af96cae7", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/polyfill-php80": "^1.16" + }, + "require-dev": { + "symfony/var-dumper": "^4.4.9|^5.0.9|^6.0" + }, + "time": "2024-01-23T13:51:25+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", + "serialize" + ], + "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" + } + ] } ] diff --git a/advancedcontentfilter/vendor/psr/container/composer.json b/advancedcontentfilter/vendor/psr/container/composer.json index baf6cd1a..017f41ea 100644 --- a/advancedcontentfilter/vendor/psr/container/composer.json +++ b/advancedcontentfilter/vendor/psr/container/composer.json @@ -18,10 +18,5 @@ "psr-4": { "Psr\\Container\\": "src/" } - }, - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } } } diff --git a/advancedcontentfilter/vendor/psr/container/src/ContainerInterface.php b/advancedcontentfilter/vendor/psr/container/src/ContainerInterface.php index b2cad401..cf8e7fd3 100644 --- a/advancedcontentfilter/vendor/psr/container/src/ContainerInterface.php +++ b/advancedcontentfilter/vendor/psr/container/src/ContainerInterface.php @@ -32,5 +32,5 @@ interface ContainerInterface * * @return bool */ - public function has(string $id): bool; + public function has(string $id); } diff --git a/advancedcontentfilter/vendor/psr/http-message/composer.json b/advancedcontentfilter/vendor/psr/http-message/composer.json index 56e8c0a6..c66e5aba 100644 --- a/advancedcontentfilter/vendor/psr/http-message/composer.json +++ b/advancedcontentfilter/vendor/psr/http-message/composer.json @@ -7,7 +7,7 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "homepage": "https://www.php-fig.org/" } ], "require": { @@ -20,7 +20,7 @@ }, "extra": { "branch-alias": { - "dev-master": "1.1.x-dev" + "dev-master": "2.0.x-dev" } } } diff --git a/advancedcontentfilter/vendor/psr/http-message/src/MessageInterface.php b/advancedcontentfilter/vendor/psr/http-message/src/MessageInterface.php index 8cdb4ed6..a83c9851 100644 --- a/advancedcontentfilter/vendor/psr/http-message/src/MessageInterface.php +++ b/advancedcontentfilter/vendor/psr/http-message/src/MessageInterface.php @@ -1,7 +1,5 @@ + * + * 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. + * + * @param string $key The key of the item to retrieve from the cache + * @param callable|CallbackInterface $callback Should return the computed value for the given key/item + * @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 mixed + * + * @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); + + /** + * Removes an item from the pool. + * + * @param string $key The key to delete + * + * @throws InvalidArgumentException When $key is not valid + * + * @return bool True if the item was successfully removed, false if there was any error + */ + public function delete(string $key): bool; +} diff --git a/advancedcontentfilter/vendor/symfony/cache-contracts/CacheTrait.php b/advancedcontentfilter/vendor/symfony/cache-contracts/CacheTrait.php new file mode 100644 index 00000000..d340e069 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache-contracts/CacheTrait.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\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 +{ + /** + * {@inheritdoc} + * + * @return mixed + */ + public function get(string $key, callable $callback, float $beta = null, array &$metadata = null) + { + return $this->doGet($this, $key, $callback, $beta, $metadata); + } + + /** + * {@inheritdoc} + */ + 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) + { + if (0 > $beta = $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 && $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/advancedcontentfilter/vendor/symfony/cache-contracts/CallbackInterface.php b/advancedcontentfilter/vendor/symfony/cache-contracts/CallbackInterface.php new file mode 100644 index 00000000..7dae2aac --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache-contracts/CallbackInterface.php @@ -0,0 +1,30 @@ + + * + * 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 + */ +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 mixed The computed value for the passed item + */ + public function __invoke(CacheItemInterface $item, bool &$save); +} diff --git a/advancedcontentfilter/vendor/symfony/cache-contracts/ItemInterface.php b/advancedcontentfilter/vendor/symfony/cache-contracts/ItemInterface.php new file mode 100644 index 00000000..10c04889 --- /dev/null +++ b/advancedcontentfilter/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($tags): self; + + /** + * 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/advancedcontentfilter/vendor/symfony/cache-contracts/LICENSE b/advancedcontentfilter/vendor/symfony/cache-contracts/LICENSE new file mode 100644 index 00000000..74cdc2db --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache-contracts/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2018-2022 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/advancedcontentfilter/vendor/symfony/cache-contracts/README.md b/advancedcontentfilter/vendor/symfony/cache-contracts/README.md new file mode 100644 index 00000000..7085a699 --- /dev/null +++ b/advancedcontentfilter/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/advancedcontentfilter/vendor/symfony/cache-contracts/TagAwareCacheInterface.php b/advancedcontentfilter/vendor/symfony/cache-contracts/TagAwareCacheInterface.php new file mode 100644 index 00000000..7c4cf111 --- /dev/null +++ b/advancedcontentfilter/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); +} diff --git a/advancedcontentfilter/vendor/symfony/cache-contracts/composer.json b/advancedcontentfilter/vendor/symfony/cache-contracts/composer.json new file mode 100644 index 00000000..9f45e178 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache-contracts/composer.json @@ -0,0 +1,38 @@ +{ + "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": ">=7.2.5", + "psr/cache": "^1.0|^2.0|^3.0" + }, + "suggest": { + "symfony/cache-implementation": "" + }, + "autoload": { + "psr-4": { "Symfony\\Contracts\\Cache\\": "" } + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-main": "2.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + } +} diff --git a/advancedcontentfilter/vendor/symfony/cache/Adapter/AbstractAdapter.php b/advancedcontentfilter/vendor/symfony/cache/Adapter/AbstractAdapter.php index ab7dc960..65647442 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Adapter/AbstractAdapter.php +++ b/advancedcontentfilter/vendor/symfony/cache/Adapter/AbstractAdapter.php @@ -11,37 +11,32 @@ namespace Symfony\Component\Cache\Adapter; -use Psr\Cache\CacheItemInterface; 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\AbstractTrait; +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, LoggerAwareInterface, ResettableInterface +abstract class AbstractAdapter implements AdapterInterface, CacheInterface, LoggerAwareInterface, ResettableInterface { + use AbstractAdapterTrait; + use ContractsTrait; + /** * @internal */ - const NS_SEPARATOR = ':'; - - use AbstractTrait; + protected const NS_SEPARATOR = ':'; private static $apcuSupported; private static $phpFilesSupported; - private $createCacheItem; - private $mergeByLifetime; - - /** - * @param string $namespace - * @param int $defaultLifetime - */ - protected function __construct($namespace = '', $defaultLifetime = 0) + protected function __construct(string $namespace = '', int $defaultLifetime = 0) { $this->namespace = '' === $namespace ? '' : CacheItem::validateKey($namespace).static::NS_SEPARATOR; if (null !== $this->maxIdLength && \strlen($namespace) > $this->maxIdLength - 24) { @@ -51,31 +46,45 @@ abstract class AbstractAdapter implements AdapterInterface, LoggerAwareInterface static function ($key, $value, $isHit) { $item = new CacheItem(); $item->key = $key; - $item->value = $value; + $item->value = $v = $value; $item->isHit = $isHit; + // Detect wrapped values that encode for their expiry and creation duration + // For compactness, these values are packed in the key of an array using + // magic numbers in the form 9D-..-..-..-..-00-..-..-..-5F + if (\is_array($v) && 1 === \count($v) && 10 === \strlen($k = (string) array_key_first($v)) && "\x9D" === $k[0] && "\0" === $k[5] && "\x5F" === $k[9]) { + $item->value = $v[$k]; + $v = unpack('Ve/Nc', substr($k, 1, -1)); + $item->metadata[CacheItem::METADATA_EXPIRY] = $v['e'] + CacheItem::METADATA_EXPIRY_OFFSET; + $item->metadata[CacheItem::METADATA_CTIME] = $v['c']; + } return $item; }, null, CacheItem::class ); - $getId = function ($key) { return $this->getId((string) $key); }; + $getId = \Closure::fromCallable([$this, 'getId']); $this->mergeByLifetime = \Closure::bind( static function ($deferred, $namespace, &$expiredIds) use ($getId, $defaultLifetime) { $byLifetime = []; - $now = time(); + $now = microtime(true); $expiredIds = []; foreach ($deferred as $key => $item) { + $key = (string) $key; if (null === $item->expiry) { - $byLifetime[0 < $defaultLifetime ? $defaultLifetime : 0][$getId($key)] = $item->value; - } elseif (0 === $item->expiry) { - $byLifetime[0][$getId($key)] = $item->value; - } elseif ($item->expiry > $now) { - $byLifetime[$item->expiry - $now][$getId($key)] = $item->value; - } else { + $ttl = 0 < $defaultLifetime ? $defaultLifetime : 0; + } elseif (!$item->expiry) { + $ttl = 0; + } elseif (0 >= $ttl = (int) (0.1 + $item->expiry - $now)) { $expiredIds[] = $getId($key); + continue; } + if (isset(($metadata = $item->newMetadata)[CacheItem::METADATA_TAGS])) { + unset($metadata[CacheItem::METADATA_TAGS]); + } + // For compactness, expiry and creation duration are packed in the key of an array, using magic numbers as separators + $byLifetime[$ttl][$getId($key)] = $metadata ? ["\x9D".pack('VN', (int) (0.1 + $metadata[self::METADATA_EXPIRY] - self::METADATA_EXPIRY_OFFSET), $metadata[self::METADATA_CTIME])."\x5F" => $item->value] : $item->value; } return $byLifetime; @@ -86,6 +95,10 @@ abstract class AbstractAdapter implements AdapterInterface, LoggerAwareInterface } /** + * Returns the best possible adapter that your runtime supports. + * + * Using ApcuAdapter makes system caches compatible with read-only filesystems. + * * @param string $namespace * @param int $defaultLifetime * @param string $version @@ -95,37 +108,25 @@ abstract class AbstractAdapter implements AdapterInterface, LoggerAwareInterface */ public static function createSystemCache($namespace, $defaultLifetime, $version, $directory, LoggerInterface $logger = null) { - if (null === self::$apcuSupported) { - self::$apcuSupported = ApcuAdapter::isSupported(); + $opcache = new PhpFilesAdapter($namespace, $defaultLifetime, $directory, true); + if (null !== $logger) { + $opcache->setLogger($logger); } - if (!self::$apcuSupported && null === self::$phpFilesSupported) { - self::$phpFilesSupported = PhpFilesAdapter::isSupported(); - } - - if (self::$phpFilesSupported) { - $opcache = new PhpFilesAdapter($namespace, $defaultLifetime, $directory); - if (null !== $logger) { - $opcache->setLogger($logger); - } - + if (!self::$apcuSupported = self::$apcuSupported ?? ApcuAdapter::isSupported()) { return $opcache; } - $fs = new FilesystemAdapter($namespace, $defaultLifetime, $directory); - if (null !== $logger) { - $fs->setLogger($logger); - } - if (!self::$apcuSupported || (\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) && !filter_var(ini_get('apc.enable_cli'), \FILTER_VALIDATE_BOOLEAN))) { - return $fs; + if (\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) && !filter_var(\ini_get('apc.enable_cli'), \FILTER_VALIDATE_BOOLEAN)) { + return $opcache; } - $apcu = new ApcuAdapter($namespace, (int) $defaultLifetime / 5, $version); + $apcu = new ApcuAdapter($namespace, intdiv($defaultLifetime, 5), $version); if (null !== $logger) { $apcu->setLogger($logger); } - return new ChainAdapter([$apcu, $fs]); + return new ChainAdapter([$apcu, $opcache]); } public static function createConnection($dsn, array $options = []) @@ -133,10 +134,10 @@ abstract class AbstractAdapter implements AdapterInterface, LoggerAwareInterface if (!\is_string($dsn)) { throw new InvalidArgumentException(sprintf('The "%s()" method expect argument #1 to be string, "%s" given.', __METHOD__, \gettype($dsn))); } - if (0 === strpos($dsn, 'redis://')) { + if (str_starts_with($dsn, 'redis:') || str_starts_with($dsn, 'rediss:')) { return RedisAdapter::createConnection($dsn, $options); } - if (0 === strpos($dsn, 'memcached://')) { + if (str_starts_with($dsn, 'memcached:')) { return MemcachedAdapter::createConnection($dsn, $options); } @@ -145,81 +146,8 @@ abstract class AbstractAdapter implements AdapterInterface, LoggerAwareInterface /** * {@inheritdoc} - */ - public function getItem($key) - { - if ($this->deferred) { - $this->commit(); - } - $id = $this->getId($key); - - $f = $this->createCacheItem; - $isHit = false; - $value = null; - - try { - foreach ($this->doFetch([$id]) as $value) { - $isHit = true; - } - } catch (\Exception $e) { - CacheItem::log($this->logger, 'Failed to fetch key "{key}"', ['key' => $key, 'exception' => $e]); - } - - return $f($key, $value, $isHit); - } - - /** - * {@inheritdoc} - */ - public function getItems(array $keys = []) - { - if ($this->deferred) { - $this->commit(); - } - $ids = []; - - foreach ($keys as $key) { - $ids[] = $this->getId($key); - } - try { - $items = $this->doFetch($ids); - } catch (\Exception $e) { - CacheItem::log($this->logger, 'Failed to fetch requested items', ['keys' => $keys, 'exception' => $e]); - $items = []; - } - $ids = array_combine($ids, $keys); - - return $this->generateItems($items, $ids); - } - - /** - * {@inheritdoc} - */ - public function save(CacheItemInterface $item) - { - if (!$item instanceof CacheItem) { - return false; - } - $this->deferred[$item->getKey()] = $item; - - return $this->commit(); - } - - /** - * {@inheritdoc} - */ - public function saveDeferred(CacheItemInterface $item) - { - if (!$item instanceof CacheItem) { - return false; - } - $this->deferred[$item->getKey()] = $item; - - return true; - } - - /** - * {@inheritdoc} + * + * @return bool */ public function commit() { @@ -229,7 +157,12 @@ abstract class AbstractAdapter implements AdapterInterface, LoggerAwareInterface $retry = $this->deferred = []; if ($expiredIds) { - $this->doDelete($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 { @@ -244,7 +177,8 @@ abstract class AbstractAdapter implements AdapterInterface, LoggerAwareInterface $ok = false; $v = $values[$id]; $type = \is_object($v) ? \get_class($v) : \gettype($v); - CacheItem::log($this->logger, 'Failed to save key "{key}" ({type})', ['key' => substr($id, \strlen($this->namespace)), 'type' => $type, 'exception' => $e instanceof \Exception ? $e : null]); + $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]); } } else { foreach ($values as $id => $v) { @@ -266,49 +200,11 @@ abstract class AbstractAdapter implements AdapterInterface, LoggerAwareInterface } $ok = false; $type = \is_object($v) ? \get_class($v) : \gettype($v); - CacheItem::log($this->logger, 'Failed to save key "{key}" ({type})', ['key' => substr($id, \strlen($this->namespace)), 'type' => $type, 'exception' => $e instanceof \Exception ? $e : null]); + $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]); } } return $ok; } - - public function __sleep() - { - throw new \BadMethodCallException('Cannot serialize '.__CLASS__); - } - - public function __wakeup() - { - throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); - } - - public function __destruct() - { - if ($this->deferred) { - $this->commit(); - } - } - - private function generateItems($items, &$keys) - { - $f = $this->createCacheItem; - - try { - foreach ($items as $id => $value) { - if (!isset($keys[$id])) { - $id = key($keys); - } - $key = $keys[$id]; - unset($keys[$id]); - yield $key => $f($key, $value, true); - } - } catch (\Exception $e) { - CacheItem::log($this->logger, 'Failed to fetch requested items', ['keys' => array_values($keys), 'exception' => $e]); - } - - foreach ($keys as $key) { - yield $key => $f($key, null, false); - } - } } diff --git a/advancedcontentfilter/vendor/symfony/cache/Adapter/AbstractTagAwareAdapter.php b/advancedcontentfilter/vendor/symfony/cache/Adapter/AbstractTagAwareAdapter.php new file mode 100644 index 00000000..6b62ae98 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Adapter/AbstractTagAwareAdapter.php @@ -0,0 +1,334 @@ + + * + * 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 = "\0tags\0"; + + protected function __construct(string $namespace = '', int $defaultLifetime = 0) + { + $this->namespace = '' === $namespace ? '' : CacheItem::validateKey($namespace).':'; + 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)); + } + $this->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] = $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 + ); + $getId = \Closure::fromCallable([$this, 'getId']); + $tagPrefix = self::TAGS_PREFIX; + $this->mergeByLifetime = \Closure::bind( + static function ($deferred, &$expiredIds) use ($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[self::METADATA_EXPIRY] - self::METADATA_EXPIRY_OFFSET), $metadata[self::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($value['tags'], $oldTags) as $addedTag) { + $value['tag-operations']['add'][] = $getId($tagPrefix.$addedTag); + } + foreach (array_diff($oldTags, $value['tags']) as $removedTag) { + $value['tag-operations']['remove'][] = $getId($tagPrefix.$removedTag); + } + + $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 + * + * @return bool True if the items were successfully removed, false otherwise + */ + abstract protected function doDelete(array $ids); + + /** + * 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 + * + * @return bool True on success + */ + 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); + } + + /** + * {@inheritdoc} + */ + public function commit(): bool + { + $ok = true; + $byLifetime = $this->mergeByLifetime; + $byLifetime = $byLifetime($this->deferred, $expiredIds); + $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 (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 = \is_object($v) ? \get_class($v) : \gettype($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]); + } + } 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 (true === $e || [] === $e) { + continue; + } + $ok = false; + $type = \is_object($v) ? \get_class($v) : \gettype($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]); + } + } + + return $ok; + } + + /** + * {@inheritdoc} + */ + 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 $e) { + $ok = false; + } + + try { + if ((!$tagData || $this->doDeleteTagRelations($tagData)) && $ok) { + return true; + } + } catch (\Exception $e) { + } + + // 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]); + $ok = false; + } + + return $ok; + } + + /** + * {@inheritdoc} + */ + public function invalidateTags(array $tags) + { + if (empty($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/advancedcontentfilter/vendor/symfony/cache/Adapter/AdapterInterface.php b/advancedcontentfilter/vendor/symfony/cache/Adapter/AdapterInterface.php index 85fe0768..9e359e17 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Adapter/AdapterInterface.php +++ b/advancedcontentfilter/vendor/symfony/cache/Adapter/AdapterInterface.php @@ -14,6 +14,9 @@ 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. * @@ -34,4 +37,13 @@ interface AdapterInterface extends CacheItemPoolInterface * @return \Traversable|CacheItem[] */ public function getItems(array $keys = []); + + /** + * {@inheritdoc} + * + * @param string $prefix + * + * @return bool + */ + public function clear(/* string $prefix = '' */); } diff --git a/advancedcontentfilter/vendor/symfony/cache/Adapter/ApcuAdapter.php b/advancedcontentfilter/vendor/symfony/cache/Adapter/ApcuAdapter.php index 50554ed6..7db39565 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Adapter/ApcuAdapter.php +++ b/advancedcontentfilter/vendor/symfony/cache/Adapter/ApcuAdapter.php @@ -18,13 +18,9 @@ class ApcuAdapter extends AbstractAdapter use ApcuTrait; /** - * @param string $namespace - * @param int $defaultLifetime - * @param string|null $version - * * @throws CacheException if APCu is not enabled */ - public function __construct($namespace = '', $defaultLifetime = 0, $version = null) + public function __construct(string $namespace = '', int $defaultLifetime = 0, string $version = null) { $this->init($namespace, $defaultLifetime, $version); } diff --git a/advancedcontentfilter/vendor/symfony/cache/Adapter/ArrayAdapter.php b/advancedcontentfilter/vendor/symfony/cache/Adapter/ArrayAdapter.php index 33f55a86..20043dec 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Adapter/ArrayAdapter.php +++ b/advancedcontentfilter/vendor/symfony/cache/Adapter/ArrayAdapter.php @@ -16,11 +16,12 @@ use Psr\Log\LoggerAwareInterface; use Symfony\Component\Cache\CacheItem; use Symfony\Component\Cache\ResettableInterface; use Symfony\Component\Cache\Traits\ArrayTrait; +use Symfony\Contracts\Cache\CacheInterface; /** * @author Nicolas Grekas */ -class ArrayAdapter implements AdapterInterface, LoggerAwareInterface, ResettableInterface +class ArrayAdapter implements AdapterInterface, CacheInterface, LoggerAwareInterface, ResettableInterface { use ArrayTrait; @@ -28,10 +29,9 @@ class ArrayAdapter implements AdapterInterface, LoggerAwareInterface, Resettable private $defaultLifetime; /** - * @param int $defaultLifetime * @param bool $storeSerialized Disabling serialization can lead to cache corruptions when storing mutable values but increases performance otherwise */ - public function __construct($defaultLifetime = 0, $storeSerialized = true) + public function __construct(int $defaultLifetime = 0, bool $storeSerialized = true) { $this->defaultLifetime = $defaultLifetime; $this->storeSerialized = $storeSerialized; @@ -49,27 +49,35 @@ class ArrayAdapter implements AdapterInterface, LoggerAwareInterface, Resettable ); } + /** + * {@inheritdoc} + */ + public function get(string $key, callable $callback, float $beta = null, array &$metadata = null) + { + $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(); + } + /** * {@inheritdoc} */ public function getItem($key) { - $isHit = $this->hasItem($key); - try { - if (!$isHit) { - $this->values[$key] = $value = null; - } elseif (!$this->storeSerialized) { - $value = $this->values[$key]; - } elseif ('b:0;' === $value = $this->values[$key]) { - $value = false; - } elseif (false === $value = unserialize($value)) { - $this->values[$key] = $value = null; - $isHit = false; - } - } catch (\Exception $e) { - CacheItem::log($this->logger, 'Failed to unserialize key "{key}"', ['key' => $key, 'exception' => $e]); + if (!$isHit = $this->hasItem($key)) { $this->values[$key] = $value = null; - $isHit = false; + } else { + $value = $this->storeSerialized ? $this->unfreeze($key, $isHit) : $this->values[$key]; } $f = $this->createCacheItem; @@ -82,14 +90,18 @@ class ArrayAdapter implements AdapterInterface, LoggerAwareInterface, Resettable public function getItems(array $keys = []) { foreach ($keys as $key) { - CacheItem::validateKey($key); + if (!\is_string($key) || !isset($this->expiries[$key])) { + CacheItem::validateKey($key); + } } - return $this->generateItems($keys, time(), $this->createCacheItem); + return $this->generateItems($keys, microtime(true), $this->createCacheItem); } /** * {@inheritdoc} + * + * @return bool */ public function deleteItems(array $keys) { @@ -102,6 +114,8 @@ class ArrayAdapter implements AdapterInterface, LoggerAwareInterface, Resettable /** * {@inheritdoc} + * + * @return bool */ public function save(CacheItemInterface $item) { @@ -113,37 +127,32 @@ class ArrayAdapter implements AdapterInterface, LoggerAwareInterface, Resettable $value = $item["\0*\0value"]; $expiry = $item["\0*\0expiry"]; - if (0 === $expiry) { - $expiry = \PHP_INT_MAX; - } + if (null !== $expiry) { + if (!$expiry) { + $expiry = \PHP_INT_MAX; + } elseif ($expiry <= microtime(true)) { + $this->deleteItem($key); - if (null !== $expiry && $expiry <= time()) { - $this->deleteItem($key); - - return true; - } - if ($this->storeSerialized) { - try { - $value = serialize($value); - } catch (\Exception $e) { - $type = \is_object($value) ? \get_class($value) : \gettype($value); - CacheItem::log($this->logger, 'Failed to save key "{key}" ({type})', ['key' => $key, 'type' => $type, 'exception' => $e]); - - return false; + return true; } } + if ($this->storeSerialized && null === $value = $this->freeze($value, $key)) { + return false; + } if (null === $expiry && 0 < $this->defaultLifetime) { - $expiry = time() + $this->defaultLifetime; + $expiry = microtime(true) + $this->defaultLifetime; } $this->values[$key] = $value; - $this->expiries[$key] = null !== $expiry ? $expiry : \PHP_INT_MAX; + $this->expiries[$key] = $expiry ?? \PHP_INT_MAX; return true; } /** * {@inheritdoc} + * + * @return bool */ public function saveDeferred(CacheItemInterface $item) { @@ -152,9 +161,19 @@ class ArrayAdapter implements AdapterInterface, LoggerAwareInterface, Resettable /** * {@inheritdoc} + * + * @return bool */ public function commit() { return true; } + + /** + * {@inheritdoc} + */ + public function delete(string $key): bool + { + return $this->deleteItem($key); + } } diff --git a/advancedcontentfilter/vendor/symfony/cache/Adapter/ChainAdapter.php b/advancedcontentfilter/vendor/symfony/cache/Adapter/ChainAdapter.php index fdb28846..57fb096b 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Adapter/ChainAdapter.php +++ b/advancedcontentfilter/vendor/symfony/cache/Adapter/ChainAdapter.php @@ -17,6 +17,9 @@ 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. @@ -26,8 +29,10 @@ use Symfony\Component\Cache\ResettableInterface; * * @author Kévin Dunglas */ -class ChainAdapter implements AdapterInterface, PruneableInterface, ResettableInterface +class ChainAdapter implements AdapterInterface, CacheInterface, PruneableInterface, ResettableInterface { + use ContractsTrait; + private $adapters = []; private $adapterCount; private $syncItem; @@ -36,7 +41,7 @@ class ChainAdapter implements AdapterInterface, PruneableInterface, ResettableIn * @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, $defaultLifetime = 0) + public function __construct(array $adapters, int $defaultLifetime = 0) { if (!$adapters) { throw new InvalidArgumentException('At least one adapter must be specified.'); @@ -46,7 +51,7 @@ class ChainAdapter implements AdapterInterface, PruneableInterface, ResettableIn if (!$adapter instanceof CacheItemPoolInterface) { throw new InvalidArgumentException(sprintf('The class "%s" does not implement the "%s" interface.', \get_class($adapter), CacheItemPoolInterface::class)); } - if (\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) && $adapter instanceof ApcuAdapter && !filter_var(ini_get('apc.enable_cli'), \FILTER_VALIDATE_BOOLEAN)) { + if (\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) && $adapter instanceof ApcuAdapter && !filter_var(\ini_get('apc.enable_cli'), \FILTER_VALIDATE_BOOLEAN)) { continue; // skip putting APCu in the chain when the backend is disabled } @@ -59,11 +64,18 @@ class ChainAdapter implements AdapterInterface, PruneableInterface, ResettableIn $this->adapterCount = \count($this->adapters); $this->syncItem = \Closure::bind( - static function ($sourceItem, $item) use ($defaultLifetime) { + static function ($sourceItem, $item, $sourceMetadata = null) use ($defaultLifetime) { + $sourceItem->isTaggable = false; + $sourceMetadata = $sourceMetadata ?? $sourceItem->metadata; + unset($sourceMetadata[CacheItem::METADATA_TAGS]); + $item->value = $sourceItem->value; $item->isHit = $sourceItem->isHit; + $item->metadata = $item->newMetadata = $sourceItem->metadata = $sourceMetadata; - if (0 < $defaultLifetime) { + if (isset($item->metadata[CacheItem::METADATA_EXPIRY])) { + $item->expiresAt(\DateTime::createFromFormat('U.u', sprintf('%.6F', $item->metadata[CacheItem::METADATA_EXPIRY]))); + } elseif (0 < $defaultLifetime) { $item->expiresAfter($defaultLifetime); } @@ -74,6 +86,43 @@ class ChainAdapter implements AdapterInterface, PruneableInterface, ResettableIn ); } + /** + * {@inheritdoc} + */ + public function get(string $key, callable $callback, float $beta = null, array &$metadata = null) + { + $doSave = true; + $callback = static function (CacheItem $item, bool &$save) use ($callback, &$doSave) { + $value = $callback($item, $save); + $doSave = $save; + + return $value; + }; + + $lastItem = null; + $i = 0; + $wrap = function (CacheItem $item = null, bool &$save = true) use ($key, $callback, $beta, &$wrap, &$i, &$doSave, &$lastItem, &$metadata) { + $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) { + ($this->syncItem)($lastItem = $lastItem ?? $item, $item, $metadata); + } + $save = $doSave; + + return $value; + }; + + return $wrap(); + } + /** * {@inheritdoc} */ @@ -107,12 +156,12 @@ class ChainAdapter implements AdapterInterface, PruneableInterface, ResettableIn return $this->generateItems($this->adapters[0]->getItems($keys), 0); } - private function generateItems($items, $adapterIndex) + private function generateItems(iterable $items, int $adapterIndex) { $missing = []; $misses = []; $nextAdapterIndex = $adapterIndex + 1; - $nextAdapter = isset($this->adapters[$nextAdapterIndex]) ? $this->adapters[$nextAdapterIndex] : null; + $nextAdapter = $this->adapters[$nextAdapterIndex] ?? null; foreach ($items as $k => $item) { if (!$nextAdapter || $item->isHit()) { @@ -140,6 +189,8 @@ class ChainAdapter implements AdapterInterface, PruneableInterface, ResettableIn /** * {@inheritdoc} + * + * @return bool */ public function hasItem($key) { @@ -154,14 +205,23 @@ class ChainAdapter implements AdapterInterface, PruneableInterface, ResettableIn /** * {@inheritdoc} + * + * @param string $prefix + * + * @return bool */ - public function clear() + public function clear(/* string $prefix = '' */) { + $prefix = 0 < \func_num_args() ? (string) func_get_arg(0) : ''; $cleared = true; $i = $this->adapterCount; while ($i--) { - $cleared = $this->adapters[$i]->clear() && $cleared; + if ($this->adapters[$i] instanceof AdapterInterface) { + $cleared = $this->adapters[$i]->clear($prefix) && $cleared; + } else { + $cleared = $this->adapters[$i]->clear() && $cleared; + } } return $cleared; @@ -169,6 +229,8 @@ class ChainAdapter implements AdapterInterface, PruneableInterface, ResettableIn /** * {@inheritdoc} + * + * @return bool */ public function deleteItem($key) { @@ -184,6 +246,8 @@ class ChainAdapter implements AdapterInterface, PruneableInterface, ResettableIn /** * {@inheritdoc} + * + * @return bool */ public function deleteItems(array $keys) { @@ -199,6 +263,8 @@ class ChainAdapter implements AdapterInterface, PruneableInterface, ResettableIn /** * {@inheritdoc} + * + * @return bool */ public function save(CacheItemInterface $item) { @@ -214,6 +280,8 @@ class ChainAdapter implements AdapterInterface, PruneableInterface, ResettableIn /** * {@inheritdoc} + * + * @return bool */ public function saveDeferred(CacheItemInterface $item) { @@ -229,6 +297,8 @@ class ChainAdapter implements AdapterInterface, PruneableInterface, ResettableIn /** * {@inheritdoc} + * + * @return bool */ public function commit() { @@ -264,7 +334,7 @@ class ChainAdapter implements AdapterInterface, PruneableInterface, ResettableIn public function reset() { foreach ($this->adapters as $adapter) { - if ($adapter instanceof ResettableInterface) { + if ($adapter instanceof ResetInterface) { $adapter->reset(); } } diff --git a/advancedcontentfilter/vendor/symfony/cache/Adapter/DoctrineAdapter.php b/advancedcontentfilter/vendor/symfony/cache/Adapter/DoctrineAdapter.php index 8081d7dc..75ae4cb7 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Adapter/DoctrineAdapter.php +++ b/advancedcontentfilter/vendor/symfony/cache/Adapter/DoctrineAdapter.php @@ -18,11 +18,7 @@ class DoctrineAdapter extends AbstractAdapter { use DoctrineTrait; - /** - * @param string $namespace - * @param int $defaultLifetime - */ - public function __construct(CacheProvider $provider, $namespace = '', $defaultLifetime = 0) + public function __construct(CacheProvider $provider, string $namespace = '', int $defaultLifetime = 0) { parent::__construct('', $defaultLifetime); $this->provider = $provider; diff --git a/advancedcontentfilter/vendor/symfony/cache/Adapter/FilesystemAdapter.php b/advancedcontentfilter/vendor/symfony/cache/Adapter/FilesystemAdapter.php index d071964e..7185dd48 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Adapter/FilesystemAdapter.php +++ b/advancedcontentfilter/vendor/symfony/cache/Adapter/FilesystemAdapter.php @@ -11,6 +11,8 @@ 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; @@ -18,13 +20,9 @@ class FilesystemAdapter extends AbstractAdapter implements PruneableInterface { use FilesystemTrait; - /** - * @param string $namespace - * @param int $defaultLifetime - * @param string|null $directory - */ - public function __construct($namespace = '', $defaultLifetime = 0, $directory = null) + 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/advancedcontentfilter/vendor/symfony/cache/Adapter/FilesystemTagAwareAdapter.php b/advancedcontentfilter/vendor/symfony/cache/Adapter/FilesystemTagAwareAdapter.php new file mode 100644 index 00000000..6dccbf08 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Adapter/FilesystemTagAwareAdapter.php @@ -0,0 +1,239 @@ + + * + * 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 { + 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); + } + + /** + * {@inheritdoc} + */ + protected function doClear($namespace) + { + $ok = $this->doClearCache($namespace); + + if ('' !== $namespace) { + return $ok; + } + + set_error_handler(static function () {}); + $chars = '+-ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; + + try { + foreach ($this->scanHashDir($this->directory.self::TAG_FOLDER.\DIRECTORY_SEPARATOR) as $dir) { + if (rename($dir, $renamed = substr_replace($dir, bin2hex(random_bytes(4)), -8))) { + $dir = $renamed.\DIRECTORY_SEPARATOR; + } else { + $dir .= \DIRECTORY_SEPARATOR; + $renamed = null; + } + + for ($i = 0; $i < 38; ++$i) { + if (!file_exists($dir.$chars[$i])) { + continue; + } + for ($j = 0; $j < 38; ++$j) { + if (!file_exists($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; + } + + /** + * {@inheritdoc} + */ + 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; + } + + /** + * {@inheritdoc} + */ + protected function doDeleteYieldTags(array $ids): iterable + { + foreach ($ids as $id) { + $file = $this->getFile($id); + if (!file_exists($file) || !$h = @fopen($file, 'r')) { + continue; + } + + if ((\PHP_VERSION_ID >= 70300 || '\\' !== \DIRECTORY_SEPARATOR) && !@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 $e) { + yield $id => []; + } + } + + fclose($h); + + if (\PHP_VERSION_ID < 70300 && '\\' === \DIRECTORY_SEPARATOR) { + @unlink($file); + } + } + } + + /** + * {@inheritdoc} + */ + 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; + } + + /** + * {@inheritdoc} + */ + protected function doInvalidate(array $tagIds): bool + { + foreach ($tagIds as $tagId) { + if (!file_exists($tagFolder = $this->getTagFolder($tagId))) { + continue; + } + + set_error_handler(static function () {}); + + try { + if (rename($tagFolder, $renamed = substr_replace($tagFolder, bin2hex(random_bytes(4)), -9))) { + $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/advancedcontentfilter/vendor/symfony/cache/Adapter/MemcachedAdapter.php b/advancedcontentfilter/vendor/symfony/cache/Adapter/MemcachedAdapter.php index 5637141a..b678bb5d 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Adapter/MemcachedAdapter.php +++ b/advancedcontentfilter/vendor/symfony/cache/Adapter/MemcachedAdapter.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Cache\Adapter; +use Symfony\Component\Cache\Marshaller\MarshallerInterface; use Symfony\Component\Cache\Traits\MemcachedTrait; class MemcachedAdapter extends AbstractAdapter @@ -29,8 +30,8 @@ class MemcachedAdapter extends AbstractAdapter * * Using a MemcachedAdapter as a pure items store is fine. */ - public function __construct(\Memcached $client, $namespace = '', $defaultLifetime = 0) + public function __construct(\Memcached $client, string $namespace = '', int $defaultLifetime = 0, MarshallerInterface $marshaller = null) { - $this->init($client, $namespace, $defaultLifetime); + $this->init($client, $namespace, $defaultLifetime, $marshaller); } } diff --git a/advancedcontentfilter/vendor/symfony/cache/Adapter/NullAdapter.php b/advancedcontentfilter/vendor/symfony/cache/Adapter/NullAdapter.php index c81a1cd6..3c2979bd 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Adapter/NullAdapter.php +++ b/advancedcontentfilter/vendor/symfony/cache/Adapter/NullAdapter.php @@ -13,11 +13,12 @@ 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 +class NullAdapter implements AdapterInterface, CacheInterface { private $createCacheItem; @@ -36,6 +37,16 @@ class NullAdapter implements AdapterInterface ); } + /** + * {@inheritdoc} + */ + public function get(string $key, callable $callback, float $beta = null, array &$metadata = null) + { + $save = true; + + return $callback(($this->createCacheItem)($key), $save); + } + /** * {@inheritdoc} */ @@ -56,6 +67,8 @@ class NullAdapter implements AdapterInterface /** * {@inheritdoc} + * + * @return bool */ public function hasItem($key) { @@ -64,14 +77,20 @@ class NullAdapter implements AdapterInterface /** * {@inheritdoc} + * + * @param string $prefix + * + * @return bool */ - public function clear() + public function clear(/* string $prefix = '' */) { return true; } /** * {@inheritdoc} + * + * @return bool */ public function deleteItem($key) { @@ -80,6 +99,8 @@ class NullAdapter implements AdapterInterface /** * {@inheritdoc} + * + * @return bool */ public function deleteItems(array $keys) { @@ -88,26 +109,40 @@ class NullAdapter implements AdapterInterface /** * {@inheritdoc} + * + * @return bool */ public function save(CacheItemInterface $item) { - return false; + return true; } /** * {@inheritdoc} + * + * @return bool */ public function saveDeferred(CacheItemInterface $item) { - return false; + return true; + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function commit() + { + return true; } /** * {@inheritdoc} */ - public function commit() + public function delete(string $key): bool { - return false; + return $this->deleteItem($key); } private function generateItems(array $keys) diff --git a/advancedcontentfilter/vendor/symfony/cache/Adapter/PdoAdapter.php b/advancedcontentfilter/vendor/symfony/cache/Adapter/PdoAdapter.php index 59038679..d118736a 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Adapter/PdoAdapter.php +++ b/advancedcontentfilter/vendor/symfony/cache/Adapter/PdoAdapter.php @@ -13,6 +13,7 @@ namespace Symfony\Component\Cache\Adapter; use Doctrine\DBAL\Connection; use Symfony\Component\Cache\Exception\InvalidArgumentException; +use Symfony\Component\Cache\Marshaller\MarshallerInterface; use Symfony\Component\Cache\PruneableInterface; use Symfony\Component\Cache\Traits\PdoTrait; @@ -27,6 +28,9 @@ class PdoAdapter extends AbstractAdapter implements PruneableInterface * a Doctrine DBAL Connection or a DSN string that will be used to * lazy-connect to the database when the cache is actually used. * + * When a Doctrine DBAL Connection is passed, 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] @@ -37,17 +41,14 @@ class PdoAdapter extends AbstractAdapter implements PruneableInterface * * db_password: The password when lazy-connect [default: ''] * * db_connection_options: An array of driver-specific connection options [default: []] * - * @param \PDO|Connection|string $connOrDsn A \PDO or Connection instance or DSN string or null - * @param string $namespace - * @param int $defaultLifetime - * @param array $options An associative array of options + * @param \PDO|Connection|string $connOrDsn a \PDO or Connection instance or DSN string or null * * @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($connOrDsn, $namespace = '', $defaultLifetime = 0, array $options = []) + public function __construct($connOrDsn, string $namespace = '', int $defaultLifetime = 0, array $options = [], MarshallerInterface $marshaller = null) { - $this->init($connOrDsn, $namespace, $defaultLifetime, $options); + $this->init($connOrDsn, $namespace, $defaultLifetime, $options, $marshaller); } } diff --git a/advancedcontentfilter/vendor/symfony/cache/Adapter/PhpArrayAdapter.php b/advancedcontentfilter/vendor/symfony/cache/Adapter/PhpArrayAdapter.php index 47a259c1..bdce6e1a 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Adapter/PhpArrayAdapter.php +++ b/advancedcontentfilter/vendor/symfony/cache/Adapter/PhpArrayAdapter.php @@ -17,7 +17,9 @@ 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\PhpArrayTrait; +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. @@ -26,8 +28,9 @@ use Symfony\Component\Cache\Traits\PhpArrayTrait; * @author Titouan Galopin * @author Nicolas Grekas */ -class PhpArrayAdapter implements AdapterInterface, PruneableInterface, ResettableInterface +class PhpArrayAdapter implements AdapterInterface, CacheInterface, PruneableInterface, ResettableInterface { + use ContractsTrait; use PhpArrayTrait; private $createCacheItem; @@ -36,11 +39,10 @@ class PhpArrayAdapter implements AdapterInterface, PruneableInterface, Resettabl * @param string $file The PHP file were values are cached * @param AdapterInterface $fallbackPool A pool to fallback on when an item is not hit */ - public function __construct($file, AdapterInterface $fallbackPool) + public function __construct(string $file, AdapterInterface $fallbackPool) { $this->file = $file; $this->pool = $fallbackPool; - $this->zendDetectUnicode = filter_var(ini_get('zend.detect_unicode'), \FILTER_VALIDATE_BOOLEAN); $this->createCacheItem = \Closure::bind( static function ($key, $value, $isHit) { $item = new CacheItem(); @@ -56,9 +58,7 @@ class PhpArrayAdapter implements AdapterInterface, PruneableInterface, Resettabl } /** - * This adapter should only be used on PHP 7.0+ to take advantage of how PHP - * stores arrays in its latest versions. This factory method decorates the given - * fallback pool with this adapter only if the current PHP version is supported. + * 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 @@ -67,15 +67,44 @@ class PhpArrayAdapter implements AdapterInterface, PruneableInterface, Resettabl */ public static function create($file, CacheItemPoolInterface $fallbackPool) { - if (\PHP_VERSION_ID >= 70000) { - if (!$fallbackPool instanceof AdapterInterface) { - $fallbackPool = new ProxyAdapter($fallbackPool); - } - - return new static($file, $fallbackPool); + if (!$fallbackPool instanceof AdapterInterface) { + $fallbackPool = new ProxyAdapter($fallbackPool); } - return $fallbackPool; + return new static($file, $fallbackPool); + } + + /** + * {@inheritdoc} + */ + public function get(string $key, callable $callback, float $beta = null, array &$metadata = null) + { + if (null === $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 $e) { + unset($this->keys[$key]); + goto get_from_pool; + } + + return $value; } /** @@ -89,23 +118,19 @@ class PhpArrayAdapter implements AdapterInterface, PruneableInterface, Resettabl if (null === $this->values) { $this->initialize(); } - if (!isset($this->values[$key])) { + if (!isset($this->keys[$key])) { return $this->pool->getItem($key); } - $value = $this->values[$key]; + $value = $this->values[$this->keys[$key]]; $isHit = true; if ('N;' === $value) { $value = null; - } elseif (\is_string($value) && isset($value[2]) && ':' === $value[1]) { + } elseif ($value instanceof \Closure) { try { - $e = null; - $value = unserialize($value); - } catch (\Error $e) { - } catch (\Exception $e) { - } - if (null !== $e) { + $value = $value(); + } catch (\Throwable $e) { $value = null; $isHit = false; } @@ -135,6 +160,8 @@ class PhpArrayAdapter implements AdapterInterface, PruneableInterface, Resettabl /** * {@inheritdoc} + * + * @return bool */ public function hasItem($key) { @@ -145,11 +172,13 @@ class PhpArrayAdapter implements AdapterInterface, PruneableInterface, Resettabl $this->initialize(); } - return isset($this->values[$key]) || $this->pool->hasItem($key); + return isset($this->keys[$key]) || $this->pool->hasItem($key); } /** * {@inheritdoc} + * + * @return bool */ public function deleteItem($key) { @@ -160,11 +189,13 @@ class PhpArrayAdapter implements AdapterInterface, PruneableInterface, Resettabl $this->initialize(); } - return !isset($this->values[$key]) && $this->pool->deleteItem($key); + return !isset($this->keys[$key]) && $this->pool->deleteItem($key); } /** * {@inheritdoc} + * + * @return bool */ public function deleteItems(array $keys) { @@ -176,7 +207,7 @@ class PhpArrayAdapter implements AdapterInterface, PruneableInterface, Resettabl throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', \is_object($key) ? \get_class($key) : \gettype($key))); } - if (isset($this->values[$key])) { + if (isset($this->keys[$key])) { $deleted = false; } else { $fallbackKeys[] = $key; @@ -195,6 +226,8 @@ class PhpArrayAdapter implements AdapterInterface, PruneableInterface, Resettabl /** * {@inheritdoc} + * + * @return bool */ public function save(CacheItemInterface $item) { @@ -202,11 +235,13 @@ class PhpArrayAdapter implements AdapterInterface, PruneableInterface, Resettabl $this->initialize(); } - return !isset($this->values[$item->getKey()]) && $this->pool->save($item); + return !isset($this->keys[$item->getKey()]) && $this->pool->save($item); } /** * {@inheritdoc} + * + * @return bool */ public function saveDeferred(CacheItemInterface $item) { @@ -214,37 +249,34 @@ class PhpArrayAdapter implements AdapterInterface, PruneableInterface, Resettabl $this->initialize(); } - return !isset($this->values[$item->getKey()]) && $this->pool->saveDeferred($item); + return !isset($this->keys[$item->getKey()]) && $this->pool->saveDeferred($item); } /** * {@inheritdoc} + * + * @return bool */ public function commit() { return $this->pool->commit(); } - /** - * @return \Generator - */ - private function generateItems(array $keys) + private function generateItems(array $keys): \Generator { $f = $this->createCacheItem; $fallbackKeys = []; foreach ($keys as $key) { - if (isset($this->values[$key])) { - $value = $this->values[$key]; + if (isset($this->keys[$key])) { + $value = $this->values[$this->keys[$key]]; if ('N;' === $value) { yield $key => $f($key, null, true); - } elseif (\is_string($value) && isset($value[2]) && ':' === $value[1]) { + } elseif ($value instanceof \Closure) { try { - yield $key => $f($key, unserialize($value), true); - } catch (\Error $e) { - yield $key => $f($key, null, false); - } catch (\Exception $e) { + yield $key => $f($key, $value(), true); + } catch (\Throwable $e) { yield $key => $f($key, null, false); } } else { @@ -256,9 +288,7 @@ class PhpArrayAdapter implements AdapterInterface, PruneableInterface, Resettabl } if ($fallbackKeys) { - foreach ($this->pool->getItems($fallbackKeys) as $key => $item) { - yield $key => $item; - } + yield from $this->pool->getItems($fallbackKeys); } } diff --git a/advancedcontentfilter/vendor/symfony/cache/Adapter/PhpFilesAdapter.php b/advancedcontentfilter/vendor/symfony/cache/Adapter/PhpFilesAdapter.php index b56143c2..10938a0a 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Adapter/PhpFilesAdapter.php +++ b/advancedcontentfilter/vendor/symfony/cache/Adapter/PhpFilesAdapter.php @@ -20,22 +20,19 @@ class PhpFilesAdapter extends AbstractAdapter implements PruneableInterface use PhpFilesTrait; /** - * @param string $namespace - * @param int $defaultLifetime - * @param string|null $directory + * @param $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($namespace = '', $defaultLifetime = 0, $directory = null) + public function __construct(string $namespace = '', int $defaultLifetime = 0, string $directory = null, bool $appendOnly = false) { - if (!static::isSupported()) { - throw new CacheException('OPcache is not enabled.'); - } + $this->appendOnly = $appendOnly; + self::$startTime = self::$startTime ?? $_SERVER['REQUEST_TIME'] ?? time(); parent::__construct('', $defaultLifetime); $this->init($namespace, $directory); - - $e = new \Exception(); - $this->includeHandler = function () use ($e) { throw $e; }; - $this->zendDetectUnicode = filter_var(ini_get('zend.detect_unicode'), \FILTER_VALIDATE_BOOLEAN); + $this->includeHandler = static function ($type, $msg, $file, $line) { + throw new \ErrorException($msg, 0, $type, $file, $line); + }; } } diff --git a/advancedcontentfilter/vendor/symfony/cache/Adapter/ProxyAdapter.php b/advancedcontentfilter/vendor/symfony/cache/Adapter/ProxyAdapter.php index c89a760e..e006ea01 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Adapter/ProxyAdapter.php +++ b/advancedcontentfilter/vendor/symfony/cache/Adapter/ProxyAdapter.php @@ -16,26 +16,26 @@ 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, PruneableInterface, ResettableInterface +class ProxyAdapter implements AdapterInterface, CacheInterface, PruneableInterface, ResettableInterface { + use ContractsTrait; use ProxyTrait; private $namespace; private $namespaceLen; private $createCacheItem; + private $setInnerItem; private $poolHash; private $defaultLifetime; - /** - * @param string $namespace - * @param int $defaultLifetime - */ - public function __construct(CacheItemPoolInterface $pool, $namespace = '', $defaultLifetime = 0) + public function __construct(CacheItemPoolInterface $pool, string $namespace = '', int $defaultLifetime = 0) { $this->pool = $pool; $this->poolHash = $poolHash = spl_object_hash($pool); @@ -46,20 +46,71 @@ class ProxyAdapter implements AdapterInterface, PruneableInterface, ResettableIn static function ($key, $innerItem) use ($poolHash) { $item = new CacheItem(); $item->key = $key; + + if (null === $innerItem) { + return $item; + } + + $item->value = $v = $innerItem->get(); + $item->isHit = $innerItem->isHit(); + $item->innerItem = $innerItem; $item->poolHash = $poolHash; - if (null !== $innerItem) { - $item->value = $innerItem->get(); - $item->isHit = $innerItem->isHit(); - $item->innerItem = $innerItem; - $innerItem->set(null); + // Detect wrapped values that encode for their expiry and creation duration + // For compactness, these values are packed in the key of an array using + // magic numbers in the form 9D-..-..-..-..-00-..-..-..-5F + if (\is_array($v) && 1 === \count($v) && 10 === \strlen($k = (string) array_key_first($v)) && "\x9D" === $k[0] && "\0" === $k[5] && "\x5F" === $k[9]) { + $item->value = $v[$k]; + $v = unpack('Ve/Nc', substr($k, 1, -1)); + $item->metadata[CacheItem::METADATA_EXPIRY] = $v['e'] + CacheItem::METADATA_EXPIRY_OFFSET; + $item->metadata[CacheItem::METADATA_CTIME] = $v['c']; + } elseif ($innerItem instanceof CacheItem) { + $item->metadata = $innerItem->metadata; } + $innerItem->set(null); return $item; }, null, CacheItem::class ); + $this->setInnerItem = \Closure::bind( + /** + * @param array $item A CacheItem cast to (array); accessing protected properties requires adding the "\0*\0" PHP prefix + */ + static function (CacheItemInterface $innerItem, array $item) { + // Tags are stored separately, no need to account for them when considering this item's newly set metadata + if (isset(($metadata = $item["\0*\0newMetadata"])[CacheItem::METADATA_TAGS])) { + unset($metadata[CacheItem::METADATA_TAGS]); + } + if ($metadata) { + // For compactness, expiry and creation duration are packed in the key of an array, using magic numbers as separators + $item["\0*\0value"] = ["\x9D".pack('VN', (int) (0.1 + $metadata[self::METADATA_EXPIRY] - self::METADATA_EXPIRY_OFFSET), $metadata[self::METADATA_CTIME])."\x5F" => $item["\0*\0value"]]; + } + $innerItem->set($item["\0*\0value"]); + $innerItem->expiresAt(null !== $item["\0*\0expiry"] ? \DateTime::createFromFormat('U.u', sprintf('%.6F', $item["\0*\0expiry"])) : null); + }, + null, + CacheItem::class + ); + } + + /** + * {@inheritdoc} + */ + public function get(string $key, callable $callback, float $beta = null, array &$metadata = null) + { + 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 = ($this->createCacheItem)($key, $innerItem); + $item->set($value = $callback($item, $save)); + ($this->setInnerItem)($innerItem, (array) $item); + + return $value; + }, $beta, $metadata); } /** @@ -89,6 +140,8 @@ class ProxyAdapter implements AdapterInterface, PruneableInterface, ResettableIn /** * {@inheritdoc} + * + * @return bool */ public function hasItem($key) { @@ -97,14 +150,26 @@ class ProxyAdapter implements AdapterInterface, PruneableInterface, ResettableIn /** * {@inheritdoc} + * + * @param string $prefix + * + * @return bool */ - public function clear() + public function clear(/* string $prefix = '' */) { + $prefix = 0 < \func_num_args() ? (string) func_get_arg(0) : ''; + + if ($this->pool instanceof AdapterInterface) { + return $this->pool->clear($this->namespace.$prefix); + } + return $this->pool->clear(); } /** * {@inheritdoc} + * + * @return bool */ public function deleteItem($key) { @@ -113,6 +178,8 @@ class ProxyAdapter implements AdapterInterface, PruneableInterface, ResettableIn /** * {@inheritdoc} + * + * @return bool */ public function deleteItems(array $keys) { @@ -127,6 +194,8 @@ class ProxyAdapter implements AdapterInterface, PruneableInterface, ResettableIn /** * {@inheritdoc} + * + * @return bool */ public function save(CacheItemInterface $item) { @@ -135,6 +204,8 @@ class ProxyAdapter implements AdapterInterface, PruneableInterface, ResettableIn /** * {@inheritdoc} + * + * @return bool */ public function saveDeferred(CacheItemInterface $item) { @@ -143,21 +214,22 @@ class ProxyAdapter implements AdapterInterface, PruneableInterface, ResettableIn /** * {@inheritdoc} + * + * @return bool */ public function commit() { return $this->pool->commit(); } - private function doSave(CacheItemInterface $item, $method) + private function doSave(CacheItemInterface $item, string $method) { if (!$item instanceof CacheItem) { return false; } $item = (array) $item; - $expiry = $item["\0*\0expiry"]; - if (null === $expiry && 0 < $this->defaultLifetime) { - $expiry = time() + $this->defaultLifetime; + if (null === $item["\0*\0expiry"] && 0 < $this->defaultLifetime) { + $item["\0*\0expiry"] = microtime(true) + $this->defaultLifetime; } if ($item["\0*\0poolHash"] === $this->poolHash && $item["\0*\0innerItem"]) { @@ -171,13 +243,12 @@ class ProxyAdapter implements AdapterInterface, PruneableInterface, ResettableIn $innerItem = $this->pool->getItem($this->namespace.$item["\0*\0key"]); } - $innerItem->set($item["\0*\0value"]); - $innerItem->expiresAt(null !== $expiry ? \DateTime::createFromFormat('U', $expiry) : null); + ($this->setInnerItem)($innerItem, $item); return $this->pool->$method($innerItem); } - private function generateItems($items) + private function generateItems(iterable $items) { $f = $this->createCacheItem; @@ -190,7 +261,7 @@ class ProxyAdapter implements AdapterInterface, PruneableInterface, ResettableIn } } - private function getId($key) + private function getId($key): string { CacheItem::validateKey($key); diff --git a/advancedcontentfilter/vendor/symfony/cache/Adapter/Psr16Adapter.php b/advancedcontentfilter/vendor/symfony/cache/Adapter/Psr16Adapter.php new file mode 100644 index 00000000..e959d784 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Adapter/Psr16Adapter.php @@ -0,0 +1,86 @@ + + * + * 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 $miss; + + public function __construct(CacheInterface $pool, string $namespace = '', int $defaultLifetime = 0) + { + parent::__construct($namespace, $defaultLifetime); + + $this->pool = $pool; + $this->miss = new \stdClass(); + } + + /** + * {@inheritdoc} + */ + protected function doFetch(array $ids) + { + foreach ($this->pool->getMultiple($ids, $this->miss) as $key => $value) { + if ($this->miss !== $value) { + yield $key => $value; + } + } + } + + /** + * {@inheritdoc} + */ + protected function doHave($id) + { + return $this->pool->has($id); + } + + /** + * {@inheritdoc} + */ + protected function doClear($namespace) + { + return $this->pool->clear(); + } + + /** + * {@inheritdoc} + */ + protected function doDelete(array $ids) + { + return $this->pool->deleteMultiple($ids); + } + + /** + * {@inheritdoc} + */ + protected function doSave(array $values, int $lifetime) + { + return $this->pool->setMultiple($values, 0 === $lifetime ? null : $lifetime); + } +} diff --git a/advancedcontentfilter/vendor/symfony/cache/Adapter/RedisAdapter.php b/advancedcontentfilter/vendor/symfony/cache/Adapter/RedisAdapter.php index c1e17997..eb5950e5 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Adapter/RedisAdapter.php +++ b/advancedcontentfilter/vendor/symfony/cache/Adapter/RedisAdapter.php @@ -11,6 +11,9 @@ namespace Symfony\Component\Cache\Adapter; +use Symfony\Component\Cache\Marshaller\MarshallerInterface; +use Symfony\Component\Cache\Traits\RedisClusterProxy; +use Symfony\Component\Cache\Traits\RedisProxy; use Symfony\Component\Cache\Traits\RedisTrait; class RedisAdapter extends AbstractAdapter @@ -18,12 +21,12 @@ class RedisAdapter extends AbstractAdapter use RedisTrait; /** - * @param \Redis|\RedisArray|\RedisCluster|\Predis\Client $redisClient The redis client - * @param string $namespace The default namespace - * @param int $defaultLifetime The default lifetime + * @param \Redis|\RedisArray|\RedisCluster|\Predis\ClientInterface|RedisProxy|RedisClusterProxy $redis The redis client + * @param string $namespace The default namespace + * @param int $defaultLifetime The default lifetime */ - public function __construct($redisClient, $namespace = '', $defaultLifetime = 0) + public function __construct($redis, string $namespace = '', int $defaultLifetime = 0, MarshallerInterface $marshaller = null) { - $this->init($redisClient, $namespace, $defaultLifetime); + $this->init($redis, $namespace, $defaultLifetime, $marshaller); } } diff --git a/advancedcontentfilter/vendor/symfony/cache/Adapter/RedisTagAwareAdapter.php b/advancedcontentfilter/vendor/symfony/cache/Adapter/RedisTagAwareAdapter.php new file mode 100644 index 00000000..fd263da3 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Adapter/RedisTagAwareAdapter.php @@ -0,0 +1,321 @@ + + * + * 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 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\RedisClusterProxy; +use Symfony\Component\Cache\Traits\RedisProxy; +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; + + /** + * @var string|null detected eviction policy used on Redis server + */ + private $redisEvictionPolicy; + private $namespace; + + /** + * @param \Redis|\RedisArray|\RedisCluster|\Predis\ClientInterface|RedisProxy|RedisClusterProxy $redis The redis client + * @param string $namespace The default namespace + * @param int $defaultLifetime The default lifetime + */ + public function __construct($redis, 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_class($redis->getConnection()))); + } + + if (\defined('Redis::OPT_COMPRESSION') && ($redis instanceof \Redis || $redis instanceof \RedisArray || $redis instanceof \RedisCluster)) { + $compression = $redis->getOption(\Redis::OPT_COMPRESSION); + + foreach (\is_array($compression) ? $compression : [$compression] as $c) { + if (\Redis::COMPRESSION_NONE !== $c) { + throw new InvalidArgumentException(sprintf('phpredis compression must be disabled when using "%s", use "%s" instead.', static::class, DeflateMarshaller::class)); + } + } + } + + $this->init($redis, $namespace, $defaultLifetime, new TagAwareMarshaller($marshaller)); + $this->namespace = $namespace; + } + + /** + * {@inheritdoc} + */ + 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; + } + + /** + * {@inheritdoc} + */ + protected function doDeleteYieldTags(array $ids): iterable + { + $lua = <<<'EOLUA' + local v = redis.call('GET', KEYS[1]) + redis.call('DEL', KEYS[1]) + + 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 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 $e) { + yield $id => []; + } + } + } + + /** + * {@inheritdoc} + */ + 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; + } + + /** + * {@inheritdoc} + */ + 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(\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 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 (null !== $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 ($info instanceof ErrorInterface) { + continue; + } + + $info = $info['Memory'] ?? $info; + + return $this->redisEvictionPolicy = $info['maxmemory_policy']; + } + + return $this->redisEvictionPolicy = ''; + } +} diff --git a/advancedcontentfilter/vendor/symfony/cache/Adapter/SimpleCacheAdapter.php b/advancedcontentfilter/vendor/symfony/cache/Adapter/SimpleCacheAdapter.php index d3d0ede6..5f14a85b 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Adapter/SimpleCacheAdapter.php +++ b/advancedcontentfilter/vendor/symfony/cache/Adapter/SimpleCacheAdapter.php @@ -11,73 +11,11 @@ namespace Symfony\Component\Cache\Adapter; -use Psr\SimpleCache\CacheInterface; -use Symfony\Component\Cache\PruneableInterface; -use Symfony\Component\Cache\Traits\ProxyTrait; +@trigger_error(sprintf('The "%s" class is @deprecated since Symfony 4.3, use "Psr16Adapter" instead.', SimpleCacheAdapter::class), \E_USER_DEPRECATED); /** - * @author Nicolas Grekas + * @deprecated since Symfony 4.3, use Psr16Adapter instead. */ -class SimpleCacheAdapter extends AbstractAdapter implements PruneableInterface +class SimpleCacheAdapter extends Psr16Adapter { - /** - * @internal - */ - const NS_SEPARATOR = '_'; - - use ProxyTrait; - - private $miss; - - public function __construct(CacheInterface $pool, $namespace = '', $defaultLifetime = 0) - { - parent::__construct($namespace, $defaultLifetime); - - $this->pool = $pool; - $this->miss = new \stdClass(); - } - - /** - * {@inheritdoc} - */ - protected function doFetch(array $ids) - { - foreach ($this->pool->getMultiple($ids, $this->miss) as $key => $value) { - if ($this->miss !== $value) { - yield $key => $value; - } - } - } - - /** - * {@inheritdoc} - */ - protected function doHave($id) - { - return $this->pool->has($id); - } - - /** - * {@inheritdoc} - */ - protected function doClear($namespace) - { - return $this->pool->clear(); - } - - /** - * {@inheritdoc} - */ - protected function doDelete(array $ids) - { - return $this->pool->deleteMultiple($ids); - } - - /** - * {@inheritdoc} - */ - protected function doSave(array $values, $lifetime) - { - return $this->pool->setMultiple($values, 0 === $lifetime ? null : $lifetime); - } } diff --git a/advancedcontentfilter/vendor/symfony/cache/Adapter/TagAwareAdapter.php b/advancedcontentfilter/vendor/symfony/cache/Adapter/TagAwareAdapter.php index febe5090..105d4a64 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Adapter/TagAwareAdapter.php +++ b/advancedcontentfilter/vendor/symfony/cache/Adapter/TagAwareAdapter.php @@ -13,20 +13,26 @@ 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\Component\Cache\Traits\ProxyTrait; +use Symfony\Contracts\Cache\TagAwareCacheInterface; /** * @author Nicolas Grekas */ -class TagAwareAdapter implements TagAwareAdapterInterface, PruneableInterface, ResettableInterface +class TagAwareAdapter implements TagAwareAdapterInterface, TagAwareCacheInterface, PruneableInterface, ResettableInterface, LoggerAwareInterface { - const TAGS_PREFIX = "\0tags\0"; - + use ContractsTrait; + use LoggerAwareTrait; use ProxyTrait; + public const TAGS_PREFIX = "\0tags\0"; + private $deferred = []; private $createCacheItem; private $setCacheItemTags; @@ -36,7 +42,7 @@ class TagAwareAdapter implements TagAwareAdapterInterface, PruneableInterface, R private $knownTagVersions = []; private $knownTagVersionsTtl; - public function __construct(AdapterInterface $itemsPool, AdapterInterface $tagsPool = null, $knownTagVersionsTtl = 0.15) + public function __construct(AdapterInterface $itemsPool, AdapterInterface $tagsPool = null, float $knownTagVersionsTtl = 0.15) { $this->pool = $itemsPool; $this->tags = $tagsPool ?: $itemsPool; @@ -56,12 +62,13 @@ class TagAwareAdapter implements TagAwareAdapterInterface, PruneableInterface, R ); $this->setCacheItemTags = \Closure::bind( static function (CacheItem $item, $key, array &$itemTags) { + $item->isTaggable = true; if (!$item->isHit) { return $item; } if (isset($itemTags[$key])) { foreach ($itemTags[$key] as $tag => $version) { - $item->prevTags[$tag] = $tag; + $item->metadata[CacheItem::METADATA_TAGS][$tag] = $tag; } unset($itemTags[$key]); } else { @@ -78,7 +85,8 @@ class TagAwareAdapter implements TagAwareAdapterInterface, PruneableInterface, R static function ($deferred) { $tagsByKey = []; foreach ($deferred as $key => $item) { - $tagsByKey[$key] = $item->tags; + $tagsByKey[$key] = $item->newMetadata[CacheItem::METADATA_TAGS] ?? []; + $item->metadata = $item->newMetadata; } return $tagsByKey; @@ -145,12 +153,15 @@ class TagAwareAdapter implements TagAwareAdapterInterface, PruneableInterface, R /** * {@inheritdoc} + * + * @return bool */ public function hasItem($key) { - if ($this->deferred) { + if (\is_string($key) && isset($this->deferred[$key])) { $this->commit(); } + if (!$this->pool->hasItem($key)) { return false; } @@ -166,9 +177,11 @@ class TagAwareAdapter implements TagAwareAdapterInterface, PruneableInterface, R } foreach ($this->getTagVersions([$itemTags]) as $tag => $version) { - if ($itemTags[$tag] !== $version && 1 !== $itemTags[$tag] - $version) { - return false; + if ($itemTags[$tag] === $version || \is_int($itemTags[$tag]) && \is_int($version) && 1 === $itemTags[$tag] - $version) { + continue; } + + return false; } return true; @@ -191,18 +204,21 @@ class TagAwareAdapter implements TagAwareAdapterInterface, PruneableInterface, R */ public function getItems(array $keys = []) { - if ($this->deferred) { - $this->commit(); - } $tagKeys = []; + $commit = false; foreach ($keys as $key) { if ('' !== $key && \is_string($key)) { + $commit = $commit || isset($this->deferred[$key]); $key = static::TAGS_PREFIX.$key; $tagKeys[$key] = $key; } } + if ($commit) { + $this->commit(); + } + try { $items = $this->pool->getItems($tagKeys + $keys); } catch (InvalidArgumentException $e) { @@ -216,16 +232,36 @@ class TagAwareAdapter implements TagAwareAdapterInterface, PruneableInterface, R /** * {@inheritdoc} + * + * @param string $prefix + * + * @return bool */ - public function clear() + public function clear(/* string $prefix = '' */) { - $this->deferred = []; + $prefix = 0 < \func_num_args() ? (string) func_get_arg(0) : ''; + + if ('' !== $prefix) { + foreach ($this->deferred as $key => $item) { + if (str_starts_with($key, $prefix)) { + unset($this->deferred[$key]); + } + } + } else { + $this->deferred = []; + } + + if ($this->pool instanceof AdapterInterface) { + return $this->pool->clear($prefix); + } return $this->pool->clear(); } /** * {@inheritdoc} + * + * @return bool */ public function deleteItem($key) { @@ -234,6 +270,8 @@ class TagAwareAdapter implements TagAwareAdapterInterface, PruneableInterface, R /** * {@inheritdoc} + * + * @return bool */ public function deleteItems(array $keys) { @@ -248,6 +286,8 @@ class TagAwareAdapter implements TagAwareAdapterInterface, PruneableInterface, R /** * {@inheritdoc} + * + * @return bool */ public function save(CacheItemInterface $item) { @@ -261,6 +301,8 @@ class TagAwareAdapter implements TagAwareAdapterInterface, PruneableInterface, R /** * {@inheritdoc} + * + * @return bool */ public function saveDeferred(CacheItemInterface $item) { @@ -274,12 +316,17 @@ class TagAwareAdapter implements TagAwareAdapterInterface, PruneableInterface, R /** * {@inheritdoc} + * + * @return bool */ public function commit() { return $this->invalidateTags([]); } + /** + * @return array + */ public function __sleep() { throw new \BadMethodCallException('Cannot serialize '.__CLASS__); @@ -295,7 +342,7 @@ class TagAwareAdapter implements TagAwareAdapterInterface, PruneableInterface, R $this->commit(); } - private function generateItems($items, array $tagKeys) + private function generateItems(iterable $items, array $tagKeys) { $bufferedItems = $itemTags = []; $f = $this->setCacheItemTags; @@ -321,10 +368,11 @@ class TagAwareAdapter implements TagAwareAdapterInterface, PruneableInterface, R foreach ($itemTags as $key => $tags) { foreach ($tags as $tag => $version) { - if ($tagVersions[$tag] !== $version && 1 !== $version - $tagVersions[$tag]) { - unset($itemTags[$key]); - continue 2; + if ($tagVersions[$tag] === $version || \is_int($version) && \is_int($tagVersions[$tag]) && 1 === $version - $tagVersions[$tag]) { + continue; } + unset($itemTags[$key]); + continue 2; } } $tagVersions = $tagKeys = null; @@ -363,7 +411,7 @@ class TagAwareAdapter implements TagAwareAdapterInterface, PruneableInterface, R $tags = []; foreach ($tagVersions as $tag => $version) { $tags[$tag.static::TAGS_PREFIX] = $tag; - if ($fetchTagVersions || !isset($this->knownTagVersions[$tag])) { + if ($fetchTagVersions || !isset($this->knownTagVersions[$tag]) || !\is_int($version)) { $fetchTagVersions = true; continue; } @@ -385,6 +433,10 @@ class TagAwareAdapter implements TagAwareAdapterInterface, PruneableInterface, R if (isset($invalidatedTags[$tag])) { $invalidatedTags[$tag] = $version->set(++$tagVersions[$tag]); } + if (!\is_int($tagVersions[$tag])) { + unset($this->knownTagVersions[$tag]); + continue; + } $this->knownTagVersions[$tag] = [$now, $tagVersions[$tag]]; } diff --git a/advancedcontentfilter/vendor/symfony/cache/Adapter/TraceableAdapter.php b/advancedcontentfilter/vendor/symfony/cache/Adapter/TraceableAdapter.php index cc855c13..9e65b2ef 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Adapter/TraceableAdapter.php +++ b/advancedcontentfilter/vendor/symfony/cache/Adapter/TraceableAdapter.php @@ -12,8 +12,11 @@ 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. @@ -22,7 +25,7 @@ use Symfony\Component\Cache\ResettableInterface; * @author Tobias Nyholm * @author Nicolas Grekas */ -class TraceableAdapter implements AdapterInterface, PruneableInterface, ResettableInterface +class TraceableAdapter implements AdapterInterface, CacheInterface, PruneableInterface, ResettableInterface { protected $pool; private $calls = []; @@ -32,6 +35,38 @@ class TraceableAdapter implements AdapterInterface, PruneableInterface, Resettab $this->pool = $pool; } + /** + * {@inheritdoc} + */ + public function get(string $key, callable $callback, float $beta = null, array &$metadata = null) + { + if (!$this->pool instanceof CacheInterface) { + throw new \BadMethodCallException(sprintf('Cannot call "%s::get()": this class doesn\'t implement "%s".', \get_class($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] = \is_object($value) ? \get_class($value) : \gettype($value); + } finally { + $event->end = microtime(true); + } + if ($isHit) { + ++$event->hits; + } else { + ++$event->misses; + } + + return $value; + } + /** * {@inheritdoc} */ @@ -54,6 +89,8 @@ class TraceableAdapter implements AdapterInterface, PruneableInterface, Resettab /** * {@inheritdoc} + * + * @return bool */ public function hasItem($key) { @@ -67,6 +104,8 @@ class TraceableAdapter implements AdapterInterface, PruneableInterface, Resettab /** * {@inheritdoc} + * + * @return bool */ public function deleteItem($key) { @@ -80,6 +119,8 @@ class TraceableAdapter implements AdapterInterface, PruneableInterface, Resettab /** * {@inheritdoc} + * + * @return bool */ public function save(CacheItemInterface $item) { @@ -93,6 +134,8 @@ class TraceableAdapter implements AdapterInterface, PruneableInterface, Resettab /** * {@inheritdoc} + * + * @return bool */ public function saveDeferred(CacheItemInterface $item) { @@ -132,11 +175,20 @@ class TraceableAdapter implements AdapterInterface, PruneableInterface, Resettab /** * {@inheritdoc} + * + * @param string $prefix + * + * @return bool */ - public function clear() + public function clear(/* string $prefix = '' */) { + $prefix = 0 < \func_num_args() ? (string) func_get_arg(0) : ''; $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); @@ -145,6 +197,8 @@ class TraceableAdapter implements AdapterInterface, PruneableInterface, Resettab /** * {@inheritdoc} + * + * @return bool */ public function deleteItems(array $keys) { @@ -159,6 +213,8 @@ class TraceableAdapter implements AdapterInterface, PruneableInterface, Resettab /** * {@inheritdoc} + * + * @return bool */ public function commit() { @@ -191,13 +247,26 @@ class TraceableAdapter implements AdapterInterface, PruneableInterface, Resettab */ public function reset() { - if ($this->pool instanceof ResettableInterface) { + if ($this->pool instanceof ResetInterface) { $this->pool->reset(); } $this->clearCalls(); } + /** + * {@inheritdoc} + */ + 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() { return $this->calls; diff --git a/advancedcontentfilter/vendor/symfony/cache/Adapter/TraceableTagAwareAdapter.php b/advancedcontentfilter/vendor/symfony/cache/Adapter/TraceableTagAwareAdapter.php index de68955d..69461b8b 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Adapter/TraceableTagAwareAdapter.php +++ b/advancedcontentfilter/vendor/symfony/cache/Adapter/TraceableTagAwareAdapter.php @@ -11,10 +11,12 @@ namespace Symfony\Component\Cache\Adapter; +use Symfony\Contracts\Cache\TagAwareCacheInterface; + /** * @author Robin Chalas */ -class TraceableTagAwareAdapter extends TraceableAdapter implements TagAwareAdapterInterface +class TraceableTagAwareAdapter extends TraceableAdapter implements TagAwareAdapterInterface, TagAwareCacheInterface { public function __construct(TagAwareAdapterInterface $pool) { diff --git a/advancedcontentfilter/vendor/symfony/cache/CHANGELOG.md b/advancedcontentfilter/vendor/symfony/cache/CHANGELOG.md index 11c1b936..435eaf3d 100644 --- a/advancedcontentfilter/vendor/symfony/cache/CHANGELOG.md +++ b/advancedcontentfilter/vendor/symfony/cache/CHANGELOG.md @@ -1,6 +1,43 @@ CHANGELOG ========= +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`. + +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 ----- @@ -13,7 +50,7 @@ CHANGELOG 3.3.0 ----- - * [EXPERIMENTAL] added CacheItem::getPreviousTags() to get bound tags coming from the pool storage if any + * 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) diff --git a/advancedcontentfilter/vendor/symfony/cache/CacheItem.php b/advancedcontentfilter/vendor/symfony/cache/CacheItem.php index 7ae6568c..4dd6fd7c 100644 --- a/advancedcontentfilter/vendor/symfony/cache/CacheItem.php +++ b/advancedcontentfilter/vendor/symfony/cache/CacheItem.php @@ -11,34 +11,40 @@ namespace Symfony\Component\Cache; -use Psr\Cache\CacheItemInterface; 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 CacheItemInterface +final class CacheItem implements ItemInterface { + private const METADATA_EXPIRY_OFFSET = 1527506807; + protected $key; protected $value; protected $isHit = false; protected $expiry; - protected $tags = []; - protected $prevTags = []; + protected $metadata = []; + protected $newMetadata = []; protected $innerItem; protected $poolHash; + protected $isTaggable = false; /** * {@inheritdoc} */ - public function getKey() + public function getKey(): string { return $this->key; } /** * {@inheritdoc} + * + * @return mixed */ public function get() { @@ -48,7 +54,7 @@ final class CacheItem implements CacheItemInterface /** * {@inheritdoc} */ - public function isHit() + public function isHit(): bool { return $this->isHit; } @@ -58,7 +64,7 @@ final class CacheItem implements CacheItemInterface * * @return $this */ - public function set($value) + public function set($value): self { $this->value = $value; @@ -70,12 +76,12 @@ final class CacheItem implements CacheItemInterface * * @return $this */ - public function expiresAt($expiration) + public function expiresAt($expiration): self { if (null === $expiration) { $this->expiry = null; } elseif ($expiration instanceof \DateTimeInterface) { - $this->expiry = (int) $expiration->format('U'); + $this->expiry = (float) $expiration->format('U.u'); } else { throw new InvalidArgumentException(sprintf('Expiration date must implement DateTimeInterface or be null, "%s" given.', \is_object($expiration) ? \get_class($expiration) : \gettype($expiration))); } @@ -88,14 +94,14 @@ final class CacheItem implements CacheItemInterface * * @return $this */ - public function expiresAfter($time) + public function expiresAfter($time): self { if (null === $time) { $this->expiry = null; } elseif ($time instanceof \DateInterval) { - $this->expiry = (int) \DateTime::createFromFormat('U', time())->add($time)->format('U'); + $this->expiry = microtime(true) + \DateTime::createFromFormat('U', 0)->add($time)->format('U.u'); } elseif (\is_int($time)) { - $this->expiry = $time + time(); + $this->expiry = $time + microtime(true); } else { throw new InvalidArgumentException(sprintf('Expiration date must be an integer, a DateInterval or null, "%s" given.', \is_object($time) ? \get_class($time) : \gettype($time))); } @@ -104,58 +110,64 @@ final class CacheItem implements CacheItemInterface } /** - * Adds a tag to a cache item. - * - * @param string|string[] $tags A tag or array of tags - * - * @return $this - * - * @throws InvalidArgumentException When $tag is not valid + * {@inheritdoc} */ - public function tag($tags) + public function tag($tags): ItemInterface { - if (!\is_array($tags)) { + 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_iterable($tags)) { $tags = [$tags]; } foreach ($tags as $tag) { - if (!\is_string($tag)) { - throw new InvalidArgumentException(sprintf('Cache tag must be string, "%s" given.', \is_object($tag) ? \get_class($tag) : \gettype($tag))); + if (!\is_string($tag) && !(\is_object($tag) && method_exists($tag, '__toString'))) { + throw new InvalidArgumentException(sprintf('Cache tag must be string or object that implements __toString(), "%s" given.', \is_object($tag) ? \get_class($tag) : \gettype($tag))); } - if (isset($this->tags[$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, '{}()/\@:')) { - throw new InvalidArgumentException(sprintf('Cache tag "%s" contains reserved characters {}()/\@:.', $tag)); + if (false !== strpbrk($tag, self::RESERVED_CHARACTERS)) { + throw new InvalidArgumentException(sprintf('Cache tag "%s" contains reserved characters "%s".', $tag, self::RESERVED_CHARACTERS)); } - $this->tags[$tag] = $tag; + $this->newMetadata[self::METADATA_TAGS][$tag] = $tag; } return $this; } + /** + * {@inheritdoc} + */ + public function getMetadata(): array + { + return $this->metadata; + } + /** * Returns the list of tags bound to the value coming from the pool storage if any. * - * @return array + * @deprecated since Symfony 4.2, use the "getMetadata()" method instead. */ - public function getPreviousTags() + public function getPreviousTags(): array { - return $this->prevTags; + @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.2, use the "getMetadata()" method instead.', __METHOD__), \E_USER_DEPRECATED); + + return $this->metadata[self::METADATA_TAGS] ?? []; } /** * Validates a cache key according to PSR-6. * - * @param string $key The key to validate - * - * @return string + * @param mixed $key The key to validate * * @throws InvalidArgumentException When $key is not valid */ - public static function validateKey($key) + public static function validateKey($key): string { if (!\is_string($key)) { throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', \is_object($key) ? \get_class($key) : \gettype($key))); @@ -163,8 +175,8 @@ final class CacheItem implements CacheItemInterface if ('' === $key) { throw new InvalidArgumentException('Cache key length must be greater than zero.'); } - if (false !== strpbrk($key, '{}()/\@:')) { - throw new InvalidArgumentException(sprintf('Cache key "%s" contains reserved characters {}()/\@:.', $key)); + if (false !== strpbrk($key, self::RESERVED_CHARACTERS)) { + throw new InvalidArgumentException(sprintf('Cache key "%s" contains reserved characters "%s".', $key, self::RESERVED_CHARACTERS)); } return $key; @@ -175,14 +187,14 @@ final class CacheItem implements CacheItemInterface * * @internal */ - public static function log(LoggerInterface $logger = null, $message, $context = []) + public static function log(?LoggerInterface $logger, string $message, array $context = []) { if ($logger) { $logger->warning($message, $context); } else { $replace = []; foreach ($context as $k => $v) { - if (is_scalar($v)) { + if (\is_scalar($v)) { $replace['{'.$k.'}'] = $v; } } diff --git a/advancedcontentfilter/vendor/symfony/cache/DataCollector/CacheDataCollector.php b/advancedcontentfilter/vendor/symfony/cache/DataCollector/CacheDataCollector.php index c9e87d5c..9bcd5b06 100644 --- a/advancedcontentfilter/vendor/symfony/cache/DataCollector/CacheDataCollector.php +++ b/advancedcontentfilter/vendor/symfony/cache/DataCollector/CacheDataCollector.php @@ -21,6 +21,8 @@ use Symfony\Component\HttpKernel\DataCollector\LateDataCollectorInterface; /** * @author Aaron Scherer * @author Tobias Nyholm + * + * @final since Symfony 4.4 */ class CacheDataCollector extends DataCollector implements LateDataCollectorInterface { @@ -39,8 +41,10 @@ class CacheDataCollector extends DataCollector implements LateDataCollectorInter /** * {@inheritdoc} + * + * @param \Throwable|null $exception */ - public function collect(Request $request, Response $response, \Exception $exception = null) + public function collect(Request $request, Response $response/* , \Throwable $exception = null */) { $empty = ['calls' => [], 'config' => [], 'options' => [], 'statistics' => []]; $this->data = ['instances' => $empty, 'total' => $empty]; @@ -62,7 +66,7 @@ class CacheDataCollector extends DataCollector implements LateDataCollectorInter public function lateCollect() { - $this->data = $this->cloneVar($this->data); + $this->data['instances']['calls'] = $this->cloneVar($this->data['instances']['calls']); } /** @@ -103,10 +107,7 @@ class CacheDataCollector extends DataCollector implements LateDataCollectorInter return $this->data['instances']['calls']; } - /** - * @return array - */ - private function calculateStatistics() + private function calculateStatistics(): array { $statistics = []; foreach ($this->data['instances']['calls'] as $name => $calls) { @@ -123,7 +124,15 @@ class CacheDataCollector extends DataCollector implements LateDataCollectorInter foreach ($calls as $call) { ++$statistics[$name]['calls']; $statistics[$name]['time'] += $call->end - $call->start; - if ('getItem' === $call->name) { + 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']; @@ -157,10 +166,7 @@ class CacheDataCollector extends DataCollector implements LateDataCollectorInter return $statistics; } - /** - * @return array - */ - private function calculateTotalStatistics() + private function calculateTotalStatistics(): array { $statistics = $this->getStatistics(); $totals = [ diff --git a/advancedcontentfilter/vendor/symfony/cache/DependencyInjection/CacheCollectorPass.php b/advancedcontentfilter/vendor/symfony/cache/DependencyInjection/CacheCollectorPass.php new file mode 100644 index 00000000..6bbab9da --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/DependencyInjection/CacheCollectorPass.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\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 +{ + private $dataCollectorCacheId; + private $cachePoolTag; + private $cachePoolRecorderInnerSuffix; + + public function __construct(string $dataCollectorCacheId = 'data_collector.cache', string $cachePoolTag = 'cache.pool', string $cachePoolRecorderInnerSuffix = '.recorder_inner') + { + $this->dataCollectorCacheId = $dataCollectorCacheId; + $this->cachePoolTag = $cachePoolTag; + $this->cachePoolRecorderInnerSuffix = $cachePoolRecorderInnerSuffix; + } + + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + if (!$container->hasDefinition($this->dataCollectorCacheId)) { + return; + } + + foreach ($container->findTaggedServiceIds($this->cachePoolTag) as $id => $attributes) { + $poolName = $attributes[0]['name'] ?? $id; + + $this->addToCollector($id, $poolName, $container); + } + } + + private function addToCollector(string $id, string $name, ContainerBuilder $container) + { + $definition = $container->getDefinition($id); + if ($definition->isAbstract()) { + return; + } + + $collectorDefinition = $container->getDefinition($this->dataCollectorCacheId); + $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.$this->cachePoolRecorderInnerSuffix)]); + + $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)]); + $collectorDefinition->setPublic(false); + } +} diff --git a/advancedcontentfilter/vendor/symfony/cache/DependencyInjection/CachePoolClearerPass.php b/advancedcontentfilter/vendor/symfony/cache/DependencyInjection/CachePoolClearerPass.php new file mode 100644 index 00000000..3ca89a36 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/DependencyInjection/CachePoolClearerPass.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\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; + +/** + * @author Nicolas Grekas + */ +class CachePoolClearerPass implements CompilerPassInterface +{ + private $cachePoolClearerTag; + + public function __construct(string $cachePoolClearerTag = 'cache.pool.clearer') + { + $this->cachePoolClearerTag = $cachePoolClearerTag; + } + + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + $container->getParameterBag()->remove('cache.prefix.seed'); + + foreach ($container->findTaggedServiceIds($this->cachePoolClearerTag) 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/advancedcontentfilter/vendor/symfony/cache/DependencyInjection/CachePoolPass.php b/advancedcontentfilter/vendor/symfony/cache/DependencyInjection/CachePoolPass.php new file mode 100644 index 00000000..c707ad9a --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/DependencyInjection/CachePoolPass.php @@ -0,0 +1,228 @@ + + * + * 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\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 +{ + private $cachePoolTag; + private $kernelResetTag; + private $cacheClearerId; + private $cachePoolClearerTag; + private $cacheSystemClearerId; + private $cacheSystemClearerTag; + + public function __construct(string $cachePoolTag = 'cache.pool', string $kernelResetTag = 'kernel.reset', string $cacheClearerId = 'cache.global_clearer', string $cachePoolClearerTag = 'cache.pool.clearer', string $cacheSystemClearerId = 'cache.system_clearer', string $cacheSystemClearerTag = 'kernel.cache_clearer') + { + $this->cachePoolTag = $cachePoolTag; + $this->kernelResetTag = $kernelResetTag; + $this->cacheClearerId = $cacheClearerId; + $this->cachePoolClearerTag = $cachePoolClearerTag; + $this->cacheSystemClearerId = $cacheSystemClearerId; + $this->cacheSystemClearerTag = $cacheSystemClearerTag; + } + + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + 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'); + + $allPools = []; + $clearers = []; + $attributes = [ + 'provider', + 'name', + 'namespace', + 'default_lifetime', + 'reset', + ]; + foreach ($container->findTaggedServiceIds($this->cachePoolTag) 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($this->cachePoolTag)) { + $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($this->cachePoolTag)) { + $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($this->kernelResetTag, ['method' => $tags[0][$attr]]); + } + } elseif ('namespace' !== $attr || !\in_array($class, [ArrayAdapter::class, NullAdapter::class], true)) { + $pool->replaceArgument($i++, $tags[0][$attr]); + } + unset($tags[0][$attr]); + } + if (!empty($tags[0])) { + throw new InvalidArgumentException(sprintf('Invalid "%s" tag for service "%s": accepted attributes are "clearer", "provider", "name", "namespace", "default_lifetime" and "reset", found "%s".', $this->cachePoolTag, $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); + } + + $notAliasedCacheClearerId = $this->cacheClearerId; + while ($container->hasAlias($this->cacheClearerId)) { + $this->cacheClearerId = (string) $container->getAlias($this->cacheClearerId); + } + if ($container->hasDefinition($this->cacheClearerId)) { + $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($this->cachePoolClearerTag); + + if ($this->cacheSystemClearerId === $id) { + $clearer->addTag($this->cacheSystemClearerTag); + } + } + + if ($container->hasDefinition('console.command.cache_pool_list')) { + $container->getDefinition('console.command.cache_pool_list')->replaceArgument(0, array_keys($allPools)); + } + } + + private function getNamespace(string $seed, string $id) + { + return substr(str_replace('/', '-', base64_encode(hash('sha256', $id.$seed, true))), 0, 10); + } + + /** + * @internal + */ + public static function getServiceProvider(ContainerBuilder $container, $name) + { + $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->setPublic(false); + $definition->setFactory([AbstractAdapter::class, 'createConnection']); + $definition->setArguments([$dsn, ['lazy' => true]]); + $container->setDefinition($name, $definition); + } + } + + return $name; + } +} diff --git a/advancedcontentfilter/vendor/symfony/cache/DependencyInjection/CachePoolPrunerPass.php b/advancedcontentfilter/vendor/symfony/cache/DependencyInjection/CachePoolPrunerPass.php new file mode 100644 index 00000000..e5699623 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/DependencyInjection/CachePoolPrunerPass.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\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 +{ + private $cacheCommandServiceId; + private $cachePoolTag; + + public function __construct(string $cacheCommandServiceId = 'console.command.cache_pool_prune', string $cachePoolTag = 'cache.pool') + { + $this->cacheCommandServiceId = $cacheCommandServiceId; + $this->cachePoolTag = $cachePoolTag; + } + + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + if (!$container->hasDefinition($this->cacheCommandServiceId)) { + return; + } + + $services = []; + + foreach ($container->findTaggedServiceIds($this->cachePoolTag) 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($this->cacheCommandServiceId)->replaceArgument(0, new IteratorArgument($services)); + } +} diff --git a/advancedcontentfilter/vendor/symfony/cache/DoctrineProvider.php b/advancedcontentfilter/vendor/symfony/cache/DoctrineProvider.php index 4c5cd0cb..f6ac5745 100644 --- a/advancedcontentfilter/vendor/symfony/cache/DoctrineProvider.php +++ b/advancedcontentfilter/vendor/symfony/cache/DoctrineProvider.php @@ -13,6 +13,11 @@ namespace Symfony\Component\Cache; use Doctrine\Common\Cache\CacheProvider; use Psr\Cache\CacheItemPoolInterface; +use Symfony\Contracts\Service\ResetInterface; + +if (!class_exists(CacheProvider::class)) { + return; +} /** * @author Nicolas Grekas @@ -39,7 +44,7 @@ class DoctrineProvider extends CacheProvider implements PruneableInterface, Rese */ public function reset() { - if ($this->pool instanceof ResettableInterface) { + if ($this->pool instanceof ResetInterface) { $this->pool->reset(); } $this->setNamespace($this->getNamespace()); @@ -47,6 +52,8 @@ class DoctrineProvider extends CacheProvider implements PruneableInterface, Rese /** * {@inheritdoc} + * + * @return mixed */ protected function doFetch($id) { @@ -57,6 +64,8 @@ class DoctrineProvider extends CacheProvider implements PruneableInterface, Rese /** * {@inheritdoc} + * + * @return bool */ protected function doContains($id) { @@ -65,6 +74,8 @@ class DoctrineProvider extends CacheProvider implements PruneableInterface, Rese /** * {@inheritdoc} + * + * @return bool */ protected function doSave($id, $data, $lifeTime = 0) { @@ -79,6 +90,8 @@ class DoctrineProvider extends CacheProvider implements PruneableInterface, Rese /** * {@inheritdoc} + * + * @return bool */ protected function doDelete($id) { @@ -87,6 +100,8 @@ class DoctrineProvider extends CacheProvider implements PruneableInterface, Rese /** * {@inheritdoc} + * + * @return bool */ protected function doFlush() { @@ -95,6 +110,8 @@ class DoctrineProvider extends CacheProvider implements PruneableInterface, Rese /** * {@inheritdoc} + * + * @return array|null */ protected function doGetStats() { diff --git a/advancedcontentfilter/vendor/symfony/cache/Exception/CacheException.php b/advancedcontentfilter/vendor/symfony/cache/Exception/CacheException.php index e87b2db8..d2e975b2 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Exception/CacheException.php +++ b/advancedcontentfilter/vendor/symfony/cache/Exception/CacheException.php @@ -14,6 +14,12 @@ namespace Symfony\Component\Cache\Exception; use Psr\Cache\CacheException as Psr6CacheInterface; use Psr\SimpleCache\CacheException as SimpleCacheInterface; -class CacheException extends \Exception implements Psr6CacheInterface, SimpleCacheInterface -{ +if (interface_exists(SimpleCacheInterface::class)) { + class CacheException extends \Exception implements Psr6CacheInterface, SimpleCacheInterface + { + } +} else { + class CacheException extends \Exception implements Psr6CacheInterface + { + } } diff --git a/advancedcontentfilter/vendor/symfony/cache/Exception/InvalidArgumentException.php b/advancedcontentfilter/vendor/symfony/cache/Exception/InvalidArgumentException.php index 828bf3ed..7f9584a2 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Exception/InvalidArgumentException.php +++ b/advancedcontentfilter/vendor/symfony/cache/Exception/InvalidArgumentException.php @@ -14,6 +14,12 @@ namespace Symfony\Component\Cache\Exception; use Psr\Cache\InvalidArgumentException as Psr6CacheInterface; use Psr\SimpleCache\InvalidArgumentException as SimpleCacheInterface; -class InvalidArgumentException extends \InvalidArgumentException implements Psr6CacheInterface, SimpleCacheInterface -{ +if (interface_exists(SimpleCacheInterface::class)) { + class InvalidArgumentException extends \InvalidArgumentException implements Psr6CacheInterface, SimpleCacheInterface + { + } +} else { + class InvalidArgumentException extends \InvalidArgumentException implements Psr6CacheInterface + { + } } diff --git a/advancedcontentfilter/vendor/symfony/cache/Exception/LogicException.php b/advancedcontentfilter/vendor/symfony/cache/Exception/LogicException.php new file mode 100644 index 00000000..9ffa7ed6 --- /dev/null +++ b/advancedcontentfilter/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/advancedcontentfilter/vendor/symfony/cache/LICENSE b/advancedcontentfilter/vendor/symfony/cache/LICENSE index a7ec7080..7fa95390 100644 --- a/advancedcontentfilter/vendor/symfony/cache/LICENSE +++ b/advancedcontentfilter/vendor/symfony/cache/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2016-2020 Fabien Potencier +Copyright (c) 2016-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/advancedcontentfilter/vendor/symfony/cache/LockRegistry.php b/advancedcontentfilter/vendor/symfony/cache/LockRegistry.php new file mode 100644 index 00000000..26574f10 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/LockRegistry.php @@ -0,0 +1,161 @@ + + * + * 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 $openedFiles = []; + private static $lockedFiles; + private static $signalingException; + private static $signalingCallback; + + /** + * The number of items in this list controls the max number of concurrent processes. + */ + private static $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.'DoctrineAdapter.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.'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.'SimpleCacheAdapter.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) + { + 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 ?? self::$signalingException = unserialize("O:9:\"Exception\":1:{s:16:\"\0Exception\0trace\";a:0:{}}"); + self::$signalingCallback ?? self::$signalingCallback = function () { 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 && $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 && $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 && $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 && $logger->info('Item "{key}" not found while lock was released, now retrying', ['key' => $item->getKey()]); + } + } + + return null; + } + + private static function open(int $key) + { + if (null !== $h = self::$openedFiles[$key] ?? null) { + return $h; + } + set_error_handler(function () {}); + try { + $h = fopen(self::$files[$key], 'r+'); + } finally { + restore_error_handler(); + } + + return self::$openedFiles[$key] = $h ?: @fopen(self::$files[$key], 'r'); + } +} diff --git a/advancedcontentfilter/vendor/symfony/cache/Marshaller/DefaultMarshaller.php b/advancedcontentfilter/vendor/symfony/cache/Marshaller/DefaultMarshaller.php new file mode 100644 index 00000000..7493a2ef --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Marshaller/DefaultMarshaller.php @@ -0,0 +1,99 @@ + + * + * 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 $useIgbinarySerialize = true; + + public function __construct(bool $useIgbinarySerialize = null) + { + if (null === $useIgbinarySerialize) { + $useIgbinarySerialize = \extension_loaded('igbinary') && (\PHP_VERSION_ID < 70400 || version_compare('3.1.6', phpversion('igbinary'), '<=')); + } elseif ($useIgbinarySerialize && (!\extension_loaded('igbinary') || (\PHP_VERSION_ID >= 70400 && version_compare('3.1.6', phpversion('igbinary'), '>')))) { + throw new CacheException(\extension_loaded('igbinary') && \PHP_VERSION_ID >= 70400 ? 'Please upgrade the "igbinary" PHP extension to v3.1.6 or higher.' : 'The "igbinary" PHP extension is not loaded.'); + } + $this->useIgbinarySerialize = $useIgbinarySerialize; + } + + /** + * {@inheritdoc} + */ + 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) { + $failed[] = $id; + } + } + + return $serialized; + } + + /** + * {@inheritdoc} + */ + public function unmarshall(string $value) + { + if ('b:0;' === $value) { + return false; + } + if ('N;' === $value) { + return null; + } + static $igbinaryNull; + if ($value === ($igbinaryNull ?? $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($class) + { + throw new \DomainException('Class not found: '.$class); + } +} diff --git a/advancedcontentfilter/vendor/symfony/cache/Marshaller/DeflateMarshaller.php b/advancedcontentfilter/vendor/symfony/cache/Marshaller/DeflateMarshaller.php new file mode 100644 index 00000000..55448061 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Marshaller/DeflateMarshaller.php @@ -0,0 +1,53 @@ + + * + * 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 +{ + private $marshaller; + + public function __construct(MarshallerInterface $marshaller) + { + if (!\function_exists('gzdeflate')) { + throw new CacheException('The "zlib" PHP extension is not loaded.'); + } + + $this->marshaller = $marshaller; + } + + /** + * {@inheritdoc} + */ + public function marshall(array $values, ?array &$failed): array + { + return array_map('gzdeflate', $this->marshaller->marshall($values, $failed)); + } + + /** + * {@inheritdoc} + */ + public function unmarshall(string $value) + { + if (false !== $inflatedValue = @gzinflate($value)) { + $value = $inflatedValue; + } + + return $this->marshaller->unmarshall($value); + } +} diff --git a/advancedcontentfilter/vendor/symfony/cache/Marshaller/MarshallerInterface.php b/advancedcontentfilter/vendor/symfony/cache/Marshaller/MarshallerInterface.php new file mode 100644 index 00000000..cdd6c402 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Marshaller/MarshallerInterface.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\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. + * + * @return mixed + * + * @throws \Exception Whenever unserialization fails + */ + public function unmarshall(string $value); +} diff --git a/advancedcontentfilter/vendor/symfony/cache/Marshaller/TagAwareMarshaller.php b/advancedcontentfilter/vendor/symfony/cache/Marshaller/TagAwareMarshaller.php new file mode 100644 index 00000000..5d1e303b --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Marshaller/TagAwareMarshaller.php @@ -0,0 +1,89 @@ + + * + * 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 $marshaller; + + public function __construct(MarshallerInterface $marshaller = null) + { + $this->marshaller = $marshaller ?? new DefaultMarshaller(); + } + + /** + * {@inheritdoc} + */ + 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 arbitratry 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; + } + + /** + * {@inheritdoc} + */ + public function unmarshall(string $value) + { + // 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/advancedcontentfilter/vendor/symfony/cache/Psr16Cache.php b/advancedcontentfilter/vendor/symfony/cache/Psr16Cache.php new file mode 100644 index 00000000..ac265a57 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Psr16Cache.php @@ -0,0 +1,284 @@ + + * + * 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; + +if (null !== (new \ReflectionMethod(CacheInterface::class, 'get'))->getReturnType()) { + throw new \LogicException('psr/simple-cache 3.0+ is not compatible with this version of symfony/cache. Please upgrade symfony/cache to 6.0+ or downgrade psr/simple-cache to 1.x or 2.x.'); +} + +/** + * Turns a PSR-6 cache into a PSR-16 one. + * + * @author Nicolas Grekas + */ +class Psr16Cache implements CacheInterface, PruneableInterface, ResettableInterface +{ + use ProxyTrait; + + private const METADATA_EXPIRY_OFFSET = 1527506807; + + private $createCacheItem; + private $cacheItemPrototype; + + 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; + $item->key = $allowInt && \is_int($key) ? (string) $key : CacheItem::validateKey($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); + }; + } + + /** + * {@inheritdoc} + * + * @return mixed + */ + public function get($key, $default = null) + { + 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; + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function set($key, $value, $ttl = null) + { + 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); + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function delete($key) + { + try { + return $this->pool->deleteItem($key); + } catch (SimpleCacheException $e) { + throw $e; + } catch (Psr6CacheException $e) { + throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e); + } + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function clear() + { + return $this->pool->clear(); + } + + /** + * {@inheritdoc} + * + * @return iterable + */ + public function getMultiple($keys, $default = null) + { + 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.', \is_object($keys) ? \get_class($keys) : \gettype($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) { + if (!$item->isHit()) { + $values[$key] = $default; + continue; + } + $values[$key] = $item->get(); + + if (!$metadata = $item->getMetadata()) { + continue; + } + unset($metadata[CacheItem::METADATA_TAGS]); + + if ($metadata) { + $values[$key] = ["\x9D".pack('VN', (int) (0.1 + $metadata[CacheItem::METADATA_EXPIRY] - self::METADATA_EXPIRY_OFFSET), $metadata[CacheItem::METADATA_CTIME])."\x5F" => $values[$key]]; + } + } + + return $values; + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function setMultiple($values, $ttl = null) + { + $valuesIsArray = \is_array($values); + if (!$valuesIsArray && !$values instanceof \Traversable) { + throw new InvalidArgumentException(sprintf('Cache values must be array or Traversable, "%s" given.', \is_object($values) ? \get_class($values) : \gettype($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; + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function deleteMultiple($keys) + { + 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.', \is_object($keys) ? \get_class($keys) : \gettype($keys))); + } + + try { + return $this->pool->deleteItems($keys); + } catch (SimpleCacheException $e) { + throw $e; + } catch (Psr6CacheException $e) { + throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e); + } + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function has($key) + { + 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/advancedcontentfilter/vendor/symfony/cache/README.md b/advancedcontentfilter/vendor/symfony/cache/README.md index c4ab7520..c466d578 100644 --- a/advancedcontentfilter/vendor/symfony/cache/README.md +++ b/advancedcontentfilter/vendor/symfony/cache/README.md @@ -1,18 +1,19 @@ Symfony PSR-6 implementation for caching ======================================== -This component provides an extended [PSR-6](http://www.php-fig.org/psr/psr-6/) -implementation for adding cache to your applications. It is designed to have a -low overhead so that caching is fastest. It ships with a few caching adapters -for the most widespread and suited to caching backends. It also provides a -`doctrine/cache` proxy adapter to cover more advanced caching needs and a proxy -adapter for greater interoperability between PSR-6 implementations. +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) + * [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/advancedcontentfilter/vendor/symfony/cache/ResettableInterface.php b/advancedcontentfilter/vendor/symfony/cache/ResettableInterface.php index 6be72861..7b0a853f 100644 --- a/advancedcontentfilter/vendor/symfony/cache/ResettableInterface.php +++ b/advancedcontentfilter/vendor/symfony/cache/ResettableInterface.php @@ -11,10 +11,11 @@ namespace Symfony\Component\Cache; +use Symfony\Contracts\Service\ResetInterface; + /** * Resets a pool's local state. */ -interface ResettableInterface +interface ResettableInterface extends ResetInterface { - public function reset(); } diff --git a/advancedcontentfilter/vendor/symfony/cache/Simple/AbstractCache.php b/advancedcontentfilter/vendor/symfony/cache/Simple/AbstractCache.php index baedb737..c3d8b38c 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Simple/AbstractCache.php +++ b/advancedcontentfilter/vendor/symfony/cache/Simple/AbstractCache.php @@ -12,37 +12,37 @@ namespace Symfony\Component\Cache\Simple; use Psr\Log\LoggerAwareInterface; -use Psr\SimpleCache\CacheInterface; +use Psr\SimpleCache\CacheInterface as Psr16CacheInterface; +use Symfony\Component\Cache\Adapter\AbstractAdapter; use Symfony\Component\Cache\CacheItem; use Symfony\Component\Cache\Exception\InvalidArgumentException; use Symfony\Component\Cache\ResettableInterface; use Symfony\Component\Cache\Traits\AbstractTrait; +use Symfony\Contracts\Cache\CacheInterface; + +@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.3, use "%s" and type-hint for "%s" instead.', AbstractCache::class, AbstractAdapter::class, CacheInterface::class), \E_USER_DEPRECATED); /** - * @author Nicolas Grekas + * @deprecated since Symfony 4.3, use AbstractAdapter and type-hint for CacheInterface instead. */ -abstract class AbstractCache implements CacheInterface, LoggerAwareInterface, ResettableInterface +abstract class AbstractCache implements Psr16CacheInterface, LoggerAwareInterface, ResettableInterface { - /** - * @internal - */ - const NS_SEPARATOR = ':'; - use AbstractTrait { deleteItems as private; AbstractTrait::deleteItem as delete; AbstractTrait::hasItem as has; } + /** + * @internal + */ + protected const NS_SEPARATOR = ':'; + private $defaultLifetime; - /** - * @param string $namespace - * @param int $defaultLifetime - */ - protected function __construct($namespace = '', $defaultLifetime = 0) + protected function __construct(string $namespace = '', int $defaultLifetime = 0) { - $this->defaultLifetime = max(0, (int) $defaultLifetime); + $this->defaultLifetime = max(0, $defaultLifetime); $this->namespace = '' === $namespace ? '' : CacheItem::validateKey($namespace).':'; 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)); @@ -61,7 +61,7 @@ abstract class AbstractCache implements CacheInterface, LoggerAwareInterface, Re return $value; } } catch (\Exception $e) { - CacheItem::log($this->logger, 'Failed to fetch key "{key}"', ['key' => $key, 'exception' => $e]); + CacheItem::log($this->logger, 'Failed to fetch key "{key}": '.$e->getMessage(), ['key' => $key, 'exception' => $e]); } return $default; @@ -69,6 +69,8 @@ abstract class AbstractCache implements CacheInterface, LoggerAwareInterface, Re /** * {@inheritdoc} + * + * @return bool */ public function set($key, $value, $ttl = null) { @@ -79,6 +81,8 @@ abstract class AbstractCache implements CacheInterface, LoggerAwareInterface, Re /** * {@inheritdoc} + * + * @return iterable */ public function getMultiple($keys, $default = null) { @@ -95,7 +99,7 @@ abstract class AbstractCache implements CacheInterface, LoggerAwareInterface, Re try { $values = $this->doFetch($ids); } catch (\Exception $e) { - CacheItem::log($this->logger, 'Failed to fetch requested values', ['keys' => $keys, 'exception' => $e]); + CacheItem::log($this->logger, 'Failed to fetch values: '.$e->getMessage(), ['keys' => $keys, 'exception' => $e]); $values = []; } $ids = array_combine($ids, $keys); @@ -105,6 +109,8 @@ abstract class AbstractCache implements CacheInterface, LoggerAwareInterface, Re /** * {@inheritdoc} + * + * @return bool */ public function setMultiple($values, $ttl = null) { @@ -134,13 +140,16 @@ abstract class AbstractCache implements CacheInterface, LoggerAwareInterface, Re foreach (\is_array($e) ? $e : array_keys($valuesById) as $id) { $keys[] = substr($id, \strlen($this->namespace)); } - CacheItem::log($this->logger, 'Failed to save values', ['keys' => $keys, 'exception' => $e instanceof \Exception ? $e : null]); + $message = 'Failed to save values'.($e instanceof \Exception ? ': '.$e->getMessage() : '.'); + CacheItem::log($this->logger, $message, ['keys' => $keys, 'exception' => $e instanceof \Exception ? $e : null]); return false; } /** * {@inheritdoc} + * + * @return bool */ public function deleteMultiple($keys) { @@ -168,19 +177,19 @@ abstract class AbstractCache implements CacheInterface, LoggerAwareInterface, Re throw new InvalidArgumentException(sprintf('Expiration date must be an integer, a DateInterval or null, "%s" given.', \is_object($ttl) ? \get_class($ttl) : \gettype($ttl))); } - private function generateValues($values, &$keys, $default) + private function generateValues(iterable $values, array &$keys, $default): iterable { try { foreach ($values as $id => $value) { if (!isset($keys[$id])) { - $id = key($keys); + throw new InvalidArgumentException(sprintf('Could not match value id "%s" to keys "%s".', $id, implode('", "', $keys))); } $key = $keys[$id]; unset($keys[$id]); yield $key => $value; } } catch (\Exception $e) { - CacheItem::log($this->logger, 'Failed to fetch requested values', ['keys' => array_values($keys), 'exception' => $e]); + CacheItem::log($this->logger, 'Failed to fetch values: '.$e->getMessage(), ['keys' => array_values($keys), 'exception' => $e]); } foreach ($keys as $key) { diff --git a/advancedcontentfilter/vendor/symfony/cache/Simple/ApcuCache.php b/advancedcontentfilter/vendor/symfony/cache/Simple/ApcuCache.php index e583b443..bef89e27 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Simple/ApcuCache.php +++ b/advancedcontentfilter/vendor/symfony/cache/Simple/ApcuCache.php @@ -11,18 +11,20 @@ namespace Symfony\Component\Cache\Simple; +use Symfony\Component\Cache\Adapter\ApcuAdapter; use Symfony\Component\Cache\Traits\ApcuTrait; +use Symfony\Contracts\Cache\CacheInterface; +@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.3, use "%s" and type-hint for "%s" instead.', ApcuCache::class, ApcuAdapter::class, CacheInterface::class), \E_USER_DEPRECATED); + +/** + * @deprecated since Symfony 4.3, use ApcuAdapter and type-hint for CacheInterface instead. + */ class ApcuCache extends AbstractCache { use ApcuTrait; - /** - * @param string $namespace - * @param int $defaultLifetime - * @param string|null $version - */ - public function __construct($namespace = '', $defaultLifetime = 0, $version = null) + public function __construct(string $namespace = '', int $defaultLifetime = 0, string $version = null) { $this->init($namespace, $defaultLifetime, $version); } diff --git a/advancedcontentfilter/vendor/symfony/cache/Simple/ArrayCache.php b/advancedcontentfilter/vendor/symfony/cache/Simple/ArrayCache.php index 6013f0ad..469edf1c 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Simple/ArrayCache.php +++ b/advancedcontentfilter/vendor/symfony/cache/Simple/ArrayCache.php @@ -12,16 +12,20 @@ namespace Symfony\Component\Cache\Simple; use Psr\Log\LoggerAwareInterface; -use Psr\SimpleCache\CacheInterface; +use Psr\SimpleCache\CacheInterface as Psr16CacheInterface; +use Symfony\Component\Cache\Adapter\ArrayAdapter; use Symfony\Component\Cache\CacheItem; use Symfony\Component\Cache\Exception\InvalidArgumentException; use Symfony\Component\Cache\ResettableInterface; use Symfony\Component\Cache\Traits\ArrayTrait; +use Symfony\Contracts\Cache\CacheInterface; + +@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.3, use "%s" and type-hint for "%s" instead.', ArrayCache::class, ArrayAdapter::class, CacheInterface::class), \E_USER_DEPRECATED); /** - * @author Nicolas Grekas + * @deprecated since Symfony 4.3, use ArrayAdapter and type-hint for CacheInterface instead. */ -class ArrayCache implements CacheInterface, LoggerAwareInterface, ResettableInterface +class ArrayCache implements Psr16CacheInterface, LoggerAwareInterface, ResettableInterface { use ArrayTrait { ArrayTrait::deleteItem as delete; @@ -31,12 +35,11 @@ class ArrayCache implements CacheInterface, LoggerAwareInterface, ResettableInte private $defaultLifetime; /** - * @param int $defaultLifetime * @param bool $storeSerialized Disabling serialization can lead to cache corruptions when storing mutable values but increases performance otherwise */ - public function __construct($defaultLifetime = 0, $storeSerialized = true) + public function __construct(int $defaultLifetime = 0, bool $storeSerialized = true) { - $this->defaultLifetime = (int) $defaultLifetime; + $this->defaultLifetime = $defaultLifetime; $this->storeSerialized = $storeSerialized; } @@ -45,13 +48,26 @@ class ArrayCache implements CacheInterface, LoggerAwareInterface, ResettableInte */ public function get($key, $default = null) { - foreach ($this->getMultiple([$key], $default) as $v) { - return $v; + if (!\is_string($key) || !isset($this->expiries[$key])) { + CacheItem::validateKey($key); } + if (!$isHit = isset($this->expiries[$key]) && ($this->expiries[$key] > microtime(true) || !$this->delete($key))) { + $this->values[$key] = null; + + return $default; + } + if (!$this->storeSerialized) { + return $this->values[$key]; + } + $value = $this->unfreeze($key, $isHit); + + return $isHit ? $value : $default; } /** * {@inheritdoc} + * + * @return iterable */ public function getMultiple($keys, $default = null) { @@ -61,14 +77,18 @@ class ArrayCache implements CacheInterface, LoggerAwareInterface, ResettableInte throw new InvalidArgumentException(sprintf('Cache keys must be array or Traversable, "%s" given.', \is_object($keys) ? \get_class($keys) : \gettype($keys))); } foreach ($keys as $key) { - CacheItem::validateKey($key); + if (!\is_string($key) || !isset($this->expiries[$key])) { + CacheItem::validateKey($key); + } } - return $this->generateItems($keys, time(), function ($k, $v, $hit) use ($default) { return $hit ? $v : $default; }); + return $this->generateItems($keys, microtime(true), function ($k, $v, $hit) use ($default) { return $hit ? $v : $default; }); } /** * {@inheritdoc} + * + * @return bool */ public function deleteMultiple($keys) { @@ -84,16 +104,22 @@ class ArrayCache implements CacheInterface, LoggerAwareInterface, ResettableInte /** * {@inheritdoc} + * + * @return bool */ public function set($key, $value, $ttl = null) { - CacheItem::validateKey($key); + if (!\is_string($key)) { + CacheItem::validateKey($key); + } return $this->setMultiple([$key => $value], $ttl); } /** * {@inheritdoc} + * + * @return bool */ public function setMultiple($values, $ttl = null) { @@ -103,27 +129,20 @@ class ArrayCache implements CacheInterface, LoggerAwareInterface, ResettableInte $valuesArray = []; foreach ($values as $key => $value) { - \is_int($key) || CacheItem::validateKey($key); + if (!\is_int($key) && !(\is_string($key) && isset($this->expiries[$key]))) { + CacheItem::validateKey($key); + } $valuesArray[$key] = $value; } if (false === $ttl = $this->normalizeTtl($ttl)) { return $this->deleteMultiple(array_keys($valuesArray)); } - if ($this->storeSerialized) { - foreach ($valuesArray as $key => $value) { - try { - $valuesArray[$key] = serialize($value); - } catch (\Exception $e) { - $type = \is_object($value) ? \get_class($value) : \gettype($value); - CacheItem::log($this->logger, 'Failed to save key "{key}" ({type})', ['key' => $key, 'type' => $type, 'exception' => $e]); - - return false; - } - } - } - $expiry = 0 < $ttl ? time() + $ttl : \PHP_INT_MAX; + $expiry = 0 < $ttl ? microtime(true) + $ttl : \PHP_INT_MAX; foreach ($valuesArray as $key => $value) { + if ($this->storeSerialized && null === $value = $this->freeze($value, $key)) { + return false; + } $this->values[$key] = $value; $this->expiries[$key] = $expiry; } diff --git a/advancedcontentfilter/vendor/symfony/cache/Simple/ChainCache.php b/advancedcontentfilter/vendor/symfony/cache/Simple/ChainCache.php index 2e6c7277..bae95072 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Simple/ChainCache.php +++ b/advancedcontentfilter/vendor/symfony/cache/Simple/ChainCache.php @@ -11,10 +11,15 @@ namespace Symfony\Component\Cache\Simple; -use Psr\SimpleCache\CacheInterface; +use Psr\SimpleCache\CacheInterface as Psr16CacheInterface; +use Symfony\Component\Cache\Adapter\ChainAdapter; use Symfony\Component\Cache\Exception\InvalidArgumentException; use Symfony\Component\Cache\PruneableInterface; use Symfony\Component\Cache\ResettableInterface; +use Symfony\Contracts\Cache\CacheInterface; +use Symfony\Contracts\Service\ResetInterface; + +@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.3, use "%s" and type-hint for "%s" instead.', ChainCache::class, ChainAdapter::class, CacheInterface::class), \E_USER_DEPRECATED); /** * Chains several caches together. @@ -22,9 +27,9 @@ use Symfony\Component\Cache\ResettableInterface; * Cached items are fetched from the first cache having them in its data store. * They are saved and deleted in all caches at once. * - * @author Nicolas Grekas + * @deprecated since Symfony 4.3, use ChainAdapter and type-hint for CacheInterface instead. */ -class ChainCache implements CacheInterface, PruneableInterface, ResettableInterface +class ChainCache implements Psr16CacheInterface, PruneableInterface, ResettableInterface { private $miss; private $caches = []; @@ -32,25 +37,25 @@ class ChainCache implements CacheInterface, PruneableInterface, ResettableInterf private $cacheCount; /** - * @param CacheInterface[] $caches The ordered list of caches used to fetch cached items - * @param int $defaultLifetime The lifetime of items propagated from lower caches to upper ones + * @param Psr16CacheInterface[] $caches The ordered list of caches used to fetch cached items + * @param int $defaultLifetime The lifetime of items propagated from lower caches to upper ones */ - public function __construct(array $caches, $defaultLifetime = 0) + public function __construct(array $caches, int $defaultLifetime = 0) { if (!$caches) { throw new InvalidArgumentException('At least one cache must be specified.'); } foreach ($caches as $cache) { - if (!$cache instanceof CacheInterface) { - throw new InvalidArgumentException(sprintf('The class "%s" does not implement the "%s" interface.', \get_class($cache), CacheInterface::class)); + if (!$cache instanceof Psr16CacheInterface) { + throw new InvalidArgumentException(sprintf('The class "%s" does not implement the "%s" interface.', \get_class($cache), Psr16CacheInterface::class)); } } $this->miss = new \stdClass(); $this->caches = array_values($caches); $this->cacheCount = \count($this->caches); - $this->defaultLifetime = 0 < $defaultLifetime ? (int) $defaultLifetime : null; + $this->defaultLifetime = 0 < $defaultLifetime ? $defaultLifetime : null; } /** @@ -77,6 +82,8 @@ class ChainCache implements CacheInterface, PruneableInterface, ResettableInterf /** * {@inheritdoc} + * + * @return iterable */ public function getMultiple($keys, $default = null) { @@ -85,11 +92,11 @@ class ChainCache implements CacheInterface, PruneableInterface, ResettableInterf return $this->generateItems($this->caches[0]->getMultiple($keys, $miss), 0, $miss, $default); } - private function generateItems($values, $cacheIndex, $miss, $default) + private function generateItems(iterable $values, int $cacheIndex, $miss, $default): iterable { $missing = []; $nextCacheIndex = $cacheIndex + 1; - $nextCache = isset($this->caches[$nextCacheIndex]) ? $this->caches[$nextCacheIndex] : null; + $nextCache = $this->caches[$nextCacheIndex] ?? null; foreach ($values as $k => $value) { if ($miss !== $value) { @@ -118,6 +125,8 @@ class ChainCache implements CacheInterface, PruneableInterface, ResettableInterf /** * {@inheritdoc} + * + * @return bool */ public function has($key) { @@ -132,6 +141,8 @@ class ChainCache implements CacheInterface, PruneableInterface, ResettableInterf /** * {@inheritdoc} + * + * @return bool */ public function clear() { @@ -147,6 +158,8 @@ class ChainCache implements CacheInterface, PruneableInterface, ResettableInterf /** * {@inheritdoc} + * + * @return bool */ public function delete($key) { @@ -162,6 +175,8 @@ class ChainCache implements CacheInterface, PruneableInterface, ResettableInterf /** * {@inheritdoc} + * + * @return bool */ public function deleteMultiple($keys) { @@ -180,6 +195,8 @@ class ChainCache implements CacheInterface, PruneableInterface, ResettableInterf /** * {@inheritdoc} + * + * @return bool */ public function set($key, $value, $ttl = null) { @@ -195,6 +212,8 @@ class ChainCache implements CacheInterface, PruneableInterface, ResettableInterf /** * {@inheritdoc} + * + * @return bool */ public function setMultiple($values, $ttl = null) { @@ -244,7 +263,7 @@ class ChainCache implements CacheInterface, PruneableInterface, ResettableInterf public function reset() { foreach ($this->caches as $cache) { - if ($cache instanceof ResettableInterface) { + if ($cache instanceof ResetInterface) { $cache->reset(); } } diff --git a/advancedcontentfilter/vendor/symfony/cache/Simple/DoctrineCache.php b/advancedcontentfilter/vendor/symfony/cache/Simple/DoctrineCache.php index ea1a4eda..d7feb4d3 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Simple/DoctrineCache.php +++ b/advancedcontentfilter/vendor/symfony/cache/Simple/DoctrineCache.php @@ -12,17 +12,20 @@ namespace Symfony\Component\Cache\Simple; use Doctrine\Common\Cache\CacheProvider; +use Symfony\Component\Cache\Adapter\DoctrineAdapter; use Symfony\Component\Cache\Traits\DoctrineTrait; +use Symfony\Contracts\Cache\CacheInterface; +@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.3, use "%s" and type-hint for "%s" instead.', DoctrineCache::class, DoctrineAdapter::class, CacheInterface::class), \E_USER_DEPRECATED); + +/** + * @deprecated since Symfony 4.3, use DoctrineAdapter and type-hint for CacheInterface instead. + */ class DoctrineCache extends AbstractCache { use DoctrineTrait; - /** - * @param string $namespace - * @param int $defaultLifetime - */ - public function __construct(CacheProvider $provider, $namespace = '', $defaultLifetime = 0) + public function __construct(CacheProvider $provider, string $namespace = '', int $defaultLifetime = 0) { parent::__construct('', $defaultLifetime); $this->provider = $provider; diff --git a/advancedcontentfilter/vendor/symfony/cache/Simple/FilesystemCache.php b/advancedcontentfilter/vendor/symfony/cache/Simple/FilesystemCache.php index ccd57953..fcc8a170 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Simple/FilesystemCache.php +++ b/advancedcontentfilter/vendor/symfony/cache/Simple/FilesystemCache.php @@ -11,20 +11,25 @@ namespace Symfony\Component\Cache\Simple; +use Symfony\Component\Cache\Adapter\FilesystemAdapter; +use Symfony\Component\Cache\Marshaller\DefaultMarshaller; +use Symfony\Component\Cache\Marshaller\MarshallerInterface; use Symfony\Component\Cache\PruneableInterface; use Symfony\Component\Cache\Traits\FilesystemTrait; +use Symfony\Contracts\Cache\CacheInterface; +@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.3, use "%s" and type-hint for "%s" instead.', FilesystemCache::class, FilesystemAdapter::class, CacheInterface::class), \E_USER_DEPRECATED); + +/** + * @deprecated since Symfony 4.3, use FilesystemAdapter and type-hint for CacheInterface instead. + */ class FilesystemCache extends AbstractCache implements PruneableInterface { use FilesystemTrait; - /** - * @param string $namespace - * @param int $defaultLifetime - * @param string|null $directory - */ - public function __construct($namespace = '', $defaultLifetime = 0, $directory = null) + 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/advancedcontentfilter/vendor/symfony/cache/Simple/MemcachedCache.php b/advancedcontentfilter/vendor/symfony/cache/Simple/MemcachedCache.php index 94a9f297..1f636486 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Simple/MemcachedCache.php +++ b/advancedcontentfilter/vendor/symfony/cache/Simple/MemcachedCache.php @@ -11,20 +11,24 @@ namespace Symfony\Component\Cache\Simple; +use Symfony\Component\Cache\Adapter\MemcachedAdapter; +use Symfony\Component\Cache\Marshaller\MarshallerInterface; use Symfony\Component\Cache\Traits\MemcachedTrait; +use Symfony\Contracts\Cache\CacheInterface; +@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.3, use "%s" and type-hint for "%s" instead.', MemcachedCache::class, MemcachedAdapter::class, CacheInterface::class), \E_USER_DEPRECATED); + +/** + * @deprecated since Symfony 4.3, use MemcachedAdapter and type-hint for CacheInterface instead. + */ class MemcachedCache extends AbstractCache { use MemcachedTrait; protected $maxIdLength = 250; - /** - * @param string $namespace - * @param int $defaultLifetime - */ - public function __construct(\Memcached $client, $namespace = '', $defaultLifetime = 0) + public function __construct(\Memcached $client, string $namespace = '', int $defaultLifetime = 0, MarshallerInterface $marshaller = null) { - $this->init($client, $namespace, $defaultLifetime); + $this->init($client, $namespace, $defaultLifetime, $marshaller); } } diff --git a/advancedcontentfilter/vendor/symfony/cache/Simple/NullCache.php b/advancedcontentfilter/vendor/symfony/cache/Simple/NullCache.php index fa986aeb..fcbd39d5 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Simple/NullCache.php +++ b/advancedcontentfilter/vendor/symfony/cache/Simple/NullCache.php @@ -11,12 +11,16 @@ namespace Symfony\Component\Cache\Simple; -use Psr\SimpleCache\CacheInterface; +use Psr\SimpleCache\CacheInterface as Psr16CacheInterface; +use Symfony\Component\Cache\Adapter\NullAdapter; +use Symfony\Contracts\Cache\CacheInterface; + +@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.3, use "%s" and type-hint for "%s" instead.', NullCache::class, NullAdapter::class, CacheInterface::class), \E_USER_DEPRECATED); /** - * @author Nicolas Grekas + * @deprecated since Symfony 4.3, use NullAdapter and type-hint for CacheInterface instead. */ -class NullCache implements CacheInterface +class NullCache implements Psr16CacheInterface { /** * {@inheritdoc} @@ -28,6 +32,8 @@ class NullCache implements CacheInterface /** * {@inheritdoc} + * + * @return iterable */ public function getMultiple($keys, $default = null) { @@ -38,6 +44,8 @@ class NullCache implements CacheInterface /** * {@inheritdoc} + * + * @return bool */ public function has($key) { @@ -46,6 +54,8 @@ class NullCache implements CacheInterface /** * {@inheritdoc} + * + * @return bool */ public function clear() { @@ -54,6 +64,8 @@ class NullCache implements CacheInterface /** * {@inheritdoc} + * + * @return bool */ public function delete($key) { @@ -62,6 +74,8 @@ class NullCache implements CacheInterface /** * {@inheritdoc} + * + * @return bool */ public function deleteMultiple($keys) { @@ -70,6 +84,8 @@ class NullCache implements CacheInterface /** * {@inheritdoc} + * + * @return bool */ public function set($key, $value, $ttl = null) { @@ -78,6 +94,8 @@ class NullCache implements CacheInterface /** * {@inheritdoc} + * + * @return bool */ public function setMultiple($values, $ttl = null) { diff --git a/advancedcontentfilter/vendor/symfony/cache/Simple/PdoCache.php b/advancedcontentfilter/vendor/symfony/cache/Simple/PdoCache.php index c92e049a..7011ea07 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Simple/PdoCache.php +++ b/advancedcontentfilter/vendor/symfony/cache/Simple/PdoCache.php @@ -11,9 +11,17 @@ namespace Symfony\Component\Cache\Simple; +use Symfony\Component\Cache\Adapter\PdoAdapter; +use Symfony\Component\Cache\Marshaller\MarshallerInterface; use Symfony\Component\Cache\PruneableInterface; use Symfony\Component\Cache\Traits\PdoTrait; +use Symfony\Contracts\Cache\CacheInterface; +@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.3, use "%s" and type-hint for "%s" instead.', PdoCache::class, PdoAdapter::class, CacheInterface::class), \E_USER_DEPRECATED); + +/** + * @deprecated since Symfony 4.3, use PdoAdapter and type-hint for CacheInterface instead. + */ class PdoCache extends AbstractCache implements PruneableInterface { use PdoTrait; @@ -25,6 +33,9 @@ class PdoCache extends AbstractCache implements PruneableInterface * a Doctrine DBAL Connection or a DSN string that will be used to * lazy-connect to the database when the cache is actually used. * + * When a Doctrine DBAL Connection is passed, 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] @@ -35,17 +46,14 @@ class PdoCache extends AbstractCache implements PruneableInterface * * db_password: The password when lazy-connect [default: ''] * * db_connection_options: An array of driver-specific connection options [default: []] * - * @param \PDO|Connection|string $connOrDsn A \PDO or Connection instance or DSN string or null - * @param string $namespace - * @param int $defaultLifetime - * @param array $options An associative array of options + * @param \PDO|Connection|string $connOrDsn a \PDO or Connection instance or DSN string or null * * @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($connOrDsn, $namespace = '', $defaultLifetime = 0, array $options = []) + public function __construct($connOrDsn, string $namespace = '', int $defaultLifetime = 0, array $options = [], MarshallerInterface $marshaller = null) { - $this->init($connOrDsn, $namespace, $defaultLifetime, $options); + $this->init($connOrDsn, $namespace, $defaultLifetime, $options, $marshaller); } } diff --git a/advancedcontentfilter/vendor/symfony/cache/Simple/PhpArrayCache.php b/advancedcontentfilter/vendor/symfony/cache/Simple/PhpArrayCache.php index 7bb25ff8..10c7340a 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Simple/PhpArrayCache.php +++ b/advancedcontentfilter/vendor/symfony/cache/Simple/PhpArrayCache.php @@ -11,51 +11,44 @@ namespace Symfony\Component\Cache\Simple; -use Psr\SimpleCache\CacheInterface; +use Psr\SimpleCache\CacheInterface as Psr16CacheInterface; +use Symfony\Component\Cache\Adapter\PhpArrayAdapter; use Symfony\Component\Cache\Exception\InvalidArgumentException; use Symfony\Component\Cache\PruneableInterface; use Symfony\Component\Cache\ResettableInterface; use Symfony\Component\Cache\Traits\PhpArrayTrait; +use Symfony\Contracts\Cache\CacheInterface; + +@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.3, use "%s" and type-hint for "%s" instead.', PhpArrayCache::class, PhpArrayAdapter::class, CacheInterface::class), \E_USER_DEPRECATED); /** - * 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 + * @deprecated since Symfony 4.3, use PhpArrayAdapter and type-hint for CacheInterface instead. */ -class PhpArrayCache implements CacheInterface, PruneableInterface, ResettableInterface +class PhpArrayCache implements Psr16CacheInterface, PruneableInterface, ResettableInterface { use PhpArrayTrait; /** - * @param string $file The PHP file were values are cached - * @param CacheInterface $fallbackPool A pool to fallback on when an item is not hit + * @param string $file The PHP file were values are cached + * @param Psr16CacheInterface $fallbackPool A pool to fallback on when an item is not hit */ - public function __construct($file, CacheInterface $fallbackPool) + public function __construct(string $file, Psr16CacheInterface $fallbackPool) { $this->file = $file; $this->pool = $fallbackPool; - $this->zendDetectUnicode = filter_var(ini_get('zend.detect_unicode'), \FILTER_VALIDATE_BOOLEAN); } /** - * This adapter should only be used on PHP 7.0+ to take advantage of how PHP - * stores arrays in its latest versions. This factory method decorates the given - * fallback pool with this adapter only if the current PHP version is supported. + * This adapter takes advantage of how PHP stores arrays in its latest versions. * * @param string $file The PHP file were values are cached * @param CacheInterface $fallbackPool A pool to fallback on when an item is not hit * - * @return CacheInterface + * @return Psr16CacheInterface */ - public static function create($file, CacheInterface $fallbackPool) + public static function create($file, Psr16CacheInterface $fallbackPool) { - if (\PHP_VERSION_ID >= 70000) { - return new static($file, $fallbackPool); - } - - return $fallbackPool; + return new static($file, $fallbackPool); } /** @@ -69,22 +62,18 @@ class PhpArrayCache implements CacheInterface, PruneableInterface, ResettableInt if (null === $this->values) { $this->initialize(); } - if (!isset($this->values[$key])) { + if (!isset($this->keys[$key])) { return $this->pool->get($key, $default); } - - $value = $this->values[$key]; + $value = $this->values[$this->keys[$key]]; if ('N;' === $value) { - $value = null; - } elseif (\is_string($value) && isset($value[2]) && ':' === $value[1]) { + return null; + } + if ($value instanceof \Closure) { try { - $e = null; - $value = unserialize($value); - } catch (\Error $e) { - } catch (\Exception $e) { - } - if (null !== $e) { + return $value(); + } catch (\Throwable $e) { return $default; } } @@ -94,6 +83,8 @@ class PhpArrayCache implements CacheInterface, PruneableInterface, ResettableInt /** * {@inheritdoc} + * + * @return iterable */ public function getMultiple($keys, $default = null) { @@ -116,6 +107,8 @@ class PhpArrayCache implements CacheInterface, PruneableInterface, ResettableInt /** * {@inheritdoc} + * + * @return bool */ public function has($key) { @@ -126,11 +119,13 @@ class PhpArrayCache implements CacheInterface, PruneableInterface, ResettableInt $this->initialize(); } - return isset($this->values[$key]) || $this->pool->has($key); + return isset($this->keys[$key]) || $this->pool->has($key); } /** * {@inheritdoc} + * + * @return bool */ public function delete($key) { @@ -141,11 +136,13 @@ class PhpArrayCache implements CacheInterface, PruneableInterface, ResettableInt $this->initialize(); } - return !isset($this->values[$key]) && $this->pool->delete($key); + return !isset($this->keys[$key]) && $this->pool->delete($key); } /** * {@inheritdoc} + * + * @return bool */ public function deleteMultiple($keys) { @@ -161,7 +158,7 @@ class PhpArrayCache implements CacheInterface, PruneableInterface, ResettableInt throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', \is_object($key) ? \get_class($key) : \gettype($key))); } - if (isset($this->values[$key])) { + if (isset($this->keys[$key])) { $deleted = false; } else { $fallbackKeys[] = $key; @@ -180,6 +177,8 @@ class PhpArrayCache implements CacheInterface, PruneableInterface, ResettableInt /** * {@inheritdoc} + * + * @return bool */ public function set($key, $value, $ttl = null) { @@ -190,11 +189,13 @@ class PhpArrayCache implements CacheInterface, PruneableInterface, ResettableInt $this->initialize(); } - return !isset($this->values[$key]) && $this->pool->set($key, $value, $ttl); + return !isset($this->keys[$key]) && $this->pool->set($key, $value, $ttl); } /** * {@inheritdoc} + * + * @return bool */ public function setMultiple($values, $ttl = null) { @@ -210,7 +211,7 @@ class PhpArrayCache implements CacheInterface, PruneableInterface, ResettableInt throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', \is_object($key) ? \get_class($key) : \gettype($key))); } - if (isset($this->values[$key])) { + if (isset($this->keys[$key])) { $saved = false; } else { $fallbackValues[$key] = $value; @@ -224,22 +225,20 @@ class PhpArrayCache implements CacheInterface, PruneableInterface, ResettableInt return $saved; } - private function generateItems(array $keys, $default) + private function generateItems(array $keys, $default): iterable { $fallbackKeys = []; foreach ($keys as $key) { - if (isset($this->values[$key])) { - $value = $this->values[$key]; + if (isset($this->keys[$key])) { + $value = $this->values[$this->keys[$key]]; if ('N;' === $value) { yield $key => null; - } elseif (\is_string($value) && isset($value[2]) && ':' === $value[1]) { + } elseif ($value instanceof \Closure) { try { - yield $key => unserialize($value); - } catch (\Error $e) { - yield $key => $default; - } catch (\Exception $e) { + yield $key => $value(); + } catch (\Throwable $e) { yield $key => $default; } } else { @@ -251,9 +250,7 @@ class PhpArrayCache implements CacheInterface, PruneableInterface, ResettableInt } if ($fallbackKeys) { - foreach ($this->pool->getMultiple($fallbackKeys, $default) as $key => $item) { - yield $key => $item; - } + yield from $this->pool->getMultiple($fallbackKeys, $default); } } } diff --git a/advancedcontentfilter/vendor/symfony/cache/Simple/PhpFilesCache.php b/advancedcontentfilter/vendor/symfony/cache/Simple/PhpFilesCache.php index 50c19034..9c79ae9a 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Simple/PhpFilesCache.php +++ b/advancedcontentfilter/vendor/symfony/cache/Simple/PhpFilesCache.php @@ -11,31 +11,35 @@ namespace Symfony\Component\Cache\Simple; +use Symfony\Component\Cache\Adapter\PhpFilesAdapter; use Symfony\Component\Cache\Exception\CacheException; use Symfony\Component\Cache\PruneableInterface; use Symfony\Component\Cache\Traits\PhpFilesTrait; +use Symfony\Contracts\Cache\CacheInterface; +@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.3, use "%s" and type-hint for "%s" instead.', PhpFilesCache::class, PhpFilesAdapter::class, CacheInterface::class), \E_USER_DEPRECATED); + +/** + * @deprecated since Symfony 4.3, use PhpFilesAdapter and type-hint for CacheInterface instead. + */ class PhpFilesCache extends AbstractCache implements PruneableInterface { use PhpFilesTrait; /** - * @param string $namespace - * @param int $defaultLifetime - * @param string|null $directory + * @param $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($namespace = '', $defaultLifetime = 0, $directory = null) + public function __construct(string $namespace = '', int $defaultLifetime = 0, string $directory = null, bool $appendOnly = false) { - if (!static::isSupported()) { - throw new CacheException('OPcache is not enabled.'); - } + $this->appendOnly = $appendOnly; + self::$startTime = self::$startTime ?? $_SERVER['REQUEST_TIME'] ?? time(); parent::__construct('', $defaultLifetime); $this->init($namespace, $directory); - - $e = new \Exception(); - $this->includeHandler = function () use ($e) { throw $e; }; - $this->zendDetectUnicode = filter_var(ini_get('zend.detect_unicode'), \FILTER_VALIDATE_BOOLEAN); + $this->includeHandler = static function ($type, $msg, $file, $line) { + throw new \ErrorException($msg, 0, $type, $file, $line); + }; } } diff --git a/advancedcontentfilter/vendor/symfony/cache/Simple/Psr6Cache.php b/advancedcontentfilter/vendor/symfony/cache/Simple/Psr6Cache.php index 6b3de205..366284b2 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Simple/Psr6Cache.php +++ b/advancedcontentfilter/vendor/symfony/cache/Simple/Psr6Cache.php @@ -11,231 +11,13 @@ namespace Symfony\Component\Cache\Simple; -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\CacheItem; -use Symfony\Component\Cache\Exception\InvalidArgumentException; -use Symfony\Component\Cache\PruneableInterface; -use Symfony\Component\Cache\ResettableInterface; -use Symfony\Component\Cache\Traits\ProxyTrait; +use Symfony\Component\Cache\Psr16Cache; + +@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.3, use "%s" instead.', Psr6Cache::class, Psr16Cache::class), \E_USER_DEPRECATED); /** - * @author Nicolas Grekas + * @deprecated since Symfony 4.3, use Psr16Cache instead. */ -class Psr6Cache implements CacheInterface, PruneableInterface, ResettableInterface +class Psr6Cache extends Psr16Cache { - use ProxyTrait; - - private $createCacheItem; - private $cacheItemPrototype; - - 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->key = $allowInt && \is_int($key) ? (string) $key : CacheItem::validateKey($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, $value, $allowInt); - }; - } - - /** - * {@inheritdoc} - */ - public function get($key, $default = null) - { - 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; - } - - /** - * {@inheritdoc} - */ - public function set($key, $value, $ttl = null) - { - 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); - } - - /** - * {@inheritdoc} - */ - public function delete($key) - { - try { - return $this->pool->deleteItem($key); - } catch (SimpleCacheException $e) { - throw $e; - } catch (Psr6CacheException $e) { - throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e); - } - } - - /** - * {@inheritdoc} - */ - public function clear() - { - return $this->pool->clear(); - } - - /** - * {@inheritdoc} - */ - public function getMultiple($keys, $default = null) - { - 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.', \is_object($keys) ? \get_class($keys) : \gettype($keys))); - } - - try { - $items = $this->pool->getItems($keys); - } catch (SimpleCacheException $e) { - throw $e; - } catch (Psr6CacheException $e) { - throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e); - } - $values = []; - - foreach ($items as $key => $item) { - $values[$key] = $item->isHit() ? $item->get() : $default; - } - - return $values; - } - - /** - * {@inheritdoc} - */ - public function setMultiple($values, $ttl = null) - { - $valuesIsArray = \is_array($values); - if (!$valuesIsArray && !$values instanceof \Traversable) { - throw new InvalidArgumentException(sprintf('Cache values must be array or Traversable, "%s" given.', \is_object($values) ? \get_class($values) : \gettype($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; - } - - /** - * {@inheritdoc} - */ - public function deleteMultiple($keys) - { - 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.', \is_object($keys) ? \get_class($keys) : \gettype($keys))); - } - - try { - return $this->pool->deleteItems($keys); - } catch (SimpleCacheException $e) { - throw $e; - } catch (Psr6CacheException $e) { - throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e); - } - } - - /** - * {@inheritdoc} - */ - public function has($key) - { - 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/advancedcontentfilter/vendor/symfony/cache/Simple/RedisCache.php b/advancedcontentfilter/vendor/symfony/cache/Simple/RedisCache.php index e82c0627..e0a76fd6 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Simple/RedisCache.php +++ b/advancedcontentfilter/vendor/symfony/cache/Simple/RedisCache.php @@ -11,19 +11,27 @@ namespace Symfony\Component\Cache\Simple; +use Symfony\Component\Cache\Adapter\RedisAdapter; +use Symfony\Component\Cache\Marshaller\MarshallerInterface; +use Symfony\Component\Cache\Traits\RedisClusterProxy; +use Symfony\Component\Cache\Traits\RedisProxy; use Symfony\Component\Cache\Traits\RedisTrait; +use Symfony\Contracts\Cache\CacheInterface; +@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.3, use "%s" and type-hint for "%s" instead.', RedisCache::class, RedisAdapter::class, CacheInterface::class), \E_USER_DEPRECATED); + +/** + * @deprecated since Symfony 4.3, use RedisAdapter and type-hint for CacheInterface instead. + */ class RedisCache extends AbstractCache { use RedisTrait; /** - * @param \Redis|\RedisArray|\RedisCluster|\Predis\Client $redisClient - * @param string $namespace - * @param int $defaultLifetime + * @param \Redis|\RedisArray|\RedisCluster|\Predis\ClientInterface|RedisProxy|RedisClusterProxy $redis */ - public function __construct($redisClient, $namespace = '', $defaultLifetime = 0) + public function __construct($redis, string $namespace = '', int $defaultLifetime = 0, MarshallerInterface $marshaller = null) { - $this->init($redisClient, $namespace, $defaultLifetime); + $this->init($redis, $namespace, $defaultLifetime, $marshaller); } } diff --git a/advancedcontentfilter/vendor/symfony/cache/Simple/TraceableCache.php b/advancedcontentfilter/vendor/symfony/cache/Simple/TraceableCache.php index 61b22963..0dae813e 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Simple/TraceableCache.php +++ b/advancedcontentfilter/vendor/symfony/cache/Simple/TraceableCache.php @@ -11,22 +11,25 @@ namespace Symfony\Component\Cache\Simple; -use Psr\SimpleCache\CacheInterface; +use Psr\SimpleCache\CacheInterface as Psr16CacheInterface; +use Symfony\Component\Cache\Adapter\TraceableAdapter; use Symfony\Component\Cache\PruneableInterface; use Symfony\Component\Cache\ResettableInterface; +use Symfony\Contracts\Cache\CacheInterface; +use Symfony\Contracts\Service\ResetInterface; + +@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.3, use "%s" and type-hint for "%s" instead.', TraceableCache::class, TraceableAdapter::class, CacheInterface::class), \E_USER_DEPRECATED); /** - * An adapter that collects data about all cache calls. - * - * @author Nicolas Grekas + * @deprecated since Symfony 4.3, use TraceableAdapter and type-hint for CacheInterface instead. */ -class TraceableCache implements CacheInterface, PruneableInterface, ResettableInterface +class TraceableCache implements Psr16CacheInterface, PruneableInterface, ResettableInterface { private $pool; private $miss; private $calls = []; - public function __construct(CacheInterface $pool) + public function __construct(Psr16CacheInterface $pool) { $this->pool = $pool; $this->miss = new \stdClass(); @@ -56,6 +59,8 @@ class TraceableCache implements CacheInterface, PruneableInterface, ResettableIn /** * {@inheritdoc} + * + * @return bool */ public function has($key) { @@ -69,6 +74,8 @@ class TraceableCache implements CacheInterface, PruneableInterface, ResettableIn /** * {@inheritdoc} + * + * @return bool */ public function delete($key) { @@ -82,6 +89,8 @@ class TraceableCache implements CacheInterface, PruneableInterface, ResettableIn /** * {@inheritdoc} + * + * @return bool */ public function set($key, $value, $ttl = null) { @@ -95,6 +104,8 @@ class TraceableCache implements CacheInterface, PruneableInterface, ResettableIn /** * {@inheritdoc} + * + * @return bool */ public function setMultiple($values, $ttl = null) { @@ -122,6 +133,8 @@ class TraceableCache implements CacheInterface, PruneableInterface, ResettableIn /** * {@inheritdoc} + * + * @return iterable */ public function getMultiple($keys, $default = null) { @@ -150,6 +163,8 @@ class TraceableCache implements CacheInterface, PruneableInterface, ResettableIn /** * {@inheritdoc} + * + * @return bool */ public function clear() { @@ -163,6 +178,8 @@ class TraceableCache implements CacheInterface, PruneableInterface, ResettableIn /** * {@inheritdoc} + * + * @return bool */ public function deleteMultiple($keys) { @@ -200,7 +217,7 @@ class TraceableCache implements CacheInterface, PruneableInterface, ResettableIn */ public function reset() { - if (!$this->pool instanceof ResettableInterface) { + if (!$this->pool instanceof ResetInterface) { return; } $event = $this->start(__FUNCTION__); @@ -220,7 +237,7 @@ class TraceableCache implements CacheInterface, PruneableInterface, ResettableIn } } - private function start($name) + private function start(string $name): TraceableCacheEvent { $this->calls[] = $event = new TraceableCacheEvent(); $event->name = $name; diff --git a/advancedcontentfilter/vendor/symfony/cache/Traits/AbstractAdapterTrait.php b/advancedcontentfilter/vendor/symfony/cache/Traits/AbstractAdapterTrait.php new file mode 100644 index 00000000..388c1df3 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Traits/AbstractAdapterTrait.php @@ -0,0 +1,164 @@ + + * + * 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 Symfony\Component\Cache\CacheItem; +use Symfony\Component\Cache\Exception\InvalidArgumentException; + +/** + * @author Nicolas Grekas + * + * @internal + */ +trait AbstractAdapterTrait +{ + use AbstractTrait; + + /** + * @var \Closure needs to be set by class, signature is function(string , mixed , bool ) + */ + private $createCacheItem; + + /** + * @var \Closure needs to be set by class, signature is function(array , string , array <&expiredIds>) + */ + private $mergeByLifetime; + + /** + * {@inheritdoc} + */ + public function getItem($key) + { + $id = $this->getId($key); + + if (isset($this->deferred[$key])) { + $this->commit(); + } + + $f = $this->createCacheItem; + $isHit = false; + $value = null; + + try { + foreach ($this->doFetch([$id]) as $value) { + $isHit = true; + } + + return $f($key, $value, $isHit); + } catch (\Exception $e) { + CacheItem::log($this->logger, 'Failed to fetch key "{key}": '.$e->getMessage(), ['key' => $key, 'exception' => $e]); + } + + return $f($key, null, false); + } + + /** + * {@inheritdoc} + */ + public function getItems(array $keys = []) + { + $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]); + $items = []; + } + $ids = array_combine($ids, $keys); + + return $this->generateItems($items, $ids); + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function save(CacheItemInterface $item) + { + if (!$item instanceof CacheItem) { + return false; + } + $this->deferred[$item->getKey()] = $item; + + return $this->commit(); + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function saveDeferred(CacheItemInterface $item) + { + if (!$item instanceof CacheItem) { + return false; + } + $this->deferred[$item->getKey()] = $item; + + return true; + } + + /** + * @return array + */ + public function __sleep() + { + throw new \BadMethodCallException('Cannot serialize '.__CLASS__); + } + + public function __wakeup() + { + throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); + } + + public function __destruct() + { + if ($this->deferred) { + $this->commit(); + } + } + + private function generateItems(iterable $items, array &$keys): iterable + { + $f = $this->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]); + } + + foreach ($keys as $key) { + yield $key => $f($key, null, false); + } + } +} diff --git a/advancedcontentfilter/vendor/symfony/cache/Traits/AbstractTrait.php b/advancedcontentfilter/vendor/symfony/cache/Traits/AbstractTrait.php index dc291e10..b0478806 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Traits/AbstractTrait.php +++ b/advancedcontentfilter/vendor/symfony/cache/Traits/AbstractTrait.php @@ -27,6 +27,7 @@ trait AbstractTrait private $namespaceVersion = ''; private $versioningIsEnabled = false; private $deferred = []; + private $ids = []; /** * @var int|null The maximum length to enforce for identifiers or null when no limit applies @@ -77,10 +78,12 @@ trait AbstractTrait * * @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, $lifetime); + abstract protected function doSave(array $values, int $lifetime); /** * {@inheritdoc} + * + * @return bool */ public function hasItem($key) { @@ -93,7 +96,7 @@ trait AbstractTrait try { return $this->doHave($id); } catch (\Exception $e) { - CacheItem::log($this->logger, 'Failed to check if key "{key}" is cached', ['key' => $key, 'exception' => $e]); + CacheItem::log($this->logger, 'Failed to check if key "{key}" is cached: '.$e->getMessage(), ['key' => $key, 'exception' => $e]); return false; } @@ -101,26 +104,43 @@ trait AbstractTrait /** * {@inheritdoc} + * + * @param string $prefix + * + * @return bool */ - public function clear() + public function clear(/* string $prefix = '' */) { $this->deferred = []; if ($cleared = $this->versioningIsEnabled) { - $namespaceVersion = substr_replace(base64_encode(pack('V', mt_rand())), static::NS_SEPARATOR, 5); + 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 { - $cleared = $this->doSave([static::NS_SEPARATOR.$this->namespace => $namespaceVersion], 0); + $e = $this->doSave([static::NS_SEPARATOR.$this->namespace => $namespaceVersion], 0); } catch (\Exception $e) { + } + if (true !== $e && [] !== $e) { $cleared = false; - } - if ($cleared = true === $cleared || [] === $cleared) { + $message = 'Failed to save the new namespace'.($e instanceof \Exception ? ': '.$e->getMessage() : '.'); + CacheItem::log($this->logger, $message, ['exception' => $e instanceof \Exception ? $e : null]); + } else { $this->namespaceVersion = $namespaceVersion; + $this->ids = []; } + } else { + $prefix = 0 < \func_num_args() ? (string) func_get_arg(0) : ''; + $namespaceToClear = $this->namespace.$prefix; } try { - return $this->doClear($this->namespace) || $cleared; + return $this->doClear($namespaceToClear) || $cleared; } catch (\Exception $e) { - CacheItem::log($this->logger, 'Failed to clear the cache', ['exception' => $e]); + CacheItem::log($this->logger, 'Failed to clear the cache: '.$e->getMessage(), ['exception' => $e]); return false; } @@ -128,6 +148,8 @@ trait AbstractTrait /** * {@inheritdoc} + * + * @return bool */ public function deleteItem($key) { @@ -136,6 +158,8 @@ trait AbstractTrait /** * {@inheritdoc} + * + * @return bool */ public function deleteItems(array $keys) { @@ -164,7 +188,8 @@ trait AbstractTrait } } catch (\Exception $e) { } - CacheItem::log($this->logger, 'Failed to delete key "{key}"', ['key' => $key, 'exception' => $e]); + $message = 'Failed to delete key "{key}"'.($e instanceof \Exception ? ': '.$e->getMessage() : '.'); + CacheItem::log($this->logger, $message, ['key' => $key, 'exception' => $e]); $ok = false; } @@ -188,6 +213,7 @@ trait AbstractTrait $wasEnabled = $this->versioningIsEnabled; $this->versioningIsEnabled = (bool) $enable; $this->namespaceVersion = ''; + $this->ids = []; return $wasEnabled; } @@ -201,6 +227,7 @@ trait AbstractTrait $this->commit(); } $this->namespaceVersion = ''; + $this->ids = []; } /** @@ -211,9 +238,13 @@ trait AbstractTrait * @return mixed * * @throws \Exception + * + * @deprecated since Symfony 4.2, use DefaultMarshaller instead. */ protected static function unserialize($value) { + @trigger_error(sprintf('The "%s::unserialize()" method is deprecated since Symfony 4.2, use DefaultMarshaller instead.', __CLASS__), \E_USER_DEPRECATED); + if ('b:0;' === $value) { return false; } @@ -230,29 +261,45 @@ trait AbstractTrait } } - private function getId($key) + private function getId($key): string { - CacheItem::validateKey($key); - 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 = substr_replace(base64_encode(pack('V', time())), static::NS_SEPARATOR, 5); - $this->doSave([static::NS_SEPARATOR.$this->namespace => $this->namespaceVersion], 0); + $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]); + } + } + + if (\is_string($key) && isset($this->ids[$key])) { + return $this->namespace.$this->namespaceVersion.$this->ids[$key]; + } + 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) { - $id = $this->namespace.$this->namespaceVersion.substr_replace(base64_encode(hash('sha256', $key, true)), static::NS_SEPARATOR, -(\strlen($this->namespaceVersion) + 22)); + // Use MD5 to favor speed over security, which is not an issue here + $this->ids[$key] = $id = substr_replace(base64_encode(hash('md5', $key, true)), static::NS_SEPARATOR, -(\strlen($this->namespaceVersion) + 2)); + $id = $this->namespace.$this->namespaceVersion.$id; } return $id; @@ -265,4 +312,9 @@ trait AbstractTrait { 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/advancedcontentfilter/vendor/symfony/cache/Traits/ApcuTrait.php b/advancedcontentfilter/vendor/symfony/cache/Traits/ApcuTrait.php index 2f47f8e6..46bd20fe 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Traits/ApcuTrait.php +++ b/advancedcontentfilter/vendor/symfony/cache/Traits/ApcuTrait.php @@ -23,10 +23,10 @@ trait ApcuTrait { public static function isSupported() { - return \function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), \FILTER_VALIDATE_BOOLEAN); + return \function_exists('apcu_fetch') && filter_var(\ini_get('apc.enabled'), \FILTER_VALIDATE_BOOLEAN); } - private function init($namespace, $defaultLifetime, $version) + private function init(string $namespace, int $defaultLifetime, ?string $version) { if (!static::isSupported()) { throw new CacheException('APCu is not enabled.'); @@ -51,14 +51,27 @@ trait ApcuTrait */ protected function doFetch(array $ids) { + $unserializeCallbackHandler = ini_set('unserialize_callback_func', __CLASS__.'::handleUnserializeCallback'); try { - foreach (apcu_fetch($ids, $ok) ?: [] as $k => $v) { + $values = []; + $ids = array_flip($ids); + foreach (apcu_fetch(array_keys($ids), $ok) ?: [] as $k => $v) { + if (!isset($ids[$k])) { + // work around https://github.com/krakjoe/apcu/issues/247 + $k = key($ids); + } + unset($ids[$k]); + if (null !== $v || $ok) { - yield $k => $v; + $values[$k] = $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); } } @@ -75,8 +88,8 @@ trait ApcuTrait */ protected function doClear($namespace) { - return isset($namespace[0]) && class_exists('APCuIterator', false) && ('cli' !== \PHP_SAPI || filter_var(ini_get('apc.enable_cli'), \FILTER_VALIDATE_BOOLEAN)) - ? apcu_delete(new \APCuIterator(sprintf('/^%s/', preg_quote($namespace, '/')), \APC_ITER_KEY)) + return isset($namespace[0]) && class_exists(\APCUIterator::class, false) && ('cli' !== \PHP_SAPI || filter_var(\ini_get('apc.enable_cli'), \FILTER_VALIDATE_BOOLEAN)) + ? apcu_delete(new \APCUIterator(sprintf('/^%s/', preg_quote($namespace, '/')), \APC_ITER_KEY)) : apcu_clear_cache(); } @@ -95,7 +108,7 @@ trait ApcuTrait /** * {@inheritdoc} */ - protected function doSave(array $values, $lifetime) + protected function doSave(array $values, int $lifetime) { try { if (false === $failures = apcu_store($values, null, $lifetime)) { @@ -103,15 +116,13 @@ trait ApcuTrait } return array_keys($failures); - } catch (\Error $e) { - } catch (\Exception $e) { - } + } catch (\Throwable $e) { + if (1 === \count($values)) { + // Workaround https://github.com/krakjoe/apcu/issues/170 + apcu_delete(array_key_first($values)); + } - if (1 === \count($values)) { - // Workaround https://github.com/krakjoe/apcu/issues/170 - apcu_delete(key($values)); + throw $e; } - - throw $e; } } diff --git a/advancedcontentfilter/vendor/symfony/cache/Traits/ArrayTrait.php b/advancedcontentfilter/vendor/symfony/cache/Traits/ArrayTrait.php index 0a60968e..e41daebc 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Traits/ArrayTrait.php +++ b/advancedcontentfilter/vendor/symfony/cache/Traits/ArrayTrait.php @@ -34,36 +34,72 @@ trait ArrayTrait */ public function getValues() { - return $this->values; + 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; } /** * {@inheritdoc} + * + * @return bool */ public function hasItem($key) { + if (\is_string($key) && isset($this->expiries[$key]) && $this->expiries[$key] > microtime(true)) { + return true; + } CacheItem::validateKey($key); - return isset($this->expiries[$key]) && ($this->expiries[$key] > time() || !$this->deleteItem($key)); + return isset($this->expiries[$key]) && !$this->deleteItem($key); } /** * {@inheritdoc} + * + * @param string $prefix + * + * @return bool */ - public function clear() + public function clear(/* string $prefix = '' */) { - $this->values = $this->expiries = []; + $prefix = 0 < \func_num_args() ? (string) func_get_arg(0) : ''; + + if ('' !== $prefix) { + foreach ($this->values as $key => $value) { + if (str_starts_with($key, $prefix)) { + unset($this->values[$key], $this->expiries[$key]); + } + } + } else { + $this->values = $this->expiries = []; + } return true; } /** * {@inheritdoc} + * + * @return bool */ public function deleteItem($key) { - CacheItem::validateKey($key); - + if (!\is_string($key) || !isset($this->expiries[$key])) { + CacheItem::validateKey($key); + } unset($this->values[$key], $this->expiries[$key]); return true; @@ -77,24 +113,13 @@ trait ArrayTrait $this->clear(); } - private function generateItems(array $keys, $now, $f) + private function generateItems(array $keys, float $now, callable $f): iterable { foreach ($keys as $i => $key) { - try { - if (!$isHit = isset($this->expiries[$key]) && ($this->expiries[$key] > $now || !$this->deleteItem($key))) { - $this->values[$key] = $value = null; - } elseif (!$this->storeSerialized) { - $value = $this->values[$key]; - } elseif ('b:0;' === $value = $this->values[$key]) { - $value = false; - } elseif (false === $value = unserialize($value)) { - $this->values[$key] = $value = null; - $isHit = false; - } - } catch (\Exception $e) { - CacheItem::log($this->logger, 'Failed to unserialize key "{key}"', ['key' => $key, 'exception' => $e]); + if (!$isHit = isset($this->expiries[$key]) && ($this->expiries[$key] > $now || !$this->deleteItem($key))) { $this->values[$key] = $value = null; - $isHit = false; + } else { + $value = $this->storeSerialized ? $this->unfreeze($key, $isHit) : $this->values[$key]; } unset($keys[$i]); @@ -105,4 +130,55 @@ trait ArrayTrait yield $key => $f($key, null, false); } } + + private function freeze($value, $key) + { + 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]); + $type = \is_object($value) ? \get_class($value) : \gettype($value); + $message = sprintf('Failed to save key "{key}" of type %s: ', $type).$e->getMessage(); + CacheItem::log($this->logger, $message, ['key' => $key, 'exception' => $e]); + + 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) + { + 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]); + $value = false; + } + if (false === $value) { + $this->values[$key] = $value = null; + $isHit = false; + } + } + + return $value; + } } diff --git a/advancedcontentfilter/vendor/symfony/cache/Traits/ContractsTrait.php b/advancedcontentfilter/vendor/symfony/cache/Traits/ContractsTrait.php new file mode 100644 index 00000000..49a96eed --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Traits/ContractsTrait.php @@ -0,0 +1,109 @@ + + * + * 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 $callbackWrapper; + private $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 = \Closure::fromCallable([LockRegistry::class, 'compute']); + + if (\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true)) { + $this->setCallbackWrapper(null); + } + } + + $previousWrapper = $this->callbackWrapper; + $this->callbackWrapper = $callbackWrapper ?? static function (callable $callback, ItemInterface $item, bool &$save, CacheInterface $pool, \Closure $setMetadata, ?LoggerInterface $logger) { + return $callback($item, $save); + }; + + return $previousWrapper; + } + + private function doGet(AdapterInterface $pool, string $key, callable $callback, ?float $beta, array &$metadata = null) + { + if (0 > $beta = $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 = $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]); + } + }, + null, + CacheItem::class + ); + + 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/advancedcontentfilter/vendor/symfony/cache/Traits/DoctrineTrait.php b/advancedcontentfilter/vendor/symfony/cache/Traits/DoctrineTrait.php index 48623e67..ae14db01 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Traits/DoctrineTrait.php +++ b/advancedcontentfilter/vendor/symfony/cache/Traits/DoctrineTrait.php @@ -91,7 +91,7 @@ trait DoctrineTrait /** * {@inheritdoc} */ - protected function doSave(array $values, $lifetime) + protected function doSave(array $values, int $lifetime) { return $this->provider->saveMultiple($values, $lifetime); } diff --git a/advancedcontentfilter/vendor/symfony/cache/Traits/FilesystemCommonTrait.php b/advancedcontentfilter/vendor/symfony/cache/Traits/FilesystemCommonTrait.php index 8071a382..4e06495d 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Traits/FilesystemCommonTrait.php +++ b/advancedcontentfilter/vendor/symfony/cache/Traits/FilesystemCommonTrait.php @@ -23,10 +23,10 @@ trait FilesystemCommonTrait private $directory; private $tmp; - private function init($namespace, $directory) + private function init(string $namespace, ?string $directory) { if (!isset($directory[0])) { - $directory = sys_get_temp_dir().'/symfony-cache'; + $directory = sys_get_temp_dir().\DIRECTORY_SEPARATOR.'symfony-cache'; } else { $directory = realpath($directory) ?: $directory; } @@ -35,6 +35,8 @@ trait FilesystemCommonTrait 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 (!file_exists($directory)) { @mkdir($directory, 0777, true); @@ -55,8 +57,12 @@ trait FilesystemCommonTrait { $ok = true; - foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->directory, \FilesystemIterator::SKIP_DOTS)) as $file) { - $ok = ($file->isDir() || @unlink($file) || !file_exists($file)) && $ok; + 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; @@ -71,23 +77,39 @@ trait FilesystemCommonTrait foreach ($ids as $id) { $file = $this->getFile($id); - $ok = (!file_exists($file) || @unlink($file) || !file_exists($file)) && $ok; + $ok = (!file_exists($file) || $this->doUnlink($file) || !file_exists($file)) && $ok; } return $ok; } - private function write($file, $data, $expiresAt = null) + protected function doUnlink($file) + { + return @unlink($file); + } + + private function write(string $file, string $data, int $expiresAt = null) { set_error_handler(__CLASS__.'::throwError'); try { if (null === $this->tmp) { - $this->tmp = $this->directory.uniqid('', true); + $this->tmp = $this->directory.bin2hex(random_bytes(6)); } - file_put_contents($this->tmp, $data); + try { + $h = fopen($this->tmp, 'x'); + } catch (\ErrorException $e) { + if (!str_contains($e->getMessage(), 'File exists')) { + throw $e; + } + + $this->tmp = $this->directory.bin2hex(random_bytes(6)); + $h = fopen($this->tmp, 'x'); + } + fwrite($h, $data); + fclose($h); if (null !== $expiresAt) { - touch($this->tmp, $expiresAt); + touch($this->tmp, $expiresAt ?: time() + 31556952); // 1 year in seconds } return rename($this->tmp, $file); @@ -96,10 +118,11 @@ trait FilesystemCommonTrait } } - private function getFile($id, $mkdir = false) + private function getFile(string $id, bool $mkdir = false, string $directory = null) { - $hash = str_replace('/', '-', base64_encode(hash('sha256', static::class.$id, true))); - $dir = $this->directory.strtoupper($hash[0].\DIRECTORY_SEPARATOR.$hash[1].\DIRECTORY_SEPARATOR); + // Use MD5 to favor speed over security, which is not an issue here + $hash = str_replace('/', '-', base64_encode(hash('md5', static::class.$id, true))); + $dir = ($directory ?? $this->directory).strtoupper($hash[0].\DIRECTORY_SEPARATOR.$hash[1].\DIRECTORY_SEPARATOR); if ($mkdir && !file_exists($dir)) { @mkdir($dir, 0777, true); @@ -108,6 +131,38 @@ trait FilesystemCommonTrait return $dir.substr($hash, 2, 20); } + private function getFileKey(string $file): string + { + return ''; + } + + private function scanHashDir(string $directory): \Generator + { + if (!file_exists($directory)) { + return; + } + + $chars = '+-ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; + + for ($i = 0; $i < 38; ++$i) { + if (!file_exists($directory.$chars[$i])) { + continue; + } + + for ($j = 0; $j < 38; ++$j) { + if (!file_exists($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; + } + } + } + } + } + /** * @internal */ @@ -116,6 +171,9 @@ trait FilesystemCommonTrait throw new \ErrorException($message, 0, $type, $file, $line); } + /** + * @return array + */ public function __sleep() { throw new \BadMethodCallException('Cannot serialize '.__CLASS__); diff --git a/advancedcontentfilter/vendor/symfony/cache/Traits/FilesystemTrait.php b/advancedcontentfilter/vendor/symfony/cache/Traits/FilesystemTrait.php index 9d7f5578..72118eaa 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Traits/FilesystemTrait.php +++ b/advancedcontentfilter/vendor/symfony/cache/Traits/FilesystemTrait.php @@ -23,6 +23,8 @@ trait FilesystemTrait { use FilesystemCommonTrait; + private $marshaller; + /** * @return bool */ @@ -31,8 +33,8 @@ trait FilesystemTrait $time = time(); $pruned = true; - foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->directory, \FilesystemIterator::SKIP_DOTS), \RecursiveIteratorIterator::LEAVES_ONLY) as $file) { - if (!$h = @fopen($file, 'rb')) { + foreach ($this->scanHashDir($this->directory) as $file) { + if (!$h = @fopen($file, 'r')) { continue; } @@ -57,7 +59,7 @@ trait FilesystemTrait foreach ($ids as $id) { $file = $this->getFile($id); - if (!file_exists($file) || !$h = @fopen($file, 'rb')) { + if (!file_exists($file) || !$h = @fopen($file, 'r')) { continue; } if (($expiresAt = (int) fgets($h)) && $now >= $expiresAt) { @@ -68,7 +70,7 @@ trait FilesystemTrait $value = stream_get_contents($h); fclose($h); if ($i === $id) { - $values[$id] = parent::unserialize($value); + $values[$id] = $this->marshaller->unmarshall($value); } } } @@ -89,19 +91,34 @@ trait FilesystemTrait /** * {@inheritdoc} */ - protected function doSave(array $values, $lifetime) + protected function doSave(array $values, int $lifetime) { - $ok = true; $expiresAt = $lifetime ? (time() + $lifetime) : 0; + $values = $this->marshaller->marshall($values, $failed); foreach ($values as $id => $value) { - $ok = $this->write($this->getFile($id, true), $expiresAt."\n".rawurlencode($id)."\n".serialize($value), $expiresAt) && $ok; + if (!$this->write($this->getFile($id, true), $expiresAt."\n".rawurlencode($id)."\n".$value, $expiresAt)) { + $failed[] = $id; + } } - if (!$ok && !is_writable($this->directory)) { + if ($failed && !is_writable($this->directory)) { throw new CacheException(sprintf('Cache directory is not writable (%s).', $this->directory)); } - return $ok; + 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/advancedcontentfilter/vendor/symfony/cache/Traits/MemcachedTrait.php b/advancedcontentfilter/vendor/symfony/cache/Traits/MemcachedTrait.php index 34d0208e..ebcb160c 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Traits/MemcachedTrait.php +++ b/advancedcontentfilter/vendor/symfony/cache/Traits/MemcachedTrait.php @@ -13,6 +13,8 @@ namespace Symfony\Component\Cache\Traits; 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 @@ -29,18 +31,27 @@ trait MemcachedTrait \Memcached::OPT_SERIALIZER => \Memcached::SERIALIZER_PHP, ]; + /** + * 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 \Symfony\Component\Cache\Adapter\AbstractAdapter::NS_SEPARATOR}. + */ + private static $RESERVED_MEMCACHED = " \n\r\t\v\f\0"; + private static $RESERVED_PSR6 = '@()\{}/'; + + private $marshaller; private $client; private $lazyClient; public static function isSupported() { - return \extension_loaded('memcached') && version_compare(phpversion('memcached'), '2.2.0', '>='); + return \extension_loaded('memcached') && version_compare(phpversion('memcached'), \PHP_VERSION_ID >= 80100 ? '3.1.6' : '2.2.0', '>='); } - private function init(\Memcached $client, $namespace, $defaultLifetime) + private function init(\Memcached $client, string $namespace, int $defaultLifetime, ?MarshallerInterface $marshaller) { if (!static::isSupported()) { - throw new CacheException('Memcached >= 2.2.0 is required.'); + throw new CacheException('Memcached '.(\PHP_VERSION_ID >= 80100 ? '> 3.1.5' : '>= 2.2.0').' is required.'); } if ('Memcached' === \get_class($client)) { $opt = $client->getOption(\Memcached::OPT_SERIALIZER); @@ -55,6 +66,7 @@ trait MemcachedTrait parent::__construct($namespace, $defaultLifetime); $this->enableVersioning(); + $this->marshaller = $marshaller ?? new DefaultMarshaller(); } /** @@ -67,7 +79,6 @@ trait MemcachedTrait * - [['localhost', 11211, 33]] * * @param array[]|string|string[] $servers An array of servers, a DSN, or an array of DSNs - * @param array $options An array of options * * @return \Memcached * @@ -81,7 +92,7 @@ trait MemcachedTrait throw new InvalidArgumentException(sprintf('MemcachedAdapter::createClient() expects array or string as first argument, "%s" given.', \gettype($servers))); } if (!static::isSupported()) { - throw new CacheException('Memcached >= 2.2.0 is required.'); + throw new CacheException('Memcached '.(\PHP_VERSION_ID >= 80100 ? '> 3.1.5' : '>= 2.2.0').' is required.'); } set_error_handler(function ($type, $msg, $file, $line) { throw new \ErrorException($msg, 0, $type, $file, $line); }); try { @@ -95,19 +106,43 @@ trait MemcachedTrait if (\is_array($dsn)) { continue; } - if (0 !== strpos($dsn, 'memcached://')) { - throw new InvalidArgumentException(sprintf('Invalid Memcached DSN: "%s" does not start with "memcached://".', $dsn)); + if (!str_starts_with($dsn, 'memcached:')) { + throw new InvalidArgumentException(sprintf('Invalid Memcached DSN: "%s" does not start with "memcached:".', $dsn)); } - $params = preg_replace_callback('#^memcached://(?:([^@]*+)@)?#', function ($m) use (&$username, &$password) { - if (!empty($m[1])) { - list($username, $password) = explode(':', $m[1], 2) + [1 => null]; + $params = preg_replace_callback('#^memcached:(//)?(?:([^@]*+)@)?#', function ($m) use (&$username, &$password) { + if (!empty($m[2])) { + [$username, $password] = explode(':', $m[2], 2) + [1 => null]; } - return 'file://'; + return 'file:'.($m[1] ?? ''); }, $dsn); if (false === $params = parse_url($params)) { throw new InvalidArgumentException(sprintf('Invalid Memcached DSN: "%s".', $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(sprintf('Invalid Memcached DSN: "%s".', $dsn)); + } + 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(sprintf('Invalid Memcached DSN: "%s".', $dsn)); } @@ -116,17 +151,20 @@ trait MemcachedTrait $params['path'] = substr($params['path'], 0, -\strlen($m[0])); } $params += [ - 'host' => isset($params['host']) ? $params['host'] : $params['path'], + 'host' => $params['host'] ?? $params['path'], 'port' => isset($params['host']) ? 11211 : null, 'weight' => 0, ]; - if (isset($params['query'])) { - parse_str($params['query'], $query); + 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 @@ -193,18 +231,22 @@ trait MemcachedTrait /** * {@inheritdoc} */ - protected function doSave(array $values, $lifetime) + protected function doSave(array $values, int $lifetime) { + if (!$values = $this->marshaller->marshall($values, $failed)) { + return $failed; + } + if ($lifetime && $lifetime > 30 * 86400) { $lifetime += time(); } $encodedValues = []; foreach ($values as $key => $value) { - $encodedValues[rawurlencode($key)] = $value; + $encodedValues[self::encodeKey($key)] = $value; } - return $this->checkResultCode($this->getClient()->setMulti($encodedValues, $lifetime)); + return $this->checkResultCode($this->getClient()->setMulti($encodedValues, $lifetime)) ? $failed : false; } /** @@ -212,22 +254,19 @@ trait MemcachedTrait */ protected function doFetch(array $ids) { - $unserializeCallbackHandler = ini_set('unserialize_callback_func', __CLASS__.'::handleUnserializeCallback'); try { - $encodedIds = array_map('rawurlencode', $ids); + $encodedIds = array_map([__CLASS__, 'encodeKey'], $ids); $encodedResult = $this->checkResultCode($this->getClient()->getMulti($encodedIds)); $result = []; foreach ($encodedResult as $key => $value) { - $result[rawurldecode($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()); - } finally { - ini_set('unserialize_callback_func', $unserializeCallbackHandler); } } @@ -236,7 +275,7 @@ trait MemcachedTrait */ protected function doHave($id) { - return false !== $this->getClient()->get(rawurlencode($id)) || $this->checkResultCode(\Memcached::RES_SUCCESS === $this->client->getResultCode()); + return false !== $this->getClient()->get(self::encodeKey($id)) || $this->checkResultCode(\Memcached::RES_SUCCESS === $this->client->getResultCode()); } /** @@ -245,7 +284,7 @@ trait MemcachedTrait protected function doDelete(array $ids) { $ok = true; - $encodedIds = array_map('rawurlencode', $ids); + $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; @@ -275,10 +314,7 @@ trait MemcachedTrait throw new CacheException('MemcachedAdapter client error: '.strtolower($this->client->getResultMessage())); } - /** - * @return \Memcached - */ - private function getClient() + private function getClient(): \Memcached { if ($this->client) { return $this->client; @@ -294,4 +330,14 @@ trait MemcachedTrait 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/advancedcontentfilter/vendor/symfony/cache/Traits/PdoTrait.php b/advancedcontentfilter/vendor/symfony/cache/Traits/PdoTrait.php index 917e8dd1..4d5e1230 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Traits/PdoTrait.php +++ b/advancedcontentfilter/vendor/symfony/cache/Traits/PdoTrait.php @@ -14,14 +14,22 @@ namespace Symfony\Component\Cache\Traits; use Doctrine\DBAL\Connection; use Doctrine\DBAL\DBALException; use Doctrine\DBAL\Driver\ServerInfoAwareConnection; +use Doctrine\DBAL\DriverManager; +use Doctrine\DBAL\Exception; +use Doctrine\DBAL\Exception\TableNotFoundException; +use Doctrine\DBAL\ParameterType; use Doctrine\DBAL\Schema\Schema; +use Doctrine\DBAL\Statement; use Symfony\Component\Cache\Exception\InvalidArgumentException; +use Symfony\Component\Cache\Marshaller\DefaultMarshaller; +use Symfony\Component\Cache\Marshaller\MarshallerInterface; /** * @internal */ trait PdoTrait { + private $marshaller; private $conn; private $dsn; private $driver; @@ -36,7 +44,7 @@ trait PdoTrait private $connectionOptions = []; private $namespace; - private function init($connOrDsn, $namespace, $defaultLifetime, array $options) + private function init($connOrDsn, string $namespace, int $defaultLifetime, array $options, ?MarshallerInterface $marshaller) { 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])); @@ -56,15 +64,16 @@ trait PdoTrait throw new InvalidArgumentException(sprintf('"%s" requires PDO or Doctrine\DBAL\Connection instance or DSN string as first argument, "%s" given.', __CLASS__, \is_object($connOrDsn) ? \get_class($connOrDsn) : \gettype($connOrDsn))); } - $this->table = isset($options['db_table']) ? $options['db_table'] : $this->table; - $this->idCol = isset($options['db_id_col']) ? $options['db_id_col'] : $this->idCol; - $this->dataCol = isset($options['db_data_col']) ? $options['db_data_col'] : $this->dataCol; - $this->lifetimeCol = isset($options['db_lifetime_col']) ? $options['db_lifetime_col'] : $this->lifetimeCol; - $this->timeCol = isset($options['db_time_col']) ? $options['db_time_col'] : $this->timeCol; - $this->username = isset($options['db_username']) ? $options['db_username'] : $this->username; - $this->password = isset($options['db_password']) ? $options['db_password'] : $this->password; - $this->connectionOptions = isset($options['db_connection_options']) ? $options['db_connection_options'] : $this->connectionOptions; + $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); } @@ -77,6 +86,7 @@ trait PdoTrait * * @throws \PDOException When the table already exists * @throws DBALException When the table already exists + * @throws Exception When the table already exists * @throws \DomainException When an unsupported PDO driver is used */ public function createTable() @@ -140,7 +150,7 @@ trait PdoTrait throw new \DomainException(sprintf('Creating the cache table is currently not implemented for PDO driver "%s".', $this->driver)); } - if (method_exists($conn, 'executeStatement')) { + if ($conn instanceof Connection && method_exists($conn, 'executeStatement')) { $conn->executeStatement($sql); } else { $conn->exec($sql); @@ -158,14 +168,35 @@ trait PdoTrait $deleteSql .= " AND $this->idCol LIKE :namespace"; } - $delete = $this->getConnection()->prepare($deleteSql); - $delete->bindValue(':time', time(), \PDO::PARAM_INT); + $connection = $this->getConnection(); + $useDbalConstants = $connection instanceof Connection; + + try { + $delete = $connection->prepare($deleteSql); + } catch (TableNotFoundException $e) { + return true; + } catch (\PDOException $e) { + return true; + } + $delete->bindValue(':time', time(), $useDbalConstants ? ParameterType::INTEGER : \PDO::PARAM_INT); if ('' !== $this->namespace) { - $delete->bindValue(':namespace', sprintf('%s%%', $this->namespace), \PDO::PARAM_STR); + $delete->bindValue(':namespace', sprintf('%s%%', $this->namespace), $useDbalConstants ? ParameterType::STRING : \PDO::PARAM_STR); } + try { + // Doctrine DBAL ^2.13 || >= 3.1 + if ($delete instanceof Statement && method_exists($delete, 'executeStatement')) { + $delete->executeStatement(); - return $delete->execute(); + return true; + } + + return $delete->execute(); + } catch (TableNotFoundException $e) { + return true; + } catch (\PDOException $e) { + return true; + } } /** @@ -173,13 +204,16 @@ trait PdoTrait */ protected function doFetch(array $ids) { + $connection = $this->getConnection(); + $useDbalConstants = $connection instanceof Connection; + $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 = $this->getConnection()->prepare($sql); - $stmt->bindValue($i = 1, $now, \PDO::PARAM_INT); + $stmt = $connection->prepare($sql); + $stmt->bindValue($i = 1, $now, $useDbalConstants ? ParameterType::INTEGER : \PDO::PARAM_INT); foreach ($ids as $id) { $stmt->bindValue(++$i, $id); } @@ -196,15 +230,15 @@ trait PdoTrait if (null === $row[1]) { $expired[] = $row[0]; } else { - yield $row[0] => parent::unserialize(\is_resource($row[1]) ? stream_get_contents($row[1]) : $row[1]); + 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 = $this->getConnection()->prepare($sql); - $stmt->bindValue($i = 1, $now, \PDO::PARAM_INT); + $stmt = $connection->prepare($sql); + $stmt->bindValue($i = 1, $now, $useDbalConstants ? ParameterType::INTEGER : \PDO::PARAM_INT); foreach ($expired as $id) { $stmt->bindValue(++$i, $id); } @@ -217,11 +251,14 @@ trait PdoTrait */ protected function doHave($id) { + $connection = $this->getConnection(); + $useDbalConstants = $connection instanceof Connection; + $sql = "SELECT 1 FROM $this->table WHERE $this->idCol = :id AND ($this->lifetimeCol IS NULL OR $this->lifetimeCol + $this->timeCol > :time)"; - $stmt = $this->getConnection()->prepare($sql); + $stmt = $connection->prepare($sql); $stmt->bindValue(':id', $id); - $stmt->bindValue(':time', time(), \PDO::PARAM_INT); + $stmt->bindValue(':time', time(), $useDbalConstants ? ParameterType::INTEGER : \PDO::PARAM_INT); $result = $stmt->execute(); return (bool) (\is_object($result) ? $result->fetchOne() : $stmt->fetchColumn()); @@ -244,10 +281,14 @@ trait PdoTrait $sql = "DELETE FROM $this->table WHERE $this->idCol LIKE '$namespace%'"; } - if (method_exists($conn, 'executeStatement')) { - $conn->executeStatement($sql); - } else { - $conn->exec($sql); + try { + if ($conn instanceof Connection && method_exists($conn, 'executeStatement')) { + $conn->executeStatement($sql); + } else { + $conn->exec($sql); + } + } catch (TableNotFoundException $e) { + } catch (\PDOException $e) { } return true; @@ -260,8 +301,12 @@ trait PdoTrait { $sql = str_pad('', (\count($ids) << 1) - 1, '?,'); $sql = "DELETE FROM $this->table WHERE $this->idCol IN ($sql)"; - $stmt = $this->getConnection()->prepare($sql); - $stmt->execute(array_values($ids)); + try { + $stmt = $this->getConnection()->prepare($sql); + $stmt->execute(array_values($ids)); + } catch (TableNotFoundException $e) { + } catch (\PDOException $e) { + } return true; } @@ -269,24 +314,15 @@ trait PdoTrait /** * {@inheritdoc} */ - protected function doSave(array $values, $lifetime) + protected function doSave(array $values, int $lifetime) { - $serialized = []; - $failed = []; - - foreach ($values as $id => $value) { - try { - $serialized[$id] = serialize($value); - } catch (\Exception $e) { - $failed[] = $id; - } - } - - if (!$serialized) { + if (!$values = $this->marshaller->marshall($values, $failed)) { return $failed; } $conn = $this->getConnection(); + $useDbalConstants = $conn instanceof Connection; + $driver = $this->driver; $insertSql = "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, :data, :lifetime, :time)"; @@ -321,39 +357,62 @@ trait PdoTrait $now = time(); $lifetime = $lifetime ?: null; - $stmt = $conn->prepare($sql); + try { + $stmt = $conn->prepare($sql); + } catch (TableNotFoundException $e) { + if (!$conn->isTransactionActive() || \in_array($this->driver, ['pgsql', 'sqlite', 'sqlsrv'], true)) { + $this->createTable(); + } + $stmt = $conn->prepare($sql); + } catch (\PDOException $e) { + if (!$conn->inTransaction() || \in_array($this->driver, ['pgsql', 'sqlite', 'sqlsrv'], true)) { + $this->createTable(); + } + $stmt = $conn->prepare($sql); + } 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); + $stmt->bindParam(3, $data, $useDbalConstants ? ParameterType::LARGE_OBJECT : \PDO::PARAM_LOB); + $stmt->bindValue(4, $lifetime, $useDbalConstants ? ParameterType::INTEGER : \PDO::PARAM_INT); + $stmt->bindValue(5, $now, $useDbalConstants ? ParameterType::INTEGER : \PDO::PARAM_INT); + $stmt->bindParam(6, $data, $useDbalConstants ? ParameterType::LARGE_OBJECT : \PDO::PARAM_LOB); + $stmt->bindValue(7, $lifetime, $useDbalConstants ? ParameterType::INTEGER : \PDO::PARAM_INT); + $stmt->bindValue(8, $now, $useDbalConstants ? ParameterType::INTEGER : \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); + $stmt->bindParam(':data', $data, $useDbalConstants ? ParameterType::LARGE_OBJECT : \PDO::PARAM_LOB); + $stmt->bindValue(':lifetime', $lifetime, $useDbalConstants ? ParameterType::INTEGER : \PDO::PARAM_INT); + $stmt->bindValue(':time', $now, $useDbalConstants ? ParameterType::INTEGER : \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); + $insertStmt->bindParam(':data', $data, $useDbalConstants ? ParameterType::LARGE_OBJECT : \PDO::PARAM_LOB); + $insertStmt->bindValue(':lifetime', $lifetime, $useDbalConstants ? ParameterType::INTEGER : \PDO::PARAM_INT); + $insertStmt->bindValue(':time', $now, $useDbalConstants ? ParameterType::INTEGER : \PDO::PARAM_INT); } - foreach ($serialized as $id => $data) { - $result = $stmt->execute(); - + foreach ($values as $id => $data) { + try { + $result = $stmt->execute(); + } catch (TableNotFoundException $e) { + if (!$conn->isTransactionActive() || \in_array($this->driver, ['pgsql', 'sqlite', 'sqlsrv'], true)) { + $this->createTable(); + } + $result = $stmt->execute(); + } catch (\PDOException $e) { + if (!$conn->inTransaction() || \in_array($this->driver, ['pgsql', 'sqlite', 'sqlsrv'], true)) { + $this->createTable(); + } + $result = $stmt->execute(); + } if (null === $driver && !(\is_object($result) ? $result->rowCount() : $stmt->rowCount())) { try { $insertStmt->execute(); - } catch (DBALException $e) { + } catch (DBALException|Exception $e) { } catch (\PDOException $e) { // A concurrent write won, let it be } @@ -369,8 +428,15 @@ trait PdoTrait private function getConnection() { if (null === $this->conn) { - $this->conn = new \PDO($this->dsn, $this->username, $this->password, $this->connectionOptions); - $this->conn->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); + if (strpos($this->dsn, '://')) { + if (!class_exists(DriverManager::class)) { + throw new InvalidArgumentException(sprintf('Failed to parse the DSN "%s". Try running "composer require doctrine/dbal".', $this->dsn)); + } + $this->conn = DriverManager::getConnection(['url' => $this->dsn]); + } else { + $this->conn = new \PDO($this->dsn, $this->username, $this->password, $this->connectionOptions); + $this->conn->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); + } } if (null === $this->driver) { if ($this->conn instanceof \PDO) { @@ -379,11 +445,9 @@ trait PdoTrait $driver = $this->conn->getDriver(); switch (true) { - case $driver instanceof \Doctrine\DBAL\Driver\AbstractMySQLDriver: - case $driver instanceof \Doctrine\DBAL\Driver\DrizzlePDOMySql\Driver: case $driver instanceof \Doctrine\DBAL\Driver\Mysqli\Driver: - case $driver instanceof \Doctrine\DBAL\Driver\PDOMySql\Driver: - case $driver instanceof \Doctrine\DBAL\Driver\PDO\MySQL\Driver: + throw new \LogicException(sprintf('The adapter "%s" does not support the mysqli driver, use pdo_mysql instead.', static::class)); + case $driver instanceof \Doctrine\DBAL\Driver\AbstractMySQLDriver: $this->driver = 'mysql'; break; case $driver instanceof \Doctrine\DBAL\Driver\PDOSqlite\Driver: @@ -404,6 +468,15 @@ trait PdoTrait case $driver instanceof \Doctrine\DBAL\Driver\PDO\SQLSrv\Driver: $this->driver = 'sqlsrv'; break; + case $driver instanceof \Doctrine\DBAL\Driver: + $this->driver = [ + 'mssql' => 'sqlsrv', + 'oracle' => 'oci', + 'postgresql' => 'pgsql', + 'sqlite' => 'sqlite', + 'mysql' => 'mysql', + ][$driver->getDatabasePlatform()->getName()] ?? \get_class($driver); + break; default: $this->driver = \get_class($driver); break; @@ -414,10 +487,7 @@ trait PdoTrait return $this->conn; } - /** - * @return string - */ - private function getServerVersion() + private function getServerVersion(): string { if (null === $this->serverVersion) { $conn = $this->conn instanceof \PDO ? $this->conn : $this->conn->getWrappedConnection(); diff --git a/advancedcontentfilter/vendor/symfony/cache/Traits/PhpArrayTrait.php b/advancedcontentfilter/vendor/symfony/cache/Traits/PhpArrayTrait.php index 972c7512..230c7bd4 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Traits/PhpArrayTrait.php +++ b/advancedcontentfilter/vendor/symfony/cache/Traits/PhpArrayTrait.php @@ -11,8 +11,10 @@ namespace Symfony\Component\Cache\Traits; +use Symfony\Component\Cache\Adapter\AdapterInterface; use Symfony\Component\Cache\CacheItem; use Symfony\Component\Cache\Exception\InvalidArgumentException; +use Symfony\Component\VarExporter\VarExporter; /** * @author Titouan Galopin @@ -25,8 +27,8 @@ trait PhpArrayTrait use ProxyTrait; private $file; + private $keys; private $values; - private $zendDetectUnicode; private static $valuesCache = []; @@ -57,56 +59,63 @@ trait PhpArrayTrait } } + $dumpedValues = ''; + $dumpedMap = []; $dump = <<<'EOF' $value) { CacheItem::validateKey(\is_int($key) ? (string) $key : $key); + $isStaticValue = true; - if (null === $value || \is_object($value)) { + if (null === $value) { + $value = "'N;'"; + } elseif (\is_object($value) || \is_array($value)) { try { - $value = serialize($value); + $value = VarExporter::export($value, $isStaticValue); } catch (\Exception $e) { - throw new InvalidArgumentException(sprintf('Cache key "%s" has non-serializable "%s" value.', $key, \get_class($value)), 0, $e); - } - } elseif (\is_array($value)) { - try { - $serialized = serialize($value); - $unserialized = unserialize($serialized); - } catch (\Exception $e) { - throw new InvalidArgumentException(sprintf('Cache key "%s" has non-serializable array value.', $key), 0, $e); - } - // Store arrays serialized if they contain any objects or references - if ($unserialized !== $value || (false !== strpos($serialized, ';R:') && preg_match('/;R:[1-9]/', $serialized))) { - $value = $serialized; + throw new InvalidArgumentException(sprintf('Cache key "%s" has non-serializable "%s" value.', $key, \is_object($value) ? \get_class($value) : 'array'), 0, $e); } } elseif (\is_string($value)) { - // Serialize strings if they could be confused with serialized objects or arrays - if ('N;' === $value || (isset($value[2]) && ':' === $value[1])) { - $value = serialize($value); + // Wrap "N;" in a closure to not confuse it with an encoded `null` + if ('N;' === $value) { + $isStaticValue = false; } - } elseif (!is_scalar($value)) { + $value = var_export($value, true); + } elseif (!\is_scalar($value)) { throw new InvalidArgumentException(sprintf('Cache key "%s" has non-serializable "%s" value.', $key, \gettype($value))); + } else { + $value = var_export($value, true); } - $dump .= var_export($key, true).' => '.var_export($value, true).",\n"; + if (!$isStaticValue) { + $value = str_replace("\n", "\n ", $value); + $value = "static function () {\n return {$value};\n}"; + } + $hash = hash('md5', $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"; - $dump = str_replace("' . \"\\0\" . '", "\0", $dump); + $dump .= "\n], [\n\n{$dumpedValues}\n]];\n"; $tmpFile = uniqid($this->file, true); file_put_contents($tmpFile, $dump); @chmod($tmpFile, 0666 & ~umask()); - unset($serialized, $unserialized, $value, $dump); + unset($serialized, $value, $dump); @rename($tmpFile, $this->file); unset(self::$valuesCache[$this->file]); @@ -116,14 +125,23 @@ EOF; /** * {@inheritdoc} + * + * @param string $prefix + * + * @return bool */ - public function clear() + public function clear(/* string $prefix = '' */) { - $this->values = []; + $prefix = 0 < \func_num_args() ? (string) func_get_arg(0) : ''; + $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; } @@ -133,20 +151,19 @@ EOF; private function initialize() { if (isset(self::$valuesCache[$this->file])) { - $this->values = self::$valuesCache[$this->file]; + $values = self::$valuesCache[$this->file]; + } elseif (!file_exists($this->file)) { + $this->keys = $this->values = []; return; + } else { + $values = self::$valuesCache[$this->file] = (include $this->file) ?: [[], []]; } - if ($this->zendDetectUnicode) { - $zmb = ini_set('zend.detect_unicode', 0); - } - try { - $this->values = self::$valuesCache[$this->file] = file_exists($this->file) ? (include $this->file ?: []) : []; - } finally { - if ($this->zendDetectUnicode) { - ini_set('zend.detect_unicode', $zmb); - } + if (2 !== \count($values) || !isset($values[0], $values[1])) { + $this->keys = $this->values = []; + } else { + [$this->keys, $this->values] = $values; } } } diff --git a/advancedcontentfilter/vendor/symfony/cache/Traits/PhpFilesTrait.php b/advancedcontentfilter/vendor/symfony/cache/Traits/PhpFilesTrait.php index 2668b26c..c76e7fe3 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Traits/PhpFilesTrait.php +++ b/advancedcontentfilter/vendor/symfony/cache/Traits/PhpFilesTrait.php @@ -13,6 +13,7 @@ namespace Symfony\Component\Cache\Traits; use Symfony\Component\Cache\Exception\CacheException; use Symfony\Component\Cache\Exception\InvalidArgumentException; +use Symfony\Component\VarExporter\VarExporter; /** * @author Piotr Stankowski @@ -23,14 +24,24 @@ use Symfony\Component\Cache\Exception\InvalidArgumentException; */ trait PhpFilesTrait { - use FilesystemCommonTrait; + use FilesystemCommonTrait { + doClear as private doCommonClear; + doDelete as private doCommonDelete; + } private $includeHandler; - private $zendDetectUnicode; + private $appendOnly; + private $values = []; + private $files = []; + + private static $startTime; + private static $valuesCache = []; public static function isSupported() { - return \function_exists('opcache_invalidate') && filter_var(ini_get('opcache.enable'), \FILTER_VALIDATE_BOOLEAN); + self::$startTime = self::$startTime ?? $_SERVER['REQUEST_TIME'] ?? time(); + + return \function_exists('opcache_invalidate') && filter_var(\ini_get('opcache.enable'), \FILTER_VALIDATE_BOOLEAN) && (!\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) || filter_var(\ini_get('opcache.enable_cli'), \FILTER_VALIDATE_BOOLEAN)); } /** @@ -40,19 +51,21 @@ trait PhpFilesTrait { $time = time(); $pruned = true; - $allowCompile = 'cli' !== \PHP_SAPI || filter_var(ini_get('opcache.enable_cli'), \FILTER_VALIDATE_BOOLEAN); + $getExpiry = true; set_error_handler($this->includeHandler); try { - foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->directory, \FilesystemIterator::SKIP_DOTS), \RecursiveIteratorIterator::LEAVES_ONLY) as $file) { - list($expiresAt) = include $file; + 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 = @unlink($file) && !file_exists($file) && $pruned; - - if ($allowCompile) { - @opcache_invalidate($file, true); - } + $pruned = $this->doUnlink($file) && !file_exists($file) && $pruned; } } } finally { @@ -67,41 +80,75 @@ trait PhpFilesTrait */ protected function doFetch(array $ids) { - $values = []; - $now = time(); - - if ($this->zendDetectUnicode) { - $zmb = ini_set('zend.detect_unicode', 0); + 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 { - foreach ($ids as $id) { + $getExpiry = true; + + foreach ($missingIds as $k => $id) { try { - $file = $this->getFile($id); - list($expiresAt, $values[$id]) = include $file; - if ($now >= $expiresAt) { - unset($values[$id]); + $file = $this->files[$id] ?? $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); } - } catch (\Exception $e) { - continue; + + if ($now >= $expiresAt) { + unset($this->values[$id], $missingIds[$k], self::$valuesCache[$file]); + } + } catch (\ErrorException $e) { + unset($missingIds[$k]); } } } finally { restore_error_handler(); - if ($this->zendDetectUnicode) { - ini_set('zend.detect_unicode', $zmb); - } } - foreach ($values as $id => $value) { - if ('N;' === $value) { - $values[$id] = null; - } elseif (\is_string($value) && isset($value[2]) && ':' === $value[1]) { - $values[$id] = parent::unserialize($value); - } - } - - return $values; + $ids = $missingIds; + $missingIds = []; + goto begin; } /** @@ -109,44 +156,94 @@ trait PhpFilesTrait */ protected function doHave($id) { - return (bool) $this->doFetch([$id]); + if ($this->appendOnly && isset($this->values[$id])) { + return true; + } + + set_error_handler($this->includeHandler); + try { + $file = $this->files[$id] ?? $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 $e) { + return false; + } finally { + restore_error_handler(); + } + if ($this->appendOnly) { + $now = 0; + $this->values[$id] = $value; + } else { + $now = time(); + } + + return $now < $expiresAt; } /** * {@inheritdoc} */ - protected function doSave(array $values, $lifetime) + protected function doSave(array $values, int $lifetime) { $ok = true; - $data = [$lifetime ? time() + $lifetime : \PHP_INT_MAX, '']; - $allowCompile = 'cli' !== \PHP_SAPI || filter_var(ini_get('opcache.enable_cli'), \FILTER_VALIDATE_BOOLEAN); + $expiry = $lifetime ? time() + $lifetime : 'PHP_INT_MAX'; + $allowCompile = self::isSupported(); foreach ($values as $key => $value) { - if (null === $value || \is_object($value)) { - $value = serialize($value); - } elseif (\is_array($value)) { - $serialized = serialize($value); - $unserialized = parent::unserialize($serialized); - // Store arrays serialized if they contain any objects or references - if ($unserialized !== $value || (false !== strpos($serialized, ';R:') && preg_match('/;R:[1-9]/', $serialized))) { - $value = $serialized; + 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, \is_object($value) ? \get_class($value) : 'array'), 0, $e); } } elseif (\is_string($value)) { - // Serialize strings if they could be confused with serialized objects or arrays - if ('N;' === $value || (isset($value[2]) && ':' === $value[1])) { - $value = serialize($value); + // Wrap "N;" in a closure to not confuse it with an encoded `null` + if ('N;' === $value) { + $isStaticValue = false; } - } elseif (!is_scalar($value)) { + $value = var_export($value, true); + } elseif (!\is_scalar($value)) { throw new InvalidArgumentException(sprintf('Cache key "%s" has non-serializable "%s" value.', $key, \gettype($value))); + } else { + $value = var_export($value, true); } - $data[1] = $value; - $file = $this->getFile($key, true); - $ok = $this->write($file, 'appendOnly) { + $value = "return [{$expiry}, static function () { return {$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)) { @@ -155,4 +252,62 @@ trait PhpFilesTrait return $ok; } + + /** + * {@inheritdoc} + */ + protected function doClear($namespace) + { + $this->values = []; + + return $this->doCommonClear($namespace); + } + + /** + * {@inheritdoc} + */ + protected function doDelete(array $ids) + { + foreach ($ids as $id) { + unset($this->values[$id]); + } + + return $this->doCommonDelete($ids); + } + + protected function doUnlink($file) + { + 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 $file; + + public function __construct(string $file) + { + $this->file = $file; + } } diff --git a/advancedcontentfilter/vendor/symfony/cache/Traits/ProxyTrait.php b/advancedcontentfilter/vendor/symfony/cache/Traits/ProxyTrait.php index d9e085b9..c86f360a 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Traits/ProxyTrait.php +++ b/advancedcontentfilter/vendor/symfony/cache/Traits/ProxyTrait.php @@ -12,7 +12,7 @@ namespace Symfony\Component\Cache\Traits; use Symfony\Component\Cache\PruneableInterface; -use Symfony\Component\Cache\ResettableInterface; +use Symfony\Contracts\Service\ResetInterface; /** * @author Nicolas Grekas @@ -36,7 +36,7 @@ trait ProxyTrait */ public function reset() { - if ($this->pool instanceof ResettableInterface) { + if ($this->pool instanceof ResetInterface) { $this->pool->reset(); } } diff --git a/advancedcontentfilter/vendor/symfony/cache/Traits/RedisClusterNodeProxy.php b/advancedcontentfilter/vendor/symfony/cache/Traits/RedisClusterNodeProxy.php new file mode 100644 index 00000000..deba74f6 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Traits/RedisClusterNodeProxy.php @@ -0,0 +1,53 @@ + + * + * 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 +{ + private $host; + private $redis; + + /** + * @param \RedisCluster|RedisClusterProxy $redis + */ + public function __construct(array $host, $redis) + { + $this->host = $host; + $this->redis = $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/advancedcontentfilter/vendor/symfony/cache/Traits/RedisClusterProxy.php b/advancedcontentfilter/vendor/symfony/cache/Traits/RedisClusterProxy.php new file mode 100644 index 00000000..b4cef59a --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Traits/RedisClusterProxy.php @@ -0,0 +1,63 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Traits; + +/** + * @author Alessandro Chitolina + * + * @internal + */ +class RedisClusterProxy +{ + private $redis; + private $initializer; + + public function __construct(\Closure $initializer) + { + $this->initializer = $initializer; + } + + public function __call($method, array $args) + { + $this->redis ?: $this->redis = $this->initializer->__invoke(); + + return $this->redis->{$method}(...$args); + } + + public function hscan($strKey, &$iIterator, $strPattern = null, $iCount = null) + { + $this->redis ?: $this->redis = $this->initializer->__invoke(); + + return $this->redis->hscan($strKey, $iIterator, $strPattern, $iCount); + } + + public function scan(&$iIterator, $strPattern = null, $iCount = null) + { + $this->redis ?: $this->redis = $this->initializer->__invoke(); + + return $this->redis->scan($iIterator, $strPattern, $iCount); + } + + public function sscan($strKey, &$iIterator, $strPattern = null, $iCount = null) + { + $this->redis ?: $this->redis = $this->initializer->__invoke(); + + return $this->redis->sscan($strKey, $iIterator, $strPattern, $iCount); + } + + public function zscan($strKey, &$iIterator, $strPattern = null, $iCount = null) + { + $this->redis ?: $this->redis = $this->initializer->__invoke(); + + return $this->redis->zscan($strKey, $iIterator, $strPattern, $iCount); + } +} diff --git a/advancedcontentfilter/vendor/symfony/cache/Traits/RedisProxy.php b/advancedcontentfilter/vendor/symfony/cache/Traits/RedisProxy.php index 98ea3aba..2b0b8573 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Traits/RedisProxy.php +++ b/advancedcontentfilter/vendor/symfony/cache/Traits/RedisProxy.php @@ -32,7 +32,7 @@ class RedisProxy { $this->ready ?: $this->ready = $this->initializer->__invoke($this->redis); - return \call_user_func_array([$this->redis, $method], $args); + return $this->redis->{$method}(...$args); } public function hscan($strKey, &$iIterator, $strPattern = null, $iCount = null) diff --git a/advancedcontentfilter/vendor/symfony/cache/Traits/RedisTrait.php b/advancedcontentfilter/vendor/symfony/cache/Traits/RedisTrait.php index a30d6d3f..dabdde4e 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Traits/RedisTrait.php +++ b/advancedcontentfilter/vendor/symfony/cache/Traits/RedisTrait.php @@ -13,10 +13,13 @@ namespace Symfony\Component\Cache\Traits; use Predis\Connection\Aggregate\ClusterInterface; use Predis\Connection\Aggregate\RedisCluster; -use Predis\Connection\Factory; +use Predis\Connection\Aggregate\ReplicationInterface; +use Predis\Response\ErrorInterface; use Predis\Response\Status; 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 @@ -33,24 +36,40 @@ trait RedisTrait 'timeout' => 30, 'read_timeout' => 0, 'retry_interval' => 0, - 'lazy' => false, + '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; + private $marshaller; /** - * @param \Redis|\RedisArray|\RedisCluster|\Predis\Client $redisClient + * @param \Redis|\RedisArray|\RedisCluster|\Predis\ClientInterface|RedisProxy|RedisClusterProxy $redis */ - private function init($redisClient, $namespace = '', $defaultLifetime = 0) + private function init($redis, string $namespace, int $defaultLifetime, ?MarshallerInterface $marshaller) { 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 (!$redisClient instanceof \Redis && !$redisClient instanceof \RedisArray && !$redisClient instanceof \RedisCluster && !$redisClient instanceof \Predis\Client && !$redisClient instanceof RedisProxy) { - throw new InvalidArgumentException(sprintf('"%s()" expects parameter 1 to be Redis, RedisArray, RedisCluster or Predis\Client, "%s" given.', __METHOD__, \is_object($redisClient) ? \get_class($redisClient) : \gettype($redisClient))); + + if (!$redis instanceof \Redis && !$redis instanceof \RedisArray && !$redis instanceof \RedisCluster && !$redis instanceof \Predis\ClientInterface && !$redis instanceof RedisProxy && !$redis instanceof RedisClusterProxy) { + throw new InvalidArgumentException(sprintf('"%s()" expects parameter 1 to be Redis, RedisArray, RedisCluster or Predis\ClientInterface, "%s" given.', __METHOD__, \is_object($redis) ? \get_class($redis) : \gettype($redis))); } - $this->redis = $redisClient; + + 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(); } /** @@ -68,57 +87,117 @@ trait RedisTrait * * @throws InvalidArgumentException when the DSN is invalid * - * @return \Redis|\Predis\Client According to the "class" option + * @return \Redis|\RedisCluster|RedisClusterProxy|RedisProxy|\Predis\ClientInterface According to the "class" option */ public static function createConnection($dsn, array $options = []) { - if (0 !== strpos($dsn, 'redis://')) { - throw new InvalidArgumentException(sprintf('Invalid Redis DSN: "%s" does not start with "redis://".', $dsn)); + if (str_starts_with($dsn, 'redis:')) { + $scheme = 'redis'; + } elseif (str_starts_with($dsn, 'rediss:')) { + $scheme = 'rediss'; + } else { + throw new InvalidArgumentException(sprintf('Invalid Redis DSN: "%s" does not start with "redis:" or "rediss".', $dsn)); } - $params = preg_replace_callback('#^redis://(?:(?:[^:@]*+:)?([^@]*+)@)?#', function ($m) use (&$auth) { - if (isset($m[1])) { - $auth = $m[1]; + + if (!\extension_loaded('redis') && !class_exists(\Predis\Client::class)) { + throw new CacheException(sprintf('Cannot find the "redis" extension nor the "predis/predis" package: "%s".', $dsn)); + } + + $params = preg_replace_callback('#^'.$scheme.':(//)?(?:(?:[^:@]*+:)?([^@]*+)@)?#', function ($m) use (&$auth) { + if (isset($m[2])) { + $auth = $m[2]; + + if ('' === $auth) { + $auth = null; + } } - return 'file://'; + return 'file:'.($m[1] ?? ''); }, $dsn); + if (false === $params = parse_url($params)) { throw new InvalidArgumentException(sprintf('Invalid Redis DSN: "%s".', $dsn)); } - if (!isset($params['host']) && !isset($params['path'])) { - throw new InvalidArgumentException(sprintf('Invalid Redis DSN: "%s".', $dsn)); - } - if (isset($params['path']) && preg_match('#/(\d+)$#', $params['path'], $m)) { - $params['dbindex'] = $m[1]; - $params['path'] = substr($params['path'], 0, -\strlen($m[0])); - } - if (isset($params['host'])) { - $scheme = 'tcp'; - } else { - $scheme = 'unix'; - } - $params += [ - 'host' => isset($params['host']) ? $params['host'] : $params['path'], - 'port' => isset($params['host']) ? 6379 : null, - 'dbindex' => 0, - ]; + + $query = $hosts = []; + + $tls = 'rediss' === $scheme; + $tcpScheme = $tls ? 'tls' : 'tcp'; + if (isset($params['query'])) { parse_str($params['query'], $query); - $params += $query; + + if (isset($query['host'])) { + if (!\is_array($hosts = $query['host'])) { + throw new InvalidArgumentException(sprintf('Invalid Redis DSN: "%s".', $dsn)); + } + 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); + } } - $params += $options + self::$defaultConnectionOptions; - if (null === $params['class'] && !\extension_loaded('redis') && !class_exists(\Predis\Client::class)) { - throw new CacheException(sprintf('Cannot find the "redis" extension, and "predis/predis" is not installed: "%s".', $dsn)); + + 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]; + $params['path'] = substr($params['path'], 0, -\strlen($m[0])); + } elseif (isset($params['host'])) { + throw new InvalidArgumentException(sprintf('Invalid Redis DSN: "%s", the "dbindex" parameter must be a number.', $dsn)); + } + } + + 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(sprintf('Invalid Redis DSN: "%s".', $dsn)); + } + + $params += $query + $options + self::$defaultConnectionOptions; + + if (isset($params['redis_sentinel']) && !class_exists(\Predis\Client::class)) { + throw new CacheException(sprintf('Redis Sentinel support requires the "predis/predis" package: "%s".', $dsn)); + } + + if (null === $params['class'] && !isset($params['redis_sentinel']) && \extension_loaded('redis')) { + $class = $params['redis_cluster'] ? \RedisCluster::class : (1 < \count($hosts) ? \RedisArray::class : \Redis::class); + } else { + $class = $params['class'] ?? \Predis\Client::class; + + if (isset($params['redis_sentinel']) && !is_a($class, \Predis\Client::class, true)) { + throw new CacheException(sprintf('Cannot use Redis Sentinel: class "%s" does not extend "Predis\Client": "%s".', $class, $dsn)); + } } - $class = null === $params['class'] ? (\extension_loaded('redis') ? \Redis::class : \Predis\Client::class) : $params['class']; if (is_a($class, \Redis::class, true)) { $connect = $params['persistent'] || $params['persistent_id'] ? 'pconnect' : 'connect'; $redis = new $class(); - $initializer = function ($redis) use ($connect, $params, $dsn, $auth) { + $initializer = static function ($redis) use ($connect, $params, $dsn, $auth, $hosts, $tls) { + $host = $hosts[0]['host'] ?? $hosts[0]['path']; + $port = $hosts[0]['port'] ?? 0; + + if (isset($hosts[0]['host']) && $tls) { + $host = 'tls://'.$host; + } + try { - @$redis->{$connect}($params['host'], $params['port'], $params['timeout'], $params['persistent_id'], $params['retry_interval']); + @$redis->{$connect}($host, $port, $params['timeout'], (string) $params['persistent_id'], $params['retry_interval'], $params['read_timeout'], ...\defined('Redis::SCAN_PREFIX') ? [['stream' => $params['ssl'] ?? null]] : []); set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; }); $isConnected = $redis->isConnected(); @@ -130,11 +209,14 @@ trait RedisTrait if ((null !== $auth && !$redis->auth($auth)) || ($params['dbindex'] && !$redis->select($params['dbindex'])) - || ($params['read_timeout'] && !$redis->setOption(\Redis::OPT_READ_TIMEOUT, $params['read_timeout'])) ) { $e = preg_replace('/^ERR /', '', $redis->getLastError()); throw new InvalidArgumentException(sprintf('Redis connection "%s" failed: ', $dsn).$e.'.'); } + + if (0 < $params['tcp_keepalive'] && \defined('Redis::OPT_TCP_KEEPALIVE')) { + $redis->setOption(\Redis::OPT_TCP_KEEPALIVE, $params['tcp_keepalive']); + } } catch (\RedisException $e) { throw new InvalidArgumentException(sprintf('Redis connection "%s" failed: ', $dsn).$e->getMessage()); } @@ -147,13 +229,92 @@ trait RedisTrait } else { $initializer($redis); } - } elseif (is_a($class, \Predis\Client::class, true)) { - $params['scheme'] = $scheme; - $params['database'] = $params['dbindex'] ?: null; - $params['password'] = $auth; - $redis = new $class((new Factory())->create($params)); + } elseif (is_a($class, \RedisArray::class, true)) { + foreach ($hosts as $i => $host) { + switch ($host['scheme']) { + case 'tcp': $hosts[$i] = $host['host'].':'.$host['port']; break; + case 'tls': $hosts[$i] = 'tls://'.$host['host'].':'.$host['port']; break; + default: $hosts[$i] = $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(sprintf('Redis connection "%s" failed: ', $dsn).$e->getMessage()); + } + + if (0 < $params['tcp_keepalive'] && \defined('Redis::OPT_TCP_KEEPALIVE')) { + $redis->setOption(\Redis::OPT_TCP_KEEPALIVE, $params['tcp_keepalive']); + } + } elseif (is_a($class, \RedisCluster::class, true)) { + $initializer = static function () use ($class, $params, $dsn, $hosts) { + foreach ($hosts as $i => $host) { + switch ($host['scheme']) { + case 'tcp': $hosts[$i] = $host['host'].':'.$host['port']; break; + case 'tls': $hosts[$i] = 'tls://'.$host['host'].':'.$host['port']; break; + default: $hosts[$i] = $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(sprintf('Redis connection "%s" failed: ', $dsn).$e->getMessage()); + } + + if (0 < $params['tcp_keepalive'] && \defined('Redis::OPT_TCP_KEEPALIVE')) { + $redis->setOption(\Redis::OPT_TCP_KEEPALIVE, $params['tcp_keepalive']); + } + switch ($params['failover']) { + case 'error': $redis->setOption(\RedisCluster::OPT_SLAVE_FAILOVER, \RedisCluster::FAILOVER_ERROR); break; + case 'distribute': $redis->setOption(\RedisCluster::OPT_SLAVE_FAILOVER, \RedisCluster::FAILOVER_DISTRIBUTE); break; + case 'slaves': $redis->setOption(\RedisCluster::OPT_SLAVE_FAILOVER, \RedisCluster::FAILOVER_DISTRIBUTE_SLAVES); break; + } + + return $redis; + }; + + $redis = $params['lazy'] ? new RedisClusterProxy($initializer) : $initializer(); + } elseif (is_a($class, \Predis\ClientInterface::class, true)) { + if ($params['redis_cluster']) { + $params['cluster'] = 'redis'; + if (isset($params['redis_sentinel'])) { + throw new InvalidArgumentException(sprintf('Cannot use both "redis_cluster" and "redis_sentinel" at the same time: "%s".', $dsn)); + } + } 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) { + $params['parameters']['password'] = $auth; + } + 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, array_diff_key(self::$defaultConnectionOptions, ['ssl' => null]))); + 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" or "Predis\Client".', $class)); + throw new InvalidArgumentException(sprintf('"%s" is not a subclass of "Redis", "RedisArray", "RedisCluster" nor "Predis\ClientInterface".', $class)); } else { throw new InvalidArgumentException(sprintf('Class "%s" does not exist.', $class)); } @@ -172,7 +333,7 @@ trait RedisTrait $result = []; - if ($this->redis instanceof \Predis\Client && $this->redis->getConnection() instanceof ClusterInterface) { + if ($this->redis instanceof \Predis\ClientInterface && $this->redis->getConnection() instanceof ClusterInterface) { $values = $this->pipeline(function () use ($ids) { foreach ($ids as $id) { yield 'get' => [$id]; @@ -190,7 +351,7 @@ trait RedisTrait foreach ($values as $id => $v) { if ($v) { - $result[$id] = parent::unserialize($v); + $result[$id] = $this->marshaller->unmarshall($v); } } @@ -210,32 +371,19 @@ trait RedisTrait */ protected function doClear($namespace) { - $cleared = true; - $hosts = [$this->redis]; - $evalArgs = [[$namespace], 0]; - - if ($this->redis instanceof \Predis\Client) { - $evalArgs = [0, $namespace]; - - $connection = $this->redis->getConnection(); - if ($connection instanceof ClusterInterface && $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[] = $h = new \Redis(); - $h->connect($host[0], $host[1]); - } + 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; @@ -243,24 +391,36 @@ trait RedisTrait } $info = $host->info('Server'); - $info = isset($info['Server']) ? $info['Server'] : $info; + $info = !$info instanceof ErrorInterface ? $info['Server'] ?? $info : ['redis_version' => '2.0']; + + if (!$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. - $cleared = $host->eval("local keys=redis.call('KEYS',ARGV[1]..'*') for i=1,#keys,5000 do redis.call('DEL',unpack(keys,i,math.min(i+4999,#keys))) end return 1", $evalArgs[0], $evalArgs[1]) && $cleared; + $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('DEL',unpack(keys,i,math.min(i+4999,#keys))) end return 1", $args[0], $args[1]) && $cleared; continue; } $cursor = null; do { - $keys = $host instanceof \Predis\Client ? $host->scan($cursor, 'MATCH', $namespace.'*', 'COUNT', 1000) : $host->scan($cursor, $namespace.'*', 1000); + $keys = $host instanceof \Predis\ClientInterface ? $host->scan($cursor, '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 = (int) $cursor); @@ -278,7 +438,7 @@ trait RedisTrait return true; } - if ($this->redis instanceof \Predis\Client && $this->redis->getConnection() instanceof ClusterInterface) { + if ($this->redis instanceof \Predis\ClientInterface && $this->redis->getConnection() instanceof ClusterInterface) { $this->pipeline(function () use ($ids) { foreach ($ids as $id) { yield 'del' => [$id]; @@ -294,25 +454,14 @@ trait RedisTrait /** * {@inheritdoc} */ - protected function doSave(array $values, $lifetime) + protected function doSave(array $values, int $lifetime) { - $serialized = []; - $failed = []; - - foreach ($values as $id => $value) { - try { - $serialized[$id] = serialize($value); - } catch (\Exception $e) { - $failed[] = $id; - } - } - - if (!$serialized) { + if (!$values = $this->marshaller->marshall($values, $failed)) { return $failed; } - $results = $this->pipeline(function () use ($serialized, $lifetime) { - foreach ($serialized as $id => $value) { + $results = $this->pipeline(function () use ($values, $lifetime) { + foreach ($values as $id => $value) { if (0 >= $lifetime) { yield 'set' => [$id, $value]; } else { @@ -320,8 +469,9 @@ trait RedisTrait } } }); + foreach ($results as $id => $result) { - if (true !== $result && (!$result instanceof Status || $result !== Status::get('OK'))) { + if (true !== $result && (!$result instanceof Status || Status::get('OK') !== $result)) { $failed[] = $id; } } @@ -329,54 +479,87 @@ trait RedisTrait return $failed; } - private function pipeline(\Closure $generator) + private function pipeline(\Closure $generator, $redis = null): \Generator { $ids = []; + $redis = $redis ?? $this->redis; - if ($this->redis instanceof \RedisCluster || ($this->redis instanceof \Predis\Client && $this->redis->getConnection() instanceof RedisCluster)) { + if ($redis instanceof RedisClusterProxy || $redis instanceof \RedisCluster || ($redis instanceof \Predis\ClientInterface && $redis->getConnection() instanceof RedisCluster)) { // 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[] = \call_user_func_array([$this->redis, $command], $args); - $ids[] = $args[0]; + $results[] = $redis->{$command}(...$args); + $ids[] = 'eval' === $command ? ($redis instanceof \Predis\ClientInterface ? $args[2] : $args[1][0]) : $args[0]; } - } elseif ($this->redis instanceof \Predis\Client) { - $results = $this->redis->pipeline(function ($redis) use ($generator, &$ids) { + } elseif ($redis instanceof \Predis\ClientInterface) { + $results = $redis->pipeline(static function ($redis) use ($generator, &$ids) { foreach ($generator() as $command => $args) { - \call_user_func_array([$redis, $command], $args); - $ids[] = $args[0]; + $redis->{$command}(...$args); + $ids[] = 'eval' === $command ? $args[2] : $args[0]; } }); - } elseif ($this->redis instanceof \RedisArray) { + } elseif ($redis instanceof \RedisArray) { $connections = $results = $ids = []; foreach ($generator() as $command => $args) { - if (!isset($connections[$h = $this->redis->_target($args[0])])) { - $connections[$h] = [$this->redis->_instance($h), -1]; + $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); } - \call_user_func_array([$connections[$h][0], $command], $args); + $connections[$h][0]->{$command}(...$args); $results[] = [$h, ++$connections[$h][1]]; - $ids[] = $args[0]; + $ids[] = $id; } foreach ($connections as $h => $c) { $connections[$h] = $c[0]->exec(); } - foreach ($results as $k => list($h, $c)) { + foreach ($results as $k => [$h, $c]) { $results[$k] = $connections[$h][$c]; } } else { - $this->redis->multi(\Redis::PIPELINE); + $redis->multi(\Redis::PIPELINE); foreach ($generator() as $command => $args) { - \call_user_func_array([$this->redis, $command], $args); - $ids[] = $args[0]; + $redis->{$command}(...$args); + $ids[] = 'eval' === $command ? $args[1][0] : $args[0]; } - $results = $this->redis->exec(); + $results = $redis->exec(); + } + + if (!$redis instanceof \Predis\ClientInterface && 'eval' === $command && $redis->getLastError()) { + $e = new \RedisException($redis->getLastError()); + $results = array_map(function ($v) use ($e) { return false === $v ? $e : $v; }, $results); } 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 \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 RedisClusterProxy || $this->redis instanceof \RedisCluster) { + $hosts = []; + foreach ($this->redis->_masters() as $host) { + $hosts[] = new RedisClusterNodeProxy($host, $this->redis); + } + } + + return $hosts; + } } diff --git a/advancedcontentfilter/vendor/symfony/cache/composer.json b/advancedcontentfilter/vendor/symfony/cache/composer.json index f412e4f1..7a9e8df5 100644 --- a/advancedcontentfilter/vendor/symfony/cache/composer.json +++ b/advancedcontentfilter/vendor/symfony/cache/composer.json @@ -1,7 +1,7 @@ { "name": "symfony/cache", "type": "library", - "description": "Symfony Cache component with PSR-6, PSR-16, and tags", + "description": "Provides extended PSR-6, PSR-16 (and tags) implementations", "keywords": ["caching", "psr6"], "homepage": "https://symfony.com", "license": "MIT", @@ -16,24 +16,37 @@ } ], "provide": { - "psr/cache-implementation": "1.0", - "psr/simple-cache-implementation": "1.0" + "psr/cache-implementation": "1.0|2.0", + "psr/simple-cache-implementation": "1.0|2.0", + "symfony/cache-implementation": "1.0|2.0" }, "require": { - "php": "^5.5.9|>=7.0.8", - "psr/cache": "~1.0", - "psr/log": "~1.0", - "psr/simple-cache": "^1.0", - "symfony/polyfill-apcu": "~1.1" + "php": ">=7.1.3", + "psr/cache": "^1.0|^2.0", + "psr/log": "^1|^2|^3", + "symfony/cache-contracts": "^1.1.7|^2", + "symfony/polyfill-php73": "^1.9", + "symfony/polyfill-php80": "^1.16", + "symfony/service-contracts": "^1.1|^2", + "symfony/var-exporter": "^4.2|^5.0" }, "require-dev": { "cache/integration-tests": "dev-master", - "doctrine/cache": "^1.6", - "doctrine/dbal": "^2.4|^3.0", - "predis/predis": "^1.0" + "doctrine/cache": "^1.6|^2.0", + "doctrine/dbal": "^2.7|^3.0", + "predis/predis": "^1.1", + "psr/simple-cache": "^1.0|^2.0", + "symfony/config": "^4.2|^5.0", + "symfony/dependency-injection": "^3.4|^4.1|^5.0", + "symfony/filesystem": "^4.4|^5.0", + "symfony/http-kernel": "^4.4", + "symfony/var-dumper": "^4.4|^5.0" }, "conflict": { - "symfony/var-dumper": "<3.3" + "doctrine/dbal": "<2.7", + "symfony/dependency-injection": "<3.4", + "symfony/http-kernel": "<4.4|>=5.0", + "symfony/var-dumper": "<4.4" }, "autoload": { "psr-4": { "Symfony\\Component\\Cache\\": "" }, diff --git a/advancedcontentfilter/vendor/symfony/deprecation-contracts/.gitignore b/advancedcontentfilter/vendor/symfony/deprecation-contracts/.gitignore new file mode 100644 index 00000000..c49a5d8d --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/deprecation-contracts/.gitignore @@ -0,0 +1,3 @@ +vendor/ +composer.lock +phpunit.xml diff --git a/advancedcontentfilter/vendor/symfony/deprecation-contracts/CHANGELOG.md b/advancedcontentfilter/vendor/symfony/deprecation-contracts/CHANGELOG.md new file mode 100644 index 00000000..7932e261 --- /dev/null +++ b/advancedcontentfilter/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/advancedcontentfilter/vendor/symfony/deprecation-contracts/LICENSE b/advancedcontentfilter/vendor/symfony/deprecation-contracts/LICENSE new file mode 100644 index 00000000..406242ff --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/deprecation-contracts/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2020-2022 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/advancedcontentfilter/vendor/symfony/deprecation-contracts/README.md b/advancedcontentfilter/vendor/symfony/deprecation-contracts/README.md new file mode 100644 index 00000000..4957933a --- /dev/null +++ b/advancedcontentfilter/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 necessarily recommended, the deprecation notices can be completely ignored by declaring an empty +`function trigger_deprecation() {}` in your application. diff --git a/advancedcontentfilter/vendor/symfony/deprecation-contracts/composer.json b/advancedcontentfilter/vendor/symfony/deprecation-contracts/composer.json new file mode 100644 index 00000000..cc7cc123 --- /dev/null +++ b/advancedcontentfilter/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": ">=7.1" + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-main": "2.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + } +} diff --git a/advancedcontentfilter/vendor/symfony/deprecation-contracts/function.php b/advancedcontentfilter/vendor/symfony/deprecation-contracts/function.php new file mode 100644 index 00000000..d4371504 --- /dev/null +++ b/advancedcontentfilter/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, ...$args): void + { + @trigger_error(($package || $version ? "Since $package $version: " : '').($args ? vsprintf($message, $args) : $message), \E_USER_DEPRECATED); + } +} diff --git a/advancedcontentfilter/vendor/symfony/polyfill-php73/LICENSE b/advancedcontentfilter/vendor/symfony/polyfill-php73/LICENSE new file mode 100644 index 00000000..7536caea --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/polyfill-php73/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/advancedcontentfilter/vendor/symfony/polyfill-php73/Php73.php b/advancedcontentfilter/vendor/symfony/polyfill-php73/Php73.php new file mode 100644 index 00000000..65c35a6a --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/polyfill-php73/Php73.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Polyfill\Php73; + +/** + * @author Gabriel Caruso + * @author Ion Bazan + * + * @internal + */ +final class Php73 +{ + public static $startAt = 1533462603; + + /** + * @param bool $asNum + * + * @return array|float|int + */ + public static function hrtime($asNum = false) + { + $ns = microtime(false); + $s = substr($ns, 11) - self::$startAt; + $ns = 1E9 * (float) $ns; + + if ($asNum) { + $ns += $s * 1E9; + + return \PHP_INT_SIZE === 4 ? $ns : (int) $ns; + } + + return [$s, (int) $ns]; + } +} diff --git a/advancedcontentfilter/vendor/symfony/polyfill-php73/README.md b/advancedcontentfilter/vendor/symfony/polyfill-php73/README.md new file mode 100644 index 00000000..032fafbd --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/polyfill-php73/README.md @@ -0,0 +1,18 @@ +Symfony Polyfill / Php73 +======================== + +This component provides functions added to PHP 7.3 core: + +- [`array_key_first`](https://php.net/array_key_first) +- [`array_key_last`](https://php.net/array_key_last) +- [`hrtime`](https://php.net/function.hrtime) +- [`is_countable`](https://php.net/is_countable) +- [`JsonException`](https://php.net/JsonException) + +More information can be found in the +[main Polyfill README](https://github.com/symfony/polyfill/blob/main/README.md). + +License +======= + +This library is released under the [MIT license](LICENSE). diff --git a/advancedcontentfilter/vendor/symfony/polyfill-php73/Resources/stubs/JsonException.php b/advancedcontentfilter/vendor/symfony/polyfill-php73/Resources/stubs/JsonException.php new file mode 100644 index 00000000..f06d6c26 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/polyfill-php73/Resources/stubs/JsonException.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +if (\PHP_VERSION_ID < 70300) { + class JsonException extends Exception + { + } +} diff --git a/advancedcontentfilter/vendor/symfony/polyfill-php73/bootstrap.php b/advancedcontentfilter/vendor/symfony/polyfill-php73/bootstrap.php new file mode 100644 index 00000000..d6b21538 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/polyfill-php73/bootstrap.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Polyfill\Php73 as p; + +if (\PHP_VERSION_ID >= 70300) { + return; +} + +if (!function_exists('is_countable')) { + function is_countable($value) { return is_array($value) || $value instanceof Countable || $value instanceof ResourceBundle || $value instanceof SimpleXmlElement; } +} +if (!function_exists('hrtime')) { + require_once __DIR__.'/Php73.php'; + p\Php73::$startAt = (int) microtime(true); + function hrtime($as_number = false) { return p\Php73::hrtime($as_number); } +} +if (!function_exists('array_key_first')) { + function array_key_first(array $array) { foreach ($array as $key => $value) { return $key; } } +} +if (!function_exists('array_key_last')) { + function array_key_last(array $array) { return key(array_slice($array, -1, 1, true)); } +} diff --git a/advancedcontentfilter/vendor/symfony/polyfill-php73/composer.json b/advancedcontentfilter/vendor/symfony/polyfill-php73/composer.json new file mode 100644 index 00000000..3d47d154 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/polyfill-php73/composer.json @@ -0,0 +1,33 @@ +{ + "name": "symfony/polyfill-php73", + "type": "library", + "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", + "keywords": ["polyfill", "shim", "compatibility", "portable"], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": ">=7.1" + }, + "autoload": { + "psr-4": { "Symfony\\Polyfill\\Php73\\": "" }, + "files": [ "bootstrap.php" ], + "classmap": [ "Resources/stubs" ] + }, + "minimum-stability": "dev", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + } +} diff --git a/advancedcontentfilter/vendor/symfony/polyfill-php80/LICENSE b/advancedcontentfilter/vendor/symfony/polyfill-php80/LICENSE new file mode 100644 index 00000000..0ed3a246 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/polyfill-php80/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/advancedcontentfilter/vendor/symfony/polyfill-php80/Php80.php b/advancedcontentfilter/vendor/symfony/polyfill-php80/Php80.php new file mode 100644 index 00000000..362dd1a9 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/polyfill-php80/Php80.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\Polyfill\Php80; + +/** + * @author Ion Bazan + * @author Nico Oelgart + * @author Nicolas Grekas + * + * @internal + */ +final class Php80 +{ + public static function fdiv(float $dividend, float $divisor): float + { + return @($dividend / $divisor); + } + + public static function get_debug_type($value): string + { + switch (true) { + case null === $value: return 'null'; + case \is_bool($value): return 'bool'; + case \is_string($value): return 'string'; + case \is_array($value): return 'array'; + case \is_int($value): return 'int'; + case \is_float($value): return 'float'; + case \is_object($value): break; + case $value instanceof \__PHP_Incomplete_Class: return '__PHP_Incomplete_Class'; + default: + if (null === $type = @get_resource_type($value)) { + return 'unknown'; + } + + if ('Unknown' === $type) { + $type = 'closed'; + } + + return "resource ($type)"; + } + + $class = \get_class($value); + + if (false === strpos($class, '@')) { + return $class; + } + + return (get_parent_class($class) ?: key(class_implements($class)) ?: 'class').'@anonymous'; + } + + public static function get_resource_id($res): int + { + if (!\is_resource($res) && null === @get_resource_type($res)) { + throw new \TypeError(sprintf('Argument 1 passed to get_resource_id() must be of the type resource, %s given', get_debug_type($res))); + } + + return (int) $res; + } + + public static function preg_last_error_msg(): string + { + switch (preg_last_error()) { + case \PREG_INTERNAL_ERROR: + return 'Internal error'; + case \PREG_BAD_UTF8_ERROR: + return 'Malformed UTF-8 characters, possibly incorrectly encoded'; + case \PREG_BAD_UTF8_OFFSET_ERROR: + return 'The offset did not correspond to the beginning of a valid UTF-8 code point'; + case \PREG_BACKTRACK_LIMIT_ERROR: + return 'Backtrack limit exhausted'; + case \PREG_RECURSION_LIMIT_ERROR: + return 'Recursion limit exhausted'; + case \PREG_JIT_STACKLIMIT_ERROR: + return 'JIT stack limit exhausted'; + case \PREG_NO_ERROR: + return 'No error'; + default: + return 'Unknown error'; + } + } + + public static function str_contains(string $haystack, string $needle): bool + { + return '' === $needle || false !== strpos($haystack, $needle); + } + + public static function str_starts_with(string $haystack, string $needle): bool + { + return 0 === strncmp($haystack, $needle, \strlen($needle)); + } + + public static function str_ends_with(string $haystack, string $needle): bool + { + if ('' === $needle || $needle === $haystack) { + return true; + } + + if ('' === $haystack) { + return false; + } + + $needleLength = \strlen($needle); + + return $needleLength <= \strlen($haystack) && 0 === substr_compare($haystack, $needle, -$needleLength); + } +} diff --git a/advancedcontentfilter/vendor/symfony/polyfill-php80/PhpToken.php b/advancedcontentfilter/vendor/symfony/polyfill-php80/PhpToken.php new file mode 100644 index 00000000..fe6e6910 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/polyfill-php80/PhpToken.php @@ -0,0 +1,103 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Polyfill\Php80; + +/** + * @author Fedonyuk Anton + * + * @internal + */ +class PhpToken implements \Stringable +{ + /** + * @var int + */ + public $id; + + /** + * @var string + */ + public $text; + + /** + * @var int + */ + public $line; + + /** + * @var int + */ + public $pos; + + public function __construct(int $id, string $text, int $line = -1, int $position = -1) + { + $this->id = $id; + $this->text = $text; + $this->line = $line; + $this->pos = $position; + } + + public function getTokenName(): ?string + { + if ('UNKNOWN' === $name = token_name($this->id)) { + $name = \strlen($this->text) > 1 || \ord($this->text) < 32 ? null : $this->text; + } + + return $name; + } + + /** + * @param int|string|array $kind + */ + public function is($kind): bool + { + foreach ((array) $kind as $value) { + if (\in_array($value, [$this->id, $this->text], true)) { + return true; + } + } + + return false; + } + + public function isIgnorable(): bool + { + return \in_array($this->id, [\T_WHITESPACE, \T_COMMENT, \T_DOC_COMMENT, \T_OPEN_TAG], true); + } + + public function __toString(): string + { + return (string) $this->text; + } + + /** + * @return static[] + */ + public static function tokenize(string $code, int $flags = 0): array + { + $line = 1; + $position = 0; + $tokens = token_get_all($code, $flags); + foreach ($tokens as $index => $token) { + if (\is_string($token)) { + $id = \ord($token); + $text = $token; + } else { + [$id, $text, $line] = $token; + } + $tokens[$index] = new static($id, $text, $line, $position); + $position += \strlen($text); + } + + return $tokens; + } +} diff --git a/advancedcontentfilter/vendor/symfony/polyfill-php80/README.md b/advancedcontentfilter/vendor/symfony/polyfill-php80/README.md new file mode 100644 index 00000000..3816c559 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/polyfill-php80/README.md @@ -0,0 +1,25 @@ +Symfony Polyfill / Php80 +======================== + +This component provides features added to PHP 8.0 core: + +- [`Stringable`](https://php.net/stringable) interface +- [`fdiv`](https://php.net/fdiv) +- [`ValueError`](https://php.net/valueerror) class +- [`UnhandledMatchError`](https://php.net/unhandledmatcherror) class +- `FILTER_VALIDATE_BOOL` constant +- [`get_debug_type`](https://php.net/get_debug_type) +- [`PhpToken`](https://php.net/phptoken) class +- [`preg_last_error_msg`](https://php.net/preg_last_error_msg) +- [`str_contains`](https://php.net/str_contains) +- [`str_starts_with`](https://php.net/str_starts_with) +- [`str_ends_with`](https://php.net/str_ends_with) +- [`get_resource_id`](https://php.net/get_resource_id) + +More information can be found in the +[main Polyfill README](https://github.com/symfony/polyfill/blob/main/README.md). + +License +======= + +This library is released under the [MIT license](LICENSE). diff --git a/advancedcontentfilter/vendor/symfony/polyfill-php80/Resources/stubs/Attribute.php b/advancedcontentfilter/vendor/symfony/polyfill-php80/Resources/stubs/Attribute.php new file mode 100644 index 00000000..2b955423 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/polyfill-php80/Resources/stubs/Attribute.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +#[Attribute(Attribute::TARGET_CLASS)] +final class Attribute +{ + public const TARGET_CLASS = 1; + public const TARGET_FUNCTION = 2; + public const TARGET_METHOD = 4; + public const TARGET_PROPERTY = 8; + public const TARGET_CLASS_CONSTANT = 16; + public const TARGET_PARAMETER = 32; + public const TARGET_ALL = 63; + public const IS_REPEATABLE = 64; + + /** @var int */ + public $flags; + + public function __construct(int $flags = self::TARGET_ALL) + { + $this->flags = $flags; + } +} diff --git a/advancedcontentfilter/vendor/symfony/polyfill-php80/Resources/stubs/PhpToken.php b/advancedcontentfilter/vendor/symfony/polyfill-php80/Resources/stubs/PhpToken.php new file mode 100644 index 00000000..bd1212f6 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/polyfill-php80/Resources/stubs/PhpToken.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +if (\PHP_VERSION_ID < 80000 && extension_loaded('tokenizer')) { + class PhpToken extends Symfony\Polyfill\Php80\PhpToken + { + } +} diff --git a/advancedcontentfilter/vendor/symfony/polyfill-php80/Resources/stubs/Stringable.php b/advancedcontentfilter/vendor/symfony/polyfill-php80/Resources/stubs/Stringable.php new file mode 100644 index 00000000..7c62d750 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/polyfill-php80/Resources/stubs/Stringable.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +if (\PHP_VERSION_ID < 80000) { + interface Stringable + { + /** + * @return string + */ + public function __toString(); + } +} diff --git a/advancedcontentfilter/vendor/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php b/advancedcontentfilter/vendor/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php new file mode 100644 index 00000000..01c6c6c8 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +if (\PHP_VERSION_ID < 80000) { + class UnhandledMatchError extends Error + { + } +} diff --git a/advancedcontentfilter/vendor/symfony/polyfill-php80/Resources/stubs/ValueError.php b/advancedcontentfilter/vendor/symfony/polyfill-php80/Resources/stubs/ValueError.php new file mode 100644 index 00000000..783dbc28 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/polyfill-php80/Resources/stubs/ValueError.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +if (\PHP_VERSION_ID < 80000) { + class ValueError extends Error + { + } +} diff --git a/advancedcontentfilter/vendor/symfony/polyfill-php80/bootstrap.php b/advancedcontentfilter/vendor/symfony/polyfill-php80/bootstrap.php new file mode 100644 index 00000000..e5f7dbc1 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/polyfill-php80/bootstrap.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Polyfill\Php80 as p; + +if (\PHP_VERSION_ID >= 80000) { + return; +} + +if (!defined('FILTER_VALIDATE_BOOL') && defined('FILTER_VALIDATE_BOOLEAN')) { + define('FILTER_VALIDATE_BOOL', \FILTER_VALIDATE_BOOLEAN); +} + +if (!function_exists('fdiv')) { + function fdiv(float $num1, float $num2): float { return p\Php80::fdiv($num1, $num2); } +} +if (!function_exists('preg_last_error_msg')) { + function preg_last_error_msg(): string { return p\Php80::preg_last_error_msg(); } +} +if (!function_exists('str_contains')) { + function str_contains(?string $haystack, ?string $needle): bool { return p\Php80::str_contains($haystack ?? '', $needle ?? ''); } +} +if (!function_exists('str_starts_with')) { + function str_starts_with(?string $haystack, ?string $needle): bool { return p\Php80::str_starts_with($haystack ?? '', $needle ?? ''); } +} +if (!function_exists('str_ends_with')) { + function str_ends_with(?string $haystack, ?string $needle): bool { return p\Php80::str_ends_with($haystack ?? '', $needle ?? ''); } +} +if (!function_exists('get_debug_type')) { + function get_debug_type($value): string { return p\Php80::get_debug_type($value); } +} +if (!function_exists('get_resource_id')) { + function get_resource_id($resource): int { return p\Php80::get_resource_id($resource); } +} diff --git a/advancedcontentfilter/vendor/symfony/polyfill-php80/composer.json b/advancedcontentfilter/vendor/symfony/polyfill-php80/composer.json new file mode 100644 index 00000000..46ccde20 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/polyfill-php80/composer.json @@ -0,0 +1,37 @@ +{ + "name": "symfony/polyfill-php80", + "type": "library", + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "keywords": ["polyfill", "shim", "compatibility", "portable"], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": ">=7.1" + }, + "autoload": { + "psr-4": { "Symfony\\Polyfill\\Php80\\": "" }, + "files": [ "bootstrap.php" ], + "classmap": [ "Resources/stubs" ] + }, + "minimum-stability": "dev", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + } +} diff --git a/advancedcontentfilter/vendor/symfony/service-contracts/.gitignore b/advancedcontentfilter/vendor/symfony/service-contracts/.gitignore new file mode 100644 index 00000000..c49a5d8d --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/service-contracts/.gitignore @@ -0,0 +1,3 @@ +vendor/ +composer.lock +phpunit.xml diff --git a/advancedcontentfilter/vendor/symfony/service-contracts/Attribute/Required.php b/advancedcontentfilter/vendor/symfony/service-contracts/Attribute/Required.php new file mode 100644 index 00000000..9df85118 --- /dev/null +++ b/advancedcontentfilter/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/advancedcontentfilter/vendor/symfony/service-contracts/Attribute/SubscribedService.php b/advancedcontentfilter/vendor/symfony/service-contracts/Attribute/SubscribedService.php new file mode 100644 index 00000000..10d1bc38 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/service-contracts/Attribute/SubscribedService.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\Attribute; + +use Symfony\Contracts\Service\ServiceSubscriberTrait; + +/** + * Use with {@see ServiceSubscriberTrait} to mark a method's return type + * as a subscribed service. + * + * @author Kevin Bond + */ +#[\Attribute(\Attribute::TARGET_METHOD)] +final class SubscribedService +{ + /** + * @param string|null $key The key to use for the service + * If null, use "ClassName::methodName" + */ + public function __construct( + public ?string $key = null + ) { + } +} diff --git a/advancedcontentfilter/vendor/symfony/service-contracts/CHANGELOG.md b/advancedcontentfilter/vendor/symfony/service-contracts/CHANGELOG.md new file mode 100644 index 00000000..7932e261 --- /dev/null +++ b/advancedcontentfilter/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/advancedcontentfilter/vendor/symfony/service-contracts/LICENSE b/advancedcontentfilter/vendor/symfony/service-contracts/LICENSE new file mode 100644 index 00000000..74cdc2db --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/service-contracts/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2018-2022 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/advancedcontentfilter/vendor/symfony/service-contracts/README.md b/advancedcontentfilter/vendor/symfony/service-contracts/README.md new file mode 100644 index 00000000..41e054a1 --- /dev/null +++ b/advancedcontentfilter/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/advancedcontentfilter/vendor/symfony/service-contracts/ResetInterface.php b/advancedcontentfilter/vendor/symfony/service-contracts/ResetInterface.php new file mode 100644 index 00000000..1af1075e --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/service-contracts/ResetInterface.php @@ -0,0 +1,30 @@ + + * + * 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 +{ + public function reset(); +} diff --git a/advancedcontentfilter/vendor/symfony/service-contracts/ServiceLocatorTrait.php b/advancedcontentfilter/vendor/symfony/service-contracts/ServiceLocatorTrait.php new file mode 100644 index 00000000..74dfa436 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/service-contracts/ServiceLocatorTrait.php @@ -0,0 +1,128 @@ + + * + * 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 $factories; + private $loading = []; + private $providedTypes; + + /** + * @param callable[] $factories + */ + public function __construct(array $factories) + { + $this->factories = $factories; + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function has(string $id) + { + return isset($this->factories[$id]); + } + + /** + * {@inheritdoc} + * + * @return mixed + */ + public function get(string $id) + { + 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]); + } + } + + /** + * {@inheritdoc} + */ + public function getProvidedServices(): array + { + if (null === $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/advancedcontentfilter/vendor/symfony/service-contracts/ServiceProviderInterface.php b/advancedcontentfilter/vendor/symfony/service-contracts/ServiceProviderInterface.php new file mode 100644 index 00000000..c60ad0bd --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/service-contracts/ServiceProviderInterface.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\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 + */ +interface ServiceProviderInterface extends ContainerInterface +{ + /** + * 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 string[] The provided service types, keyed by service names + */ + public function getProvidedServices(): array; +} diff --git a/advancedcontentfilter/vendor/symfony/service-contracts/ServiceSubscriberInterface.php b/advancedcontentfilter/vendor/symfony/service-contracts/ServiceSubscriberInterface.php new file mode 100644 index 00000000..098ab908 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/service-contracts/ServiceSubscriberInterface.php @@ -0,0 +1,53 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Contracts\Service; + +/** + * 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 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'] + * + * @return string[] The required service types, optionally keyed by service names + */ + public static function getSubscribedServices(); +} diff --git a/advancedcontentfilter/vendor/symfony/service-contracts/ServiceSubscriberTrait.php b/advancedcontentfilter/vendor/symfony/service-contracts/ServiceSubscriberTrait.php new file mode 100644 index 00000000..16e3eb2c --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/service-contracts/ServiceSubscriberTrait.php @@ -0,0 +1,109 @@ + + * + * 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\SubscribedService; + +/** + * Implementation of ServiceSubscriberInterface that determines subscribed services from + * method return types. Service ids are available as "ClassName::methodName". + * + * @author Kevin Bond + */ +trait ServiceSubscriberTrait +{ + /** @var ContainerInterface */ + protected $container; + + /** + * {@inheritdoc} + */ + public static function getSubscribedServices(): array + { + $services = method_exists(get_parent_class(self::class) ?: '', __FUNCTION__) ? parent::getSubscribedServices() : []; + $attributeOptIn = false; + + if (\PHP_VERSION_ID >= 80000) { + 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)); + } + + $serviceId = $returnType instanceof \ReflectionNamedType ? $returnType->getName() : (string) $returnType; + + if ($returnType->allowsNull()) { + $serviceId = '?'.$serviceId; + } + + $services[$attribute->newInstance()->key ?? self::class.'::'.$method->name] = $serviceId; + $attributeOptIn = true; + } + } + + if (!$attributeOptIn) { + foreach ((new \ReflectionClass(self::class))->getMethods() as $method) { + if ($method->isStatic() || $method->isAbstract() || $method->isGenerator() || $method->isInternal() || $method->getNumberOfRequiredParameters()) { + continue; + } + + if (self::class !== $method->getDeclaringClass()->name) { + continue; + } + + if (!($returnType = $method->getReturnType()) instanceof \ReflectionNamedType) { + continue; + } + + if ($returnType->isBuiltin()) { + continue; + } + + if (\PHP_VERSION_ID >= 80000) { + trigger_deprecation('symfony/service-contracts', '2.5', 'Using "%s" in "%s" without using the "%s" attribute on any method is deprecated.', ServiceSubscriberTrait::class, self::class, SubscribedService::class); + } + + $services[self::class.'::'.$method->name] = '?'.($returnType instanceof \ReflectionNamedType ? $returnType->getName() : $returnType); + } + } + + return $services; + } + + /** + * @required + * + * @return ContainerInterface|null + */ + public function setContainer(ContainerInterface $container) + { + $this->container = $container; + + if (method_exists(get_parent_class(self::class) ?: '', __FUNCTION__)) { + return parent::setContainer($container); + } + + return null; + } +} diff --git a/advancedcontentfilter/vendor/symfony/service-contracts/Test/ServiceLocatorTest.php b/advancedcontentfilter/vendor/symfony/service-contracts/Test/ServiceLocatorTest.php new file mode 100644 index 00000000..2a1b565f --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/service-contracts/Test/ServiceLocatorTest.php @@ -0,0 +1,95 @@ + + * + * 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\ContainerInterface; +use Symfony\Contracts\Service\ServiceLocatorTrait; + +abstract class ServiceLocatorTest extends TestCase +{ + /** + * @return ContainerInterface + */ + protected function getServiceLocator(array $factories) + { + return new class($factories) implements ContainerInterface { + use ServiceLocatorTrait; + }; + } + + public function testHas() + { + $locator = $this->getServiceLocator([ + 'foo' => function () { return 'bar'; }, + 'bar' => function () { return 'baz'; }, + function () { return 'dummy'; }, + ]); + + $this->assertTrue($locator->has('foo')); + $this->assertTrue($locator->has('bar')); + $this->assertFalse($locator->has('dummy')); + } + + public function testGet() + { + $locator = $this->getServiceLocator([ + 'foo' => function () { return 'bar'; }, + 'bar' => function () { return '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() + { + if (!$this->getExpectedException()) { + $this->expectException(\Psr\Container\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 = $this->getServiceLocator([ + 'foo' => function () use (&$locator) { return $locator->get('bar'); }, + ]); + + $locator->get('foo'); + } + + public function testThrowsOnCircularReference() + { + $this->expectException(\Psr\Container\ContainerExceptionInterface::class); + $this->expectExceptionMessage('Circular reference detected for service "bar", path: "bar -> baz -> bar".'); + $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'); }, + ]); + + $locator->get('foo'); + } +} diff --git a/advancedcontentfilter/vendor/symfony/service-contracts/composer.json b/advancedcontentfilter/vendor/symfony/service-contracts/composer.json new file mode 100644 index 00000000..f0586370 --- /dev/null +++ b/advancedcontentfilter/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": ">=7.2.5", + "psr/container": "^1.1", + "symfony/deprecation-contracts": "^2.1|^3" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "suggest": { + "symfony/service-implementation": "" + }, + "autoload": { + "psr-4": { "Symfony\\Contracts\\Service\\": "" } + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-main": "2.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + } +} diff --git a/advancedcontentfilter/vendor/symfony/var-exporter/CHANGELOG.md b/advancedcontentfilter/vendor/symfony/var-exporter/CHANGELOG.md new file mode 100644 index 00000000..3406c30e --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/var-exporter/CHANGELOG.md @@ -0,0 +1,12 @@ +CHANGELOG +========= + +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/advancedcontentfilter/vendor/symfony/var-exporter/Exception/ClassNotFoundException.php b/advancedcontentfilter/vendor/symfony/var-exporter/Exception/ClassNotFoundException.php new file mode 100644 index 00000000..379a7651 --- /dev/null +++ b/advancedcontentfilter/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/advancedcontentfilter/vendor/symfony/var-exporter/Exception/ExceptionInterface.php b/advancedcontentfilter/vendor/symfony/var-exporter/Exception/ExceptionInterface.php new file mode 100644 index 00000000..adfaed47 --- /dev/null +++ b/advancedcontentfilter/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/advancedcontentfilter/vendor/symfony/var-exporter/Exception/NotInstantiableTypeException.php b/advancedcontentfilter/vendor/symfony/var-exporter/Exception/NotInstantiableTypeException.php new file mode 100644 index 00000000..b9ba225d --- /dev/null +++ b/advancedcontentfilter/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/advancedcontentfilter/vendor/symfony/var-exporter/Instantiator.php b/advancedcontentfilter/vendor/symfony/var-exporter/Instantiator.php new file mode 100644 index 00000000..368c769a --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/var-exporter/Instantiator.php @@ -0,0 +1,92 @@ + + * + * 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\Hydrator; +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. + * + * For example: + * + * // creates an empty instance of Foo + * Instantiator::instantiate(Foo::class); + * + * // creates a Foo instance and sets one of its properties + * Instantiator::instantiate(Foo::class, ['propertyName' => $propertyValue]); + * + * // creates a Foo instance and sets a private property defined on its parent Bar class + * Instantiator::instantiate(Foo::class, [], [ + * Bar::class => ['privateBarProperty' => $propertyValue], + * ]); + * + * Instances of ArrayObject, ArrayIterator and SplObjectStorage can be created + * by using the special "\0" property name to define their internal value: + * + * // creates an SplObjectStorage where $info1 is attached to $obj1, etc. + * Instantiator::instantiate(SplObjectStorage::class, ["\0" => [$obj1, $info1, $obj2, $info2...]]); + * + * // creates an ArrayObject populated with $inputArray + * Instantiator::instantiate(ArrayObject::class, ["\0" => [$inputArray]]); + * + * @param string $class The class of the instance to create + * @param array $properties The properties to set on the instance + * @param array $privateProperties The private properties to set on the instance, + * keyed by their declaring class + * + * @throws ExceptionInterface When the instance cannot be created + */ + public static function instantiate(string $class, array $properties = [], array $privateProperties = []): object + { + $reflector = Registry::$reflectors[$class] ?? Registry::getClassReflector($class); + + if (Registry::$cloneable[$class]) { + $wrappedInstance = [clone Registry::$prototypes[$class]]; + } elseif (Registry::$instantiableWithoutConstructor[$class]) { + $wrappedInstance = [$reflector->newInstanceWithoutConstructor()]; + } elseif (null === Registry::$prototypes[$class]) { + throw new NotInstantiableTypeException($class); + } elseif ($reflector->implementsInterface('Serializable') && (\PHP_VERSION_ID < 70400 || !method_exists($class, '__unserialize'))) { + $wrappedInstance = [unserialize('C:'.\strlen($class).':"'.$class.'":0:{}')]; + } else { + $wrappedInstance = [unserialize('O:'.\strlen($class).':"'.$class.'":0:{}')]; + } + + if ($properties) { + $privateProperties[$class] = isset($privateProperties[$class]) ? $properties + $privateProperties[$class] : $properties; + } + + foreach ($privateProperties as $class => $properties) { + if (!$properties) { + continue; + } + foreach ($properties as $name => $value) { + // because they're also used for "unserialization", hydrators + // deal with array of instances, so we need to wrap values + $properties[$name] = [$value]; + } + (Hydrator::$hydrators[$class] ?? Hydrator::getHydrator($class))($properties, $wrappedInstance); + } + + return $wrappedInstance[0]; + } +} diff --git a/advancedcontentfilter/vendor/symfony/var-exporter/Internal/Exporter.php b/advancedcontentfilter/vendor/symfony/var-exporter/Internal/Exporter.php new file mode 100644 index 00000000..51c29e45 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/var-exporter/Internal/Exporter.php @@ -0,0 +1,417 @@ + + * + * 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 + * + * @throws NotInstantiableTypeException When a value cannot be serialized + */ + public static function prepare($values, $objectsPool, &$refsPool, &$objectsCount, &$valuesAreStatic): array + { + $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 = \get_class($value); + $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 = \PHP_VERSION_ID >= 80100 && $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 + || \PHP_VERSION_ID < 80200 && $value instanceof \DatePeriod + ) { + ++$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 = \PHP_VERSION_ID >= 80100 && $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, string $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 ('n".\'' === substr($m[1], -4)) { + 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 '\\'.\get_class($value)."::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/advancedcontentfilter/vendor/symfony/var-exporter/Internal/Hydrator.php b/advancedcontentfilter/vendor/symfony/var-exporter/Internal/Hydrator.php new file mode 100644 index 00000000..5ed6bdc9 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/var-exporter/Internal/Hydrator.php @@ -0,0 +1,152 @@ + + * + * 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 $hydrators = []; + + public $registry; + public $values; + public $properties; + public $value; + public $wakeups; + + public function __construct(?Registry $registry, ?Values $values, array $properties, $value, array $wakeups) + { + $this->registry = $registry; + $this->values = $values; + $this->properties = $properties; + $this->value = $value; + $this->wakeups = $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) + { + switch ($class) { + case 'stdClass': + return self::$hydrators[$class] = static function ($properties, $objects) { + foreach ($properties as $name => $values) { + foreach ($values as $i => $v) { + $objects[$i]->$name = $v; + } + } + }; + + case 'ErrorException': + return self::$hydrators[$class] = (self::$hydrators['stdClass'] ?? self::getHydrator('stdClass'))->bindTo(null, new class() extends \ErrorException { + }); + + case 'TypeError': + return self::$hydrators[$class] = (self::$hydrators['stdClass'] ?? self::getHydrator('stdClass'))->bindTo(null, new class() extends \Error { + }); + + case 'SplObjectStorage': + return self::$hydrators[$class] = 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 = \Closure::fromCallable([$classReflector->getConstructor(), 'invokeArgs']); + + return self::$hydrators[$class] = 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 self::$hydrators[$class] = (self::$hydrators['stdClass'] ?? self::getHydrator('stdClass'))->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()) { + $propertyReflector->setAccessible(true); + $propertySetters[$propertyReflector->name] = \Closure::fromCallable([$propertyReflector, 'setValue']); + } + } + + if (!$propertySetters) { + return self::$hydrators[$class] = self::$hydrators['stdClass'] ?? self::getHydrator('stdClass'); + } + + return self::$hydrators[$class] = 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; + } + } + }; + } +} diff --git a/advancedcontentfilter/vendor/symfony/var-exporter/Internal/Reference.php b/advancedcontentfilter/vendor/symfony/var-exporter/Internal/Reference.php new file mode 100644 index 00000000..e371c07b --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/var-exporter/Internal/Reference.php @@ -0,0 +1,30 @@ + + * + * 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 $id; + public $value; + public $count = 0; + + public function __construct(int $id, $value = null) + { + $this->id = $id; + $this->value = $value; + } +} diff --git a/advancedcontentfilter/vendor/symfony/var-exporter/Internal/Registry.php b/advancedcontentfilter/vendor/symfony/var-exporter/Internal/Registry.php new file mode 100644 index 00000000..24b77b9e --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/var-exporter/Internal/Registry.php @@ -0,0 +1,146 @@ + + * + * 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 $reflectors = []; + public static $prototypes = []; + public static $factories = []; + public static $cloneable = []; + public static $instantiableWithoutConstructor = []; + + public $classes = []; + + public function __construct(array $classes) + { + $this->classes = $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] = \Closure::fromCallable([$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 self::$reflectors[$class] = $reflector; + } else { + try { + $proto = $reflector->newInstanceWithoutConstructor(); + $instantiableWithoutConstructor = true; + } catch (\ReflectionException $e) { + $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') && (\PHP_VERSION_ID < 70400 || !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') && (\PHP_VERSION_ID < 70400 || !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]->setAccessible(true); + $setTrace[1]->setAccessible(true); + $setTrace[0] = \Closure::fromCallable([$setTrace[0], 'setValue']); + $setTrace[1] = \Closure::fromCallable([$setTrace[1], 'setValue']); + } + + $setTrace[$proto instanceof \Exception]($proto, []); + } + + return self::$reflectors[$class] = $reflector; + } +} diff --git a/advancedcontentfilter/vendor/symfony/var-exporter/Internal/Values.php b/advancedcontentfilter/vendor/symfony/var-exporter/Internal/Values.php new file mode 100644 index 00000000..21ae04e6 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/var-exporter/Internal/Values.php @@ -0,0 +1,27 @@ + + * + * 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 $values; + + public function __construct(array $values) + { + $this->values = $values; + } +} diff --git a/advancedcontentfilter/vendor/symfony/var-exporter/LICENSE b/advancedcontentfilter/vendor/symfony/var-exporter/LICENSE new file mode 100644 index 00000000..7536caea --- /dev/null +++ b/advancedcontentfilter/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/advancedcontentfilter/vendor/symfony/var-exporter/README.md b/advancedcontentfilter/vendor/symfony/var-exporter/README.md new file mode 100644 index 00000000..a34e4c23 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/var-exporter/README.md @@ -0,0 +1,38 @@ +VarExporter Component +===================== + +The VarExporter component 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`). + +It also provides an instantiator that allows creating and populating objects +without calling their constructor nor any other methods. + +The reason to use this component *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). + +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/advancedcontentfilter/vendor/symfony/var-exporter/VarExporter.php b/advancedcontentfilter/vendor/symfony/var-exporter/VarExporter.php new file mode 100644 index 00000000..d4c08091 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/var-exporter/VarExporter.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\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 mixed $value The value to export + * @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($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/advancedcontentfilter/vendor/symfony/var-exporter/composer.json b/advancedcontentfilter/vendor/symfony/var-exporter/composer.json new file mode 100644 index 00000000..29d4901d --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/var-exporter/composer.json @@ -0,0 +1,32 @@ +{ + "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"], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": ">=7.2.5", + "symfony/polyfill-php80": "^1.16" + }, + "require-dev": { + "symfony/var-dumper": "^4.4.9|^5.0.9|^6.0" + }, + "autoload": { + "psr-4": { "Symfony\\Component\\VarExporter\\": "" }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "minimum-stability": "dev" +}