diff --git a/.editorconfig b/.editorconfig index 8565b274..ef6e90b2 100644 --- a/.editorconfig +++ b/.editorconfig @@ -27,3 +27,6 @@ indent_size = 2 [*.json] indent_style = space indent_size = 2 + +[composer.json] +indent_size = 4 diff --git a/.woodpecker/.code_standards_check.yml b/.woodpecker/.code_standards_check.yml index 9d59dc08..60a1bd2a 100644 --- a/.woodpecker/.code_standards_check.yml +++ b/.woodpecker/.code_standards_check.yml @@ -1,9 +1,12 @@ skip_clone: true -pipeline: +steps: clone_friendica_base: image: alpine/git commands: + - git config --global user.email "no-reply@friendi.ca" + - git config --global user.name "Friendica" + - git config --global --add safe.directory $CI_WORKSPACE - git clone https://github.com/friendica/friendica.git . - git checkout $CI_COMMIT_BRANCH when: @@ -13,7 +16,7 @@ pipeline: commands: - git config --global user.email "no-reply@friendi.ca" - git config --global user.name "Friendica" - - git clone $CI_REPO_LINK addon + - git clone $CI_REPO_CLONE_URL addon - cd addon/ - git checkout $CI_COMMIT_BRANCH - git fetch origin $CI_COMMIT_REF @@ -53,6 +56,10 @@ pipeline: - /tmp/drone-cache:/tmp/cache when: event: pull_request + phpstan: + image: friendicaci/php8.3:php8.3.3 + commands: + - ./bin/composer.phar run phpstan; check: image: friendicaci/php-cs commands: diff --git a/.woodpecker/.continuous-deployment.yml b/.woodpecker/.continuous-deployment.yml index 3756a8bf..d6d8a22a 100644 --- a/.woodpecker/.continuous-deployment.yml +++ b/.woodpecker/.continuous-deployment.yml @@ -5,10 +5,13 @@ labels: skip_clone: true -pipeline: +steps: clone_friendica_base: image: alpine/git commands: + - git config --global user.email "no-reply@friendi.ca" + - git config --global user.name "Friendica" + - git config --global --add safe.directory $CI_WORKSPACE - git clone https://github.com/friendica/friendica.git . - git checkout $CI_COMMIT_BRANCH when: @@ -20,7 +23,7 @@ pipeline: commands: - git config --global user.email "no-reply@friendi.ca" - git config --global user.name "Friendica" - - git clone $CI_REPO_LINK addon + - git clone $CI_REPO_CLONE_URL addon - cd addon/ - git checkout $CI_COMMIT_BRANCH - git fetch origin $CI_COMMIT_REF @@ -45,7 +48,7 @@ pipeline: branch: [ develop, '*-rc' ] event: push composer_install: - image: friendicaci/php8.2:php8.2.16 + image: friendicaci/php8.2:php8.2.28 commands: - export COMPOSER_HOME=.composer - composer validate diff --git a/.woodpecker/.messages.po_check.yml b/.woodpecker/.messages.po_check.yml index f5691e00..e0239dcd 100644 --- a/.woodpecker/.messages.po_check.yml +++ b/.woodpecker/.messages.po_check.yml @@ -1,9 +1,12 @@ skip_clone: true -pipeline: +steps: clone_friendica_base: image: alpine/git commands: + - git config --global user.email "no-reply@friendi.ca" + - git config --global user.name "Friendica" + - git config --global --add safe.directory $CI_WORKSPACE - git clone https://github.com/friendica/friendica.git . - git checkout $CI_COMMIT_BRANCH when: @@ -13,7 +16,7 @@ pipeline: commands: - git config --global user.email "no-reply@friendi.ca" - git config --global user.name "Friendica" - - git clone $CI_REPO_LINK addon + - git clone $CI_REPO_CLONE_URL addon - cd addon/ - git checkout $CI_COMMIT_BRANCH - git fetch origin $CI_COMMIT_REF diff --git a/.woodpecker/.phpunit.yml b/.woodpecker/.phpunit.yml index 1e6189d3..b0745ad0 100644 --- a/.woodpecker/.phpunit.yml +++ b/.woodpecker/.phpunit.yml @@ -5,11 +5,13 @@ matrix: - PHP_MAJOR_VERSION: 8.0 PHP_VERSION: 8.0.30 - PHP_MAJOR_VERSION: 8.1 - PHP_VERSION: 8.1.27 + PHP_VERSION: 8.1.31 - PHP_MAJOR_VERSION: 8.2 - PHP_VERSION: 8.2.16 + PHP_VERSION: 8.2.28 - PHP_MAJOR_VERSION: 8.3 - PHP_VERSION: 8.3.3 + PHP_VERSION: 8.3.17 + - PHP_MAJOR_VERSION: 8.4 + PHP_VERSION: 8.4.5 # This forces PHP Unit executions at the "opensocial" labeled location (because of much more power...) labels: @@ -17,10 +19,13 @@ labels: skip_clone: true -pipeline: +steps: clone_friendica_base: image: alpine/git commands: + - git config --global user.email "no-reply@friendi.ca" + - git config --global user.name "Friendica" + - git config --global --add safe.directory $CI_WORKSPACE - git clone https://github.com/friendica/friendica.git . - git checkout $CI_COMMIT_BRANCH clone_friendica_addon: @@ -28,7 +33,7 @@ pipeline: commands: - git config --global user.email "no-reply@friendi.ca" - git config --global user.name "Friendica" - - git clone $CI_REPO_LINK addon + - git clone $CI_REPO_CLONE_URL addon - cd addon/ - git checkout $CI_COMMIT_BRANCH - git fetch origin $CI_COMMIT_REF @@ -95,9 +100,9 @@ pipeline: - friendica/friendica-addons commands: - codecov -R '.' -Z -f 'clover.xml' - secrets: - - source: codecov-token - target: codecov_token + environment: + CODECOV_TOKEN: + from_secret: codecov-token services: mariadb: diff --git a/.woodpecker/.releaser.yml b/.woodpecker/.releaser.yml index 5751f07f..7407f2bc 100644 --- a/.woodpecker/.releaser.yml +++ b/.woodpecker/.releaser.yml @@ -5,10 +5,13 @@ labels: skip_clone: true -pipeline: +steps: clone_friendica_base: image: alpine/git commands: + - git config --global user.email "no-reply@friendi.ca" + - git config --global user.name "Friendica" + - git config --global --add safe.directory $CI_WORKSPACE - git clone https://github.com/friendica/friendica.git . - git checkout $CI_COMMIT_BRANCH when: @@ -19,7 +22,7 @@ pipeline: commands: - git config --global user.email "no-reply@friendi.ca" - git config --global user.name "Friendica" - - git clone $CI_REPO_LINK addon + - git clone $CI_REPO_CLONE_URL addon - cd addon/ - git checkout $CI_COMMIT_BRANCH - git fetch origin $CI_COMMIT_REF @@ -42,7 +45,7 @@ pipeline: repo: friendica/friendica-addons event: tag composer_install: - image: friendicaci/php8.2:php8.2.16 + image: friendicaci/php8.2:php8.2.28 commands: - export COMPOSER_HOME=.composer - composer validate diff --git a/advancedcontentfilter/advancedcontentfilter.js b/advancedcontentfilter/advancedcontentfilter.js index fcf7b096..a8fc1c65 100644 --- a/advancedcontentfilter/advancedcontentfilter.js +++ b/advancedcontentfilter/advancedcontentfilter.js @@ -54,7 +54,7 @@ new Vue({ self.rules.push(responseJSON.rule); self.resetForm(); }, function (response) { - self.errorMessage = response.responseJSON.message; + self.errorMessage = response.responseJSON.exception[0].message; }); } }, @@ -74,7 +74,7 @@ new Vue({ self.rules[self.editedIndex] = rule; self.resetForm(); }, function (response) { - self.errorMessage = response.responseJSON.message; + self.errorMessage = response.responseJSON.exception[0].message; }); }, diff --git a/advancedcontentfilter/advancedcontentfilter.php b/advancedcontentfilter/advancedcontentfilter.php index 418b253e..53cb9ebe 100644 --- a/advancedcontentfilter/advancedcontentfilter.php +++ b/advancedcontentfilter/advancedcontentfilter.php @@ -33,16 +33,13 @@ * */ -use Friendica\App; use Friendica\BaseModule; use Friendica\Content\Text\Markdown; use Friendica\Core\Hook; -use Friendica\Core\Logger; use Friendica\Core\Renderer; use Friendica\Database\DBA; use Friendica\Database\DBStructure; use Friendica\DI; -use Friendica\Model\Item; use Friendica\Model\Post; use Friendica\Model\Tag; use Friendica\Model\User; @@ -64,7 +61,7 @@ function advancedcontentfilter_install() Hook::add('dbstructure_definition' , __FILE__, 'advancedcontentfilter_dbstructure_definition'); DBStructure::performUpdate(); - Logger::notice('installed advancedcontentfilter'); + DI::logger()->notice('installed advancedcontentfilter'); } /* @@ -123,21 +120,22 @@ function advancedcontentfilter_prepare_body_content_filter(&$hook_data) $expressionLanguage = new ExpressionLanguage\ExpressionLanguage(); } - if (!DI::userSession()->getLocalUserId()) { + $uid = $hook_data['uid'] ?? DI::userSession()->getLocalUserId(); + if (!$uid) { return; } $vars = advancedcontentfilter_get_filter_fields($hook_data['item']); - $rules = DI::cache()->get('rules_' . DI::userSession()->getLocalUserId()); + $rules = DI::cache()->get('rules_' . $uid); if (!isset($rules)) { $rules = DBA::toArray(DBA::select( 'advancedcontentfilter_rules', ['name', 'expression', 'serialized'], - ['uid' => DI::userSession()->getLocalUserId(), 'active' => true] + ['uid' => $uid, 'active' => true] )); - DI::cache()->set('rules_' . DI::userSession()->getLocalUserId(), $rules); + DI::cache()->set('rules_' . $uid, $rules); } if ($rules) { @@ -192,9 +190,30 @@ function advancedcontentfilter_init() if (DI::args()->getArgc() > 1 && DI::args()->getArgv()[1] == 'api') { $slim = \Slim\Factory\AppFactory::create(); - require __DIR__ . '/src/middlewares.php'; + /** + * The routing middleware should be added before the ErrorMiddleware + * Otherwise exceptions thrown from it will not be handled + */ + $slim->addRoutingMiddleware(); + + $slim->addErrorMiddleware(true, true, true, DI::logger()); + + // register routes + $slim->group('/advancedcontentfilter/api', function (\Slim\Routing\RouteCollectorProxy $app) { + $app->group('/rules', function (\Slim\Routing\RouteCollectorProxy $app) { + $app->get('', 'advancedcontentfilter_get_rules'); + $app->post('', 'advancedcontentfilter_post_rules'); + + $app->get('/{id}', 'advancedcontentfilter_get_rules_id'); + $app->put('/{id}', 'advancedcontentfilter_put_rules_id'); + $app->delete('/{id}', 'advancedcontentfilter_delete_rules_id'); + }); + + $app->group('/variables', function (\Slim\Routing\RouteCollectorProxy $app) { + $app->get('/{guid}', 'advancedcontentfilter_get_variables_guid'); + }); + }); - require __DIR__ . '/src/routes.php'; $slim->run(); exit; @@ -252,7 +271,7 @@ function advancedcontentfilter_content() 'rule_expression' => DI::l10n()->t('Rule Expression'), 'cancel' => DI::l10n()->t('Cancel'), ], - '$current_theme' => DI::app()->getCurrentTheme(), + '$current_theme' => DI::appHelper()->getCurrentTheme(), '$rules' => DBA::toArray(DBA::select('advancedcontentfilter_rules', [], ['uid' => DI::userSession()->getLocalUserId()])), '$form_security_token' => BaseModule::getFormSecurityToken() ]); diff --git a/advancedcontentfilter/composer.json b/advancedcontentfilter/composer.json index ceb152e7..b9ab1900 100644 --- a/advancedcontentfilter/composer.json +++ b/advancedcontentfilter/composer.json @@ -1,24 +1,27 @@ { - "name": "friendica-addons/advancedcontentfilter", - "description": "Advanced Content Filter addon for Friendica", - "type": "friendica-addon", - "authors": [ - { - "name": "Hypolite Petovan", - "email": "hypolite@mrpetovan.com", - "homepage": "https://friendica.mrpetovan.com/profile/hypolite", - "role": "Developer" - } - ], - "require": { - "slim/slim": "^4", - "symfony/expression-language": "^3.4" - }, - "license": "3-clause BSD license", - "minimum-stability": "stable", - "config": { - "optimize-autoloader": true, - "autoloader-suffix": "AdvancedContentFilterAddon", - "preferred-install": "dist" - } + "name": "friendica-addons/advancedcontentfilter", + "description": "Advanced Content Filter addon for Friendica", + "type": "friendica-addon", + "authors": [ + { + "name": "Hypolite Petovan", + "email": "hypolite@mrpetovan.com", + "homepage": "https://friendica.mrpetovan.com/profile/hypolite", + "role": "Developer" + } + ], + "require": { + "slim/slim": "^4", + "symfony/expression-language": "^3.4" + }, + "license": "3-clause BSD license", + "minimum-stability": "stable", + "config": { + "platform": { + "php": "7.4" + }, + "optimize-autoloader": true, + "autoloader-suffix": "AdvancedContentFilterAddon", + "preferred-install": "dist" + } } 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/lang/it/messages.po b/advancedcontentfilter/lang/it/messages.po index f32c5b94..325be52c 100644 --- a/advancedcontentfilter/lang/it/messages.po +++ b/advancedcontentfilter/lang/it/messages.po @@ -5,7 +5,7 @@ # # Translators: # fabrixxm , 2018 -# Sylke Vicious , 2021 +# Sylke Vicious , 2023 # #, fuzzy msgid "" @@ -14,7 +14,7 @@ msgstr "" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2022-05-11 08:54-0400\n" "PO-Revision-Date: 2018-05-24 06:41+0000\n" -"Last-Translator: Sylke Vicious , 2021\n" +"Last-Translator: Sylke Vicious , 2023\n" "Language-Team: Italian (https://app.transifex.com/Friendica/teams/12172/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -125,7 +125,7 @@ msgstr "Annulla" #: advancedcontentfilter.php:295 msgid "This addon requires this node having at least one post" -msgstr "" +msgstr "Questo addon richiede che questo nodo abbia almeno un messaggio" #: advancedcontentfilter.php:325 advancedcontentfilter.php:336 #: advancedcontentfilter.php:347 advancedcontentfilter.php:383 diff --git a/advancedcontentfilter/lang/it/strings.php b/advancedcontentfilter/lang/it/strings.php index 5cc01739..d47d7a5a 100644 --- a/advancedcontentfilter/lang/it/strings.php +++ b/advancedcontentfilter/lang/it/strings.php @@ -27,6 +27,7 @@ $a->strings['Add new rule'] = 'Aggiungi nuova regola'; $a->strings['Rule Name'] = 'Nome Regola'; $a->strings['Rule Expression'] = 'Espressione Regola'; $a->strings['Cancel'] = 'Annulla'; +$a->strings['This addon requires this node having at least one post'] = 'Questo addon richiede che questo nodo abbia almeno un messaggio'; $a->strings['You must be logged in to use this method'] = 'Devi essere autenticato per usare questo metodo'; $a->strings['Invalid form security token, please refresh the page.'] = 'Token di sicurezza invalido, aggiorna la pagina.'; $a->strings['The rule name and expression are required.'] = 'Il nome e l\'espressione della regola sono richiesti.'; diff --git a/advancedcontentfilter/src/middlewares.php b/advancedcontentfilter/src/middlewares.php deleted file mode 100644 index 84dd6ed8..00000000 --- a/advancedcontentfilter/src/middlewares.php +++ /dev/null @@ -1,32 +0,0 @@ -. - * - */ - -use Friendica\DI; - -/** @var $slim \Slim\App */ - -/** - * The routing middleware should be added before the ErrorMiddleware - * Otherwise exceptions thrown from it will not be handled - */ -$slim->addRoutingMiddleware(); - -$errorMiddleware = $slim->addErrorMiddleware(true, true, true); diff --git a/advancedcontentfilter/src/routes.php b/advancedcontentfilter/src/routes.php deleted file mode 100644 index a46f1b4b..00000000 --- a/advancedcontentfilter/src/routes.php +++ /dev/null @@ -1,36 +0,0 @@ -. - * - */ - -/* @var $slim Slim\App */ -$slim->group('/advancedcontentfilter/api', function (\Slim\Routing\RouteCollectorProxy $app) { - $app->group('/rules', function (\Slim\Routing\RouteCollectorProxy $app) { - $app->get('', 'advancedcontentfilter_get_rules'); - $app->post('', 'advancedcontentfilter_post_rules'); - - $app->get('/{id}', 'advancedcontentfilter_get_rules_id'); - $app->put('/{id}', 'advancedcontentfilter_put_rules_id'); - $app->delete('/{id}', 'advancedcontentfilter_delete_rules_id'); - }); - - $app->group('/variables', function (\Slim\Routing\RouteCollectorProxy $app) { - $app->get('/{guid}', 'advancedcontentfilter_get_variables_guid'); - }); -}); diff --git a/advancedcontentfilter/vendor/autoload.php b/advancedcontentfilter/vendor/autoload.php index 3e6193fa..2d273a02 100644 --- a/advancedcontentfilter/vendor/autoload.php +++ b/advancedcontentfilter/vendor/autoload.php @@ -2,6 +2,24 @@ // autoload.php @generated by Composer +if (PHP_VERSION_ID < 50600) { + if (!headers_sent()) { + header('HTTP/1.1 500 Internal Server Error'); + } + $err = 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL; + if (!ini_get('display_errors')) { + if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') { + fwrite(STDERR, $err); + } elseif (!headers_sent()) { + echo $err; + } + } + trigger_error( + $err, + E_USER_ERROR + ); +} + require_once __DIR__ . '/composer/autoload_real.php'; return ComposerAutoloaderInitAdvancedContentFilterAddon::getLoader(); diff --git a/advancedcontentfilter/vendor/composer/ClassLoader.php b/advancedcontentfilter/vendor/composer/ClassLoader.php index 03b9bb9c..7824d8f7 100644 --- a/advancedcontentfilter/vendor/composer/ClassLoader.php +++ b/advancedcontentfilter/vendor/composer/ClassLoader.php @@ -37,26 +37,81 @@ namespace Composer\Autoload; * * @author Fabien Potencier * @author Jordi Boggiano - * @see http://www.php-fig.org/psr/psr-0/ - * @see http://www.php-fig.org/psr/psr-4/ + * @see https://www.php-fig.org/psr/psr-0/ + * @see https://www.php-fig.org/psr/psr-4/ */ class ClassLoader { + /** @var \Closure(string):void */ + private static $includeFile; + + /** @var string|null */ + private $vendorDir; + // PSR-4 + /** + * @var array> + */ private $prefixLengthsPsr4 = array(); + /** + * @var array> + */ private $prefixDirsPsr4 = array(); + /** + * @var list + */ private $fallbackDirsPsr4 = array(); // PSR-0 + /** + * List of PSR-0 prefixes + * + * Structured as array('F (first letter)' => array('Foo\Bar (full prefix)' => array('path', 'path2'))) + * + * @var array>> + */ private $prefixesPsr0 = array(); + /** + * @var list + */ private $fallbackDirsPsr0 = array(); + /** @var bool */ private $useIncludePath = false; + + /** + * @var array + */ private $classMap = array(); + + /** @var bool */ private $classMapAuthoritative = false; + + /** + * @var array + */ private $missingClasses = array(); + + /** @var string|null */ private $apcuPrefix; + /** + * @var array + */ + private static $registeredLoaders = array(); + + /** + * @param string|null $vendorDir + */ + public function __construct($vendorDir = null) + { + $this->vendorDir = $vendorDir; + self::initializeIncludeClosure(); + } + + /** + * @return array> + */ public function getPrefixes() { if (!empty($this->prefixesPsr0)) { @@ -66,28 +121,42 @@ class ClassLoader return array(); } + /** + * @return array> + */ public function getPrefixesPsr4() { return $this->prefixDirsPsr4; } + /** + * @return list + */ public function getFallbackDirs() { return $this->fallbackDirsPsr0; } + /** + * @return list + */ public function getFallbackDirsPsr4() { return $this->fallbackDirsPsr4; } + /** + * @return array Array of classname => path + */ public function getClassMap() { return $this->classMap; } /** - * @param array $classMap Class to filename map + * @param array $classMap Class to filename map + * + * @return void */ public function addClassMap(array $classMap) { @@ -102,22 +171,25 @@ class ClassLoader * Registers a set of PSR-0 directories for a given prefix, either * appending or prepending to the ones previously set for this prefix. * - * @param string $prefix The prefix - * @param array|string $paths The PSR-0 root directories - * @param bool $prepend Whether to prepend the directories + * @param string $prefix The prefix + * @param list|string $paths The PSR-0 root directories + * @param bool $prepend Whether to prepend the directories + * + * @return void */ public function add($prefix, $paths, $prepend = false) { + $paths = (array) $paths; if (!$prefix) { if ($prepend) { $this->fallbackDirsPsr0 = array_merge( - (array) $paths, + $paths, $this->fallbackDirsPsr0 ); } else { $this->fallbackDirsPsr0 = array_merge( $this->fallbackDirsPsr0, - (array) $paths + $paths ); } @@ -126,19 +198,19 @@ class ClassLoader $first = $prefix[0]; if (!isset($this->prefixesPsr0[$first][$prefix])) { - $this->prefixesPsr0[$first][$prefix] = (array) $paths; + $this->prefixesPsr0[$first][$prefix] = $paths; return; } if ($prepend) { $this->prefixesPsr0[$first][$prefix] = array_merge( - (array) $paths, + $paths, $this->prefixesPsr0[$first][$prefix] ); } else { $this->prefixesPsr0[$first][$prefix] = array_merge( $this->prefixesPsr0[$first][$prefix], - (array) $paths + $paths ); } } @@ -147,25 +219,28 @@ class ClassLoader * Registers a set of PSR-4 directories for a given namespace, either * appending or prepending to the ones previously set for this namespace. * - * @param string $prefix The prefix/namespace, with trailing '\\' - * @param array|string $paths The PSR-4 base directories - * @param bool $prepend Whether to prepend the directories + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param list|string $paths The PSR-4 base directories + * @param bool $prepend Whether to prepend the directories * * @throws \InvalidArgumentException + * + * @return void */ public function addPsr4($prefix, $paths, $prepend = false) { + $paths = (array) $paths; if (!$prefix) { // Register directories for the root namespace. if ($prepend) { $this->fallbackDirsPsr4 = array_merge( - (array) $paths, + $paths, $this->fallbackDirsPsr4 ); } else { $this->fallbackDirsPsr4 = array_merge( $this->fallbackDirsPsr4, - (array) $paths + $paths ); } } elseif (!isset($this->prefixDirsPsr4[$prefix])) { @@ -175,18 +250,18 @@ class ClassLoader throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); } $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; - $this->prefixDirsPsr4[$prefix] = (array) $paths; + $this->prefixDirsPsr4[$prefix] = $paths; } elseif ($prepend) { // Prepend directories for an already registered namespace. $this->prefixDirsPsr4[$prefix] = array_merge( - (array) $paths, + $paths, $this->prefixDirsPsr4[$prefix] ); } else { // Append directories for an already registered namespace. $this->prefixDirsPsr4[$prefix] = array_merge( $this->prefixDirsPsr4[$prefix], - (array) $paths + $paths ); } } @@ -195,8 +270,10 @@ class ClassLoader * Registers a set of PSR-0 directories for a given prefix, * replacing any others previously set for this prefix. * - * @param string $prefix The prefix - * @param array|string $paths The PSR-0 base directories + * @param string $prefix The prefix + * @param list|string $paths The PSR-0 base directories + * + * @return void */ public function set($prefix, $paths) { @@ -211,10 +288,12 @@ class ClassLoader * Registers a set of PSR-4 directories for a given namespace, * replacing any others previously set for this namespace. * - * @param string $prefix The prefix/namespace, with trailing '\\' - * @param array|string $paths The PSR-4 base directories + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param list|string $paths The PSR-4 base directories * * @throws \InvalidArgumentException + * + * @return void */ public function setPsr4($prefix, $paths) { @@ -234,6 +313,8 @@ class ClassLoader * Turns on searching the include path for class files. * * @param bool $useIncludePath + * + * @return void */ public function setUseIncludePath($useIncludePath) { @@ -256,6 +337,8 @@ class ClassLoader * that have not been registered with the class map. * * @param bool $classMapAuthoritative + * + * @return void */ public function setClassMapAuthoritative($classMapAuthoritative) { @@ -276,6 +359,8 @@ class ClassLoader * APCu prefix to use to cache found/not-found classes, if the extension is enabled. * * @param string|null $apcuPrefix + * + * @return void */ public function setApcuPrefix($apcuPrefix) { @@ -296,33 +381,55 @@ class ClassLoader * Registers this instance as an autoloader. * * @param bool $prepend Whether to prepend the autoloader or not + * + * @return void */ public function register($prepend = false) { spl_autoload_register(array($this, 'loadClass'), true, $prepend); + + if (null === $this->vendorDir) { + return; + } + + if ($prepend) { + self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders; + } else { + unset(self::$registeredLoaders[$this->vendorDir]); + self::$registeredLoaders[$this->vendorDir] = $this; + } } /** * Unregisters this instance as an autoloader. + * + * @return void */ public function unregister() { spl_autoload_unregister(array($this, 'loadClass')); + + if (null !== $this->vendorDir) { + unset(self::$registeredLoaders[$this->vendorDir]); + } } /** * Loads the given class or interface. * * @param string $class The name of the class - * @return bool|null True if loaded, null otherwise + * @return true|null True if loaded, null otherwise */ public function loadClass($class) { if ($file = $this->findFile($class)) { - includeFile($file); + $includeFile = self::$includeFile; + $includeFile($file); return true; } + + return null; } /** @@ -367,6 +474,21 @@ class ClassLoader return $file; } + /** + * Returns the currently registered loaders keyed by their corresponding vendor directories. + * + * @return array + */ + public static function getRegisteredLoaders() + { + return self::$registeredLoaders; + } + + /** + * @param string $class + * @param string $ext + * @return string|false + */ private function findFileWithExtension($class, $ext) { // PSR-4 lookup @@ -432,14 +554,26 @@ class ClassLoader return false; } -} -/** - * Scope isolated include. - * - * Prevents access to $this/self from included files. - */ -function includeFile($file) -{ - include $file; + /** + * @return void + */ + private static function initializeIncludeClosure() + { + if (self::$includeFile !== null) { + return; + } + + /** + * Scope isolated include. + * + * Prevents access to $this/self from included files. + * + * @param string $file + * @return void + */ + self::$includeFile = \Closure::bind(static function($file) { + include $file; + }, null, null); + } } diff --git a/advancedcontentfilter/vendor/composer/InstalledVersions.php b/advancedcontentfilter/vendor/composer/InstalledVersions.php new file mode 100644 index 00000000..51e734a7 --- /dev/null +++ b/advancedcontentfilter/vendor/composer/InstalledVersions.php @@ -0,0 +1,359 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer; + +use Composer\Autoload\ClassLoader; +use Composer\Semver\VersionParser; + +/** + * This class is copied in every Composer installed project and available to all + * + * See also https://getcomposer.org/doc/07-runtime.md#installed-versions + * + * To require its presence, you can require `composer-runtime-api ^2.0` + * + * @final + */ +class InstalledVersions +{ + /** + * @var mixed[]|null + * @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array}|array{}|null + */ + private static $installed; + + /** + * @var bool|null + */ + private static $canGetVendors; + + /** + * @var array[] + * @psalm-var array}> + */ + private static $installedByVendor = array(); + + /** + * Returns a list of all package names which are present, either by being installed, replaced or provided + * + * @return string[] + * @psalm-return list + */ + public static function getInstalledPackages() + { + $packages = array(); + foreach (self::getInstalled() as $installed) { + $packages[] = array_keys($installed['versions']); + } + + if (1 === \count($packages)) { + return $packages[0]; + } + + return array_keys(array_flip(\call_user_func_array('array_merge', $packages))); + } + + /** + * Returns a list of all package names with a specific type e.g. 'library' + * + * @param string $type + * @return string[] + * @psalm-return list + */ + public static function getInstalledPackagesByType($type) + { + $packagesByType = array(); + + foreach (self::getInstalled() as $installed) { + foreach ($installed['versions'] as $name => $package) { + if (isset($package['type']) && $package['type'] === $type) { + $packagesByType[] = $name; + } + } + } + + return $packagesByType; + } + + /** + * Checks whether the given package is installed + * + * This also returns true if the package name is provided or replaced by another package + * + * @param string $packageName + * @param bool $includeDevRequirements + * @return bool + */ + public static function isInstalled($packageName, $includeDevRequirements = true) + { + foreach (self::getInstalled() as $installed) { + if (isset($installed['versions'][$packageName])) { + return $includeDevRequirements || !isset($installed['versions'][$packageName]['dev_requirement']) || $installed['versions'][$packageName]['dev_requirement'] === false; + } + } + + return false; + } + + /** + * Checks whether the given package satisfies a version constraint + * + * e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call: + * + * Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3') + * + * @param VersionParser $parser Install composer/semver to have access to this class and functionality + * @param string $packageName + * @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package + * @return bool + */ + public static function satisfies(VersionParser $parser, $packageName, $constraint) + { + $constraint = $parser->parseConstraints((string) $constraint); + $provided = $parser->parseConstraints(self::getVersionRanges($packageName)); + + return $provided->matches($constraint); + } + + /** + * Returns a version constraint representing all the range(s) which are installed for a given package + * + * It is easier to use this via isInstalled() with the $constraint argument if you need to check + * whether a given version of a package is installed, and not just whether it exists + * + * @param string $packageName + * @return string Version constraint usable with composer/semver + */ + public static function getVersionRanges($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + $ranges = array(); + if (isset($installed['versions'][$packageName]['pretty_version'])) { + $ranges[] = $installed['versions'][$packageName]['pretty_version']; + } + if (array_key_exists('aliases', $installed['versions'][$packageName])) { + $ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']); + } + if (array_key_exists('replaced', $installed['versions'][$packageName])) { + $ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']); + } + if (array_key_exists('provided', $installed['versions'][$packageName])) { + $ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']); + } + + return implode(' || ', $ranges); + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @param string $packageName + * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present + */ + public static function getVersion($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + if (!isset($installed['versions'][$packageName]['version'])) { + return null; + } + + return $installed['versions'][$packageName]['version']; + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @param string $packageName + * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present + */ + public static function getPrettyVersion($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + if (!isset($installed['versions'][$packageName]['pretty_version'])) { + return null; + } + + return $installed['versions'][$packageName]['pretty_version']; + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @param string $packageName + * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference + */ + public static function getReference($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + if (!isset($installed['versions'][$packageName]['reference'])) { + return null; + } + + return $installed['versions'][$packageName]['reference']; + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @param string $packageName + * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path. + */ + public static function getInstallPath($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null; + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @return array + * @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool} + */ + public static function getRootPackage() + { + $installed = self::getInstalled(); + + return $installed[0]['root']; + } + + /** + * Returns the raw installed.php data for custom implementations + * + * @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect. + * @return array[] + * @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} + */ + public static function getRawData() + { + @trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED); + + if (null === self::$installed) { + // only require the installed.php file if this file is loaded from its dumped location, + // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937 + if (substr(__DIR__, -8, 1) !== 'C') { + self::$installed = include __DIR__ . '/installed.php'; + } else { + self::$installed = array(); + } + } + + return self::$installed; + } + + /** + * Returns the raw data of all installed.php which are currently loaded for custom implementations + * + * @return array[] + * @psalm-return list}> + */ + public static function getAllRawData() + { + return self::getInstalled(); + } + + /** + * Lets you reload the static array from another file + * + * This is only useful for complex integrations in which a project needs to use + * this class but then also needs to execute another project's autoloader in process, + * and wants to ensure both projects have access to their version of installed.php. + * + * A typical case would be PHPUnit, where it would need to make sure it reads all + * the data it needs from this class, then call reload() with + * `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure + * the project in which it runs can then also use this class safely, without + * interference between PHPUnit's dependencies and the project's dependencies. + * + * @param array[] $data A vendor/composer/installed.php data set + * @return void + * + * @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} $data + */ + public static function reload($data) + { + self::$installed = $data; + self::$installedByVendor = array(); + } + + /** + * @return array[] + * @psalm-return list}> + */ + private static function getInstalled() + { + if (null === self::$canGetVendors) { + self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders'); + } + + $installed = array(); + + if (self::$canGetVendors) { + foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) { + if (isset(self::$installedByVendor[$vendorDir])) { + $installed[] = self::$installedByVendor[$vendorDir]; + } elseif (is_file($vendorDir.'/composer/installed.php')) { + /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} $required */ + $required = require $vendorDir.'/composer/installed.php'; + $installed[] = self::$installedByVendor[$vendorDir] = $required; + if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) { + self::$installed = $installed[count($installed) - 1]; + } + } + } + } + + if (null === self::$installed) { + // only require the installed.php file if this file is loaded from its dumped location, + // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937 + if (substr(__DIR__, -8, 1) !== 'C') { + /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} $required */ + $required = require __DIR__ . '/installed.php'; + self::$installed = $required; + } else { + self::$installed = array(); + } + } + + if (self::$installed !== array()) { + $installed[] = self::$installed; + } + + return $installed; + } +} diff --git a/advancedcontentfilter/vendor/composer/autoload_classmap.php b/advancedcontentfilter/vendor/composer/autoload_classmap.php index aa3de8a3..fe2a622a 100644 --- a/advancedcontentfilter/vendor/composer/autoload_classmap.php +++ b/advancedcontentfilter/vendor/composer/autoload_classmap.php @@ -2,10 +2,12 @@ // autoload_classmap.php @generated by Composer -$vendorDir = dirname(dirname(__FILE__)); +$vendorDir = dirname(__DIR__); $baseDir = dirname($vendorDir); return array( + 'Attribute' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Attribute.php', + 'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.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 +25,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 +60,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 +76,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,32 +132,47 @@ 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', 'Symfony\\Component\\Cache\\Adapter\\TraceableAdapter' => $vendorDir . '/symfony/cache/Adapter/TraceableAdapter.php', - 'Symfony\\Component\\Cache\\Adapter\\TraceableAdapterEvent' => $vendorDir . '/symfony/cache/Adapter/TraceableAdapter.php', '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', @@ -171,10 +188,11 @@ return array( 'Symfony\\Component\\Cache\\Simple\\Psr6Cache' => $vendorDir . '/symfony/cache/Simple/Psr6Cache.php', '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', @@ -183,6 +201,8 @@ return array( '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 +230,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..aafd69e1 100644 --- a/advancedcontentfilter/vendor/composer/autoload_files.php +++ b/advancedcontentfilter/vendor/composer/autoload_files.php @@ -2,10 +2,12 @@ // autoload_files.php @generated by Composer -$vendorDir = dirname(dirname(__FILE__)); +$vendorDir = dirname(__DIR__); $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_namespaces.php b/advancedcontentfilter/vendor/composer/autoload_namespaces.php index b7fc0125..15a2ff3a 100644 --- a/advancedcontentfilter/vendor/composer/autoload_namespaces.php +++ b/advancedcontentfilter/vendor/composer/autoload_namespaces.php @@ -2,7 +2,7 @@ // autoload_namespaces.php @generated by Composer -$vendorDir = dirname(dirname(__FILE__)); +$vendorDir = dirname(__DIR__); $baseDir = dirname($vendorDir); return array( diff --git a/advancedcontentfilter/vendor/composer/autoload_psr4.php b/advancedcontentfilter/vendor/composer/autoload_psr4.php index 87606585..4bf247ce 100644 --- a/advancedcontentfilter/vendor/composer/autoload_psr4.php +++ b/advancedcontentfilter/vendor/composer/autoload_psr4.php @@ -2,18 +2,21 @@ // autoload_psr4.php @generated by Composer -$vendorDir = dirname(dirname(__FILE__)); +$vendorDir = dirname(__DIR__); $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'), + 'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-message/src', $vendorDir . '/psr/http-factory/src'), 'Psr\\Container\\' => array($vendorDir . '/psr/container/src'), 'Psr\\Cache\\' => array($vendorDir . '/psr/cache/src'), 'FastRoute\\' => array($vendorDir . '/nikic/fast-route/src'), diff --git a/advancedcontentfilter/vendor/composer/autoload_real.php b/advancedcontentfilter/vendor/composer/autoload_real.php index d6532d7d..b305aa00 100644 --- a/advancedcontentfilter/vendor/composer/autoload_real.php +++ b/advancedcontentfilter/vendor/composer/autoload_real.php @@ -22,52 +22,29 @@ class ComposerAutoloaderInitAdvancedContentFilterAddon return self::$loader; } + require __DIR__ . '/platform_check.php'; + spl_autoload_register(array('ComposerAutoloaderInitAdvancedContentFilterAddon', 'loadClassLoader'), true, true); - self::$loader = $loader = new \Composer\Autoload\ClassLoader(); + self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__)); spl_autoload_unregister(array('ComposerAutoloaderInitAdvancedContentFilterAddon', 'loadClassLoader')); - $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded()); - if ($useStaticLoader) { - require_once __DIR__ . '/autoload_static.php'; - - call_user_func(\Composer\Autoload\ComposerStaticInitAdvancedContentFilterAddon::getInitializer($loader)); - } else { - $map = require __DIR__ . '/autoload_namespaces.php'; - foreach ($map as $namespace => $path) { - $loader->set($namespace, $path); - } - - $map = require __DIR__ . '/autoload_psr4.php'; - foreach ($map as $namespace => $path) { - $loader->setPsr4($namespace, $path); - } - - $classMap = require __DIR__ . '/autoload_classmap.php'; - if ($classMap) { - $loader->addClassMap($classMap); - } - } + require __DIR__ . '/autoload_static.php'; + call_user_func(\Composer\Autoload\ComposerStaticInitAdvancedContentFilterAddon::getInitializer($loader)); $loader->register(true); - if ($useStaticLoader) { - $includeFiles = Composer\Autoload\ComposerStaticInitAdvancedContentFilterAddon::$files; - } else { - $includeFiles = require __DIR__ . '/autoload_files.php'; - } - foreach ($includeFiles as $fileIdentifier => $file) { - composerRequireAdvancedContentFilterAddon($fileIdentifier, $file); + $filesToLoad = \Composer\Autoload\ComposerStaticInitAdvancedContentFilterAddon::$files; + $requireFile = \Closure::bind(static function ($fileIdentifier, $file) { + if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { + $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; + + require $file; + } + }, null, null); + foreach ($filesToLoad as $fileIdentifier => $file) { + $requireFile($fileIdentifier, $file); } return $loader; } } - -function composerRequireAdvancedContentFilterAddon($fileIdentifier, $file) -{ - if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { - require $file; - - $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; - } -} diff --git a/advancedcontentfilter/vendor/composer/autoload_static.php b/advancedcontentfilter/vendor/composer/autoload_static.php index 917d3d90..8cc48b1a 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', @@ -66,8 +83,8 @@ class ComposerStaticInitAdvancedContentFilterAddon ), 'Psr\\Http\\Message\\' => array ( - 0 => __DIR__ . '/..' . '/psr/http-factory/src', - 1 => __DIR__ . '/..' . '/psr/http-message/src', + 0 => __DIR__ . '/..' . '/psr/http-message/src', + 1 => __DIR__ . '/..' . '/psr/http-factory/src', ), 'Psr\\Container\\' => array ( @@ -84,6 +101,8 @@ class ComposerStaticInitAdvancedContentFilterAddon ); public static $classMap = array ( + 'Attribute' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Attribute.php', + 'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.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 +120,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 +155,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 +171,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,32 +227,47 @@ 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', 'Symfony\\Component\\Cache\\Adapter\\TraceableAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/TraceableAdapter.php', - 'Symfony\\Component\\Cache\\Adapter\\TraceableAdapterEvent' => __DIR__ . '/..' . '/symfony/cache/Adapter/TraceableAdapter.php', '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', @@ -249,10 +283,11 @@ class ComposerStaticInitAdvancedContentFilterAddon 'Symfony\\Component\\Cache\\Simple\\Psr6Cache' => __DIR__ . '/..' . '/symfony/cache/Simple/Psr6Cache.php', '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', @@ -261,6 +296,8 @@ class ComposerStaticInitAdvancedContentFilterAddon '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 +325,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..70c2dc41 100644 --- a/advancedcontentfilter/vendor/composer/installed.json +++ b/advancedcontentfilter/vendor/composer/installed.json @@ -1,856 +1,1212 @@ -[ - { - "name": "nikic/fast-route", - "version": "v1.3.0", - "version_normalized": "1.3.0.0", - "source": { - "type": "git", - "url": "https://github.com/nikic/FastRoute.git", - "reference": "181d480e08d9476e61381e04a71b34dc0432e812" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nikic/FastRoute/zipball/181d480e08d9476e61381e04a71b34dc0432e812", - "reference": "181d480e08d9476e61381e04a71b34dc0432e812", - "shasum": "" - }, - "require": { - "php": ">=5.4.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.8.35|~5.7" - }, - "time": "2018-02-13T20:26:39+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "FastRoute\\": "src/" +{ + "packages": [ + { + "name": "nikic/fast-route", + "version": "v1.3.0", + "version_normalized": "1.3.0.0", + "source": { + "type": "git", + "url": "https://github.com/nikic/FastRoute.git", + "reference": "181d480e08d9476e61381e04a71b34dc0432e812" }, - "files": [ - "src/functions.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Nikita Popov", - "email": "nikic@php.net" - } - ], - "description": "Fast request router for PHP", - "keywords": [ - "router", - "routing" - ] - }, - { - "name": "psr/cache", - "version": "1.0.1", - "version_normalized": "1.0.1.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/cache.git", - "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/cache/zipball/d11b50ad223250cf17b86e38383413f5a6764bf8", - "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "time": "2016-08-06T20:24:11+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Psr\\Cache\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Common interface for caching libraries", - "keywords": [ - "cache", - "psr", - "psr-6" - ] - }, - { - "name": "psr/container", - "version": "2.0.2", - "version_normalized": "2.0.2.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/container.git", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", - "shasum": "" - }, - "require": { - "php": ">=7.4.0" - }, - "time": "2021-11-05T16:47:00+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Psr\\Container\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common Container Interface (PHP FIG PSR-11)", - "homepage": "https://github.com/php-fig/container", - "keywords": [ - "PSR-11", - "container", - "container-interface", - "container-interop", - "psr" - ] - }, - { - "name": "psr/http-factory", - "version": "1.0.2", - "version_normalized": "1.0.2.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/http-factory.git", - "reference": "e616d01114759c4c489f93b099585439f795fe35" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-factory/zipball/e616d01114759c4c489f93b099585439f795fe35", - "reference": "e616d01114759c4c489f93b099585439f795fe35", - "shasum": "" - }, - "require": { - "php": ">=7.0.0", - "psr/http-message": "^1.0 || ^2.0" - }, - "time": "2023-04-10T20:10:41+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Psr\\Http\\Message\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common interfaces for PSR-7 HTTP message factories", - "keywords": [ - "factory", - "http", - "message", - "psr", - "psr-17", - "psr-7", - "request", - "response" - ] - }, - { - "name": "psr/http-message", - "version": "1.1", - "version_normalized": "1.1.0.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/http-message.git", - "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/cb6ce4845ce34a8ad9e68117c10ee90a29919eba", - "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "time": "2023-04-04T09:50:52+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.1.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Psr\\Http\\Message\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Common interface for HTTP messages", - "homepage": "https://github.com/php-fig/http-message", - "keywords": [ - "http", - "http-message", - "psr", - "psr-7", - "request", - "response" - ] - }, - { - "name": "psr/http-server-handler", - "version": "1.0.2", - "version_normalized": "1.0.2.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/http-server-handler.git", - "reference": "84c4fb66179be4caaf8e97bd239203245302e7d4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-server-handler/zipball/84c4fb66179be4caaf8e97bd239203245302e7d4", - "reference": "84c4fb66179be4caaf8e97bd239203245302e7d4", - "shasum": "" - }, - "require": { - "php": ">=7.0", - "psr/http-message": "^1.0 || ^2.0" - }, - "time": "2023-04-10T20:06:20+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Psr\\Http\\Server\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common interface for HTTP server-side request handler", - "keywords": [ - "handler", - "http", - "http-interop", - "psr", - "psr-15", - "psr-7", - "request", - "response", - "server" - ] - }, - { - "name": "psr/http-server-middleware", - "version": "1.0.2", - "version_normalized": "1.0.2.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/http-server-middleware.git", - "reference": "c1481f747daaa6a0782775cd6a8c26a1bf4a3829" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-server-middleware/zipball/c1481f747daaa6a0782775cd6a8c26a1bf4a3829", - "reference": "c1481f747daaa6a0782775cd6a8c26a1bf4a3829", - "shasum": "" - }, - "require": { - "php": ">=7.0", - "psr/http-message": "^1.0 || ^2.0", - "psr/http-server-handler": "^1.0" - }, - "time": "2023-04-11T06:14:47+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Psr\\Http\\Server\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common interface for HTTP server-side middleware", - "keywords": [ - "http", - "http-interop", - "middleware", - "psr", - "psr-15", - "psr-7", - "request", - "response" - ] - }, - { - "name": "psr/log", - "version": "1.1.4", - "version_normalized": "1.1.4.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "d49695b909c3b7628b6289db5479a1c204601f11" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11", - "reference": "d49695b909c3b7628b6289db5479a1c204601f11", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "time": "2021-05-03T11:20:27+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.1.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Psr\\Log\\": "Psr/Log/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", - "keywords": [ - "log", - "psr", - "psr-3" - ] - }, - { - "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", - "source": { - "type": "git", - "url": "https://github.com/slimphp/Slim.git", - "reference": "e9e99c2b24398b967841c6c4c3048622cc7e2b18" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/slimphp/Slim/zipball/e9e99c2b24398b967841c6c4c3048622cc7e2b18", - "reference": "e9e99c2b24398b967841c6c4c3048622cc7e2b18", - "shasum": "" - }, - "require": { - "ext-json": "*", - "nikic/fast-route": "^1.3", - "php": "^7.4 || ^8.0", - "psr/container": "^1.0 || ^2.0", - "psr/http-factory": "^1.0", - "psr/http-message": "^1.1", - "psr/http-server-handler": "^1.0", - "psr/http-server-middleware": "^1.0", - "psr/log": "^1.1 || ^2.0 || ^3.0" - }, - "require-dev": { - "adriansuter/php-autoload-override": "^1.4", - "ext-simplexml": "*", - "guzzlehttp/psr7": "^2.5", - "httpsoft/http-message": "^1.1", - "httpsoft/http-server-request": "^1.1", - "laminas/laminas-diactoros": "^2.17", - "nyholm/psr7": "^1.8", - "nyholm/psr7-server": "^1.0", - "phpspec/prophecy": "^1.17", - "phpspec/prophecy-phpunit": "^2.0", - "phpstan/phpstan": "^1.10", - "phpunit/phpunit": "^9.6", - "slim/http": "^1.3", - "slim/psr7": "^1.6", - "squizlabs/php_codesniffer": "^3.7" - }, - "suggest": { - "ext-simplexml": "Needed to support XML format in BodyParsingMiddleware", - "ext-xml": "Needed to support XML format in BodyParsingMiddleware", - "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", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "Slim\\": "Slim" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Josh Lockhart", - "email": "hello@joshlockhart.com", - "homepage": "https://joshlockhart.com" + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/FastRoute/zipball/181d480e08d9476e61381e04a71b34dc0432e812", + "reference": "181d480e08d9476e61381e04a71b34dc0432e812", + "shasum": "" }, - { - "name": "Andrew Smith", - "email": "a.smith@silentworks.co.uk", - "homepage": "http://silentworks.co.uk" + "require": { + "php": ">=5.4.0" }, - { - "name": "Rob Allen", - "email": "rob@akrabat.com", - "homepage": "http://akrabat.com" + "require-dev": { + "phpunit/phpunit": "^4.8.35|~5.7" }, - { - "name": "Pierre Berube", - "email": "pierre@lgse.com", - "homepage": "http://www.lgse.com" + "time": "2018-02-13T20:26:39+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "FastRoute\\": "src/" + }, + "files": [ + "src/functions.php" + ] }, - { - "name": "Gabriel Manricks", - "email": "gmanricks@me.com", - "homepage": "http://gabrielmanricks.com" - } - ], - "description": "Slim is a PHP micro framework that helps you quickly write simple yet powerful web applications and APIs", - "homepage": "https://www.slimframework.com", - "keywords": [ - "api", - "framework", - "micro", - "router" - ], - "funding": [ - { - "url": "https://opencollective.com/slimphp", - "type": "open_collective" - }, - { - "url": "https://tidelift.com/funding/github/packagist/slim/slim", - "type": "tidelift" - } - ] - }, - { - "name": "symfony/cache", - "version": "v3.4.47", - "version_normalized": "3.4.47.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/cache.git", - "reference": "a7a14c4832760bd1fbd31be2859ffedc9b6ff813" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/a7a14c4832760bd1fbd31be2859ffedc9b6ff813", - "reference": "a7a14c4832760bd1fbd31be2859ffedc9b6ff813", - "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" - }, - "conflict": { - "symfony/var-dumper": "<3.3" - }, - "provide": { - "psr/cache-implementation": "1.0", - "psr/simple-cache-implementation": "1.0" - }, - "require-dev": { - "cache/integration-tests": "dev-master", - "doctrine/cache": "^1.6", - "doctrine/dbal": "^2.4|^3.0", - "predis/predis": "^1.0" - }, - "time": "2020-10-24T10:57:07+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\Cache\\": "" - }, - "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": "Symfony Cache component with PSR-6, PSR-16, and tags", - "homepage": "https://symfony.com", - "keywords": [ - "caching", - "psr6" - ], - "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", - "version_normalized": "3.4.47.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/expression-language.git", - "reference": "de38e66398fca1fcb9c48e80279910e6889cb28f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/expression-language/zipball/de38e66398fca1fcb9c48e80279910e6889cb28f", - "reference": "de38e66398fca1fcb9c48e80279910e6889cb28f", - "shasum": "" - }, - "require": { - "php": "^5.5.9|>=7.0.8", - "symfony/cache": "~3.1|~4.0", - "symfony/polyfill-php70": "~1.6" - }, - "time": "2020-10-24T10:57:07+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\ExpressionLanguage\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony ExpressionLanguage Component", - "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/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" + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" ], - "psr-4": { - "Symfony\\Polyfill\\Apcu\\": "" - } + "authors": [ + { + "name": "Nikita Popov", + "email": "nikic@php.net" + } + ], + "description": "Fast request router for PHP", + "keywords": [ + "router", + "routing" + ], + "install-path": "../nikic/fast-route" }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" + { + "name": "psr/cache", + "version": "1.0.1", + "version_normalized": "1.0.1.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/cache.git", + "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8" }, - { - "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" + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/cache/zipball/d11b50ad223250cf17b86e38383413f5a6764bf8", + "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8", + "shasum": "" }, - { - "url": "https://github.com/fabpot", - "type": "github" + "require": { + "php": ">=5.3.0" }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ] - }, - { - "name": "symfony/polyfill-php70", - "version": "v1.20.0", - "version_normalized": "1.20.0.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php70.git", - "reference": "5f03a781d984aae42cebd18e7912fa80f02ee644" + "time": "2016-08-06T20:24:11+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Psr\\Cache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for caching libraries", + "keywords": [ + "cache", + "psr", + "psr-6" + ], + "install-path": "../psr/cache" }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/5f03a781d984aae42cebd18e7912fa80f02ee644", - "reference": "5f03a781d984aae42cebd18e7912fa80f02ee644", - "shasum": "" + { + "name": "psr/container", + "version": "1.1.2", + "version_normalized": "1.1.2.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "513e0666f7216c7459170d56df27dfcefe1689ea" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea", + "reference": "513e0666f7216c7459170d56df27dfcefe1689ea", + "shasum": "" + }, + "require": { + "php": ">=7.4.0" + }, + "time": "2021-11-05T16:50:12+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "install-path": "../psr/container" }, - "require": { - "php": ">=7.1" + { + "name": "psr/http-factory", + "version": "1.0.2", + "version_normalized": "1.0.2.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-factory.git", + "reference": "e616d01114759c4c489f93b099585439f795fe35" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/e616d01114759c4c489f93b099585439f795fe35", + "reference": "e616d01114759c4c489f93b099585439f795fe35", + "shasum": "" + }, + "require": { + "php": ">=7.0.0", + "psr/http-message": "^1.0 || ^2.0" + }, + "time": "2023-04-10T20:10:41+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interfaces for PSR-7 HTTP message factories", + "keywords": [ + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" + ], + "install-path": "../psr/http-factory" }, - "time": "2020-10-23T14:02:19+00:00", - "type": "metapackage", - "extra": { - "branch-alias": { - "dev-main": "1.20-dev" + { + "name": "psr/http-message", + "version": "2.0", + "version_normalized": "2.0.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } + "dist": { + "type": "zip", + "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:54:51+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "install-path": "../psr/http-message" }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" + { + "name": "psr/http-server-handler", + "version": "1.0.2", + "version_normalized": "1.0.2.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-server-handler.git", + "reference": "84c4fb66179be4caaf8e97bd239203245302e7d4" }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 7.0+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-server-handler/zipball/84c4fb66179be4caaf8e97bd239203245302e7d4", + "reference": "84c4fb66179be4caaf8e97bd239203245302e7d4", + "shasum": "" }, - { - "url": "https://github.com/fabpot", - "type": "github" + "require": { + "php": ">=7.0", + "psr/http-message": "^1.0 || ^2.0" }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ] - } -] + "time": "2023-04-10T20:06:20+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Psr\\Http\\Server\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP server-side request handler", + "keywords": [ + "handler", + "http", + "http-interop", + "psr", + "psr-15", + "psr-7", + "request", + "response", + "server" + ], + "install-path": "../psr/http-server-handler" + }, + { + "name": "psr/http-server-middleware", + "version": "1.0.2", + "version_normalized": "1.0.2.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-server-middleware.git", + "reference": "c1481f747daaa6a0782775cd6a8c26a1bf4a3829" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-server-middleware/zipball/c1481f747daaa6a0782775cd6a8c26a1bf4a3829", + "reference": "c1481f747daaa6a0782775cd6a8c26a1bf4a3829", + "shasum": "" + }, + "require": { + "php": ">=7.0", + "psr/http-message": "^1.0 || ^2.0", + "psr/http-server-handler": "^1.0" + }, + "time": "2023-04-11T06:14:47+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Psr\\Http\\Server\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP server-side middleware", + "keywords": [ + "http", + "http-interop", + "middleware", + "psr", + "psr-15", + "psr-7", + "request", + "response" + ], + "install-path": "../psr/http-server-middleware" + }, + { + "name": "psr/log", + "version": "1.1.4", + "version_normalized": "1.1.4.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "d49695b909c3b7628b6289db5479a1c204601f11" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11", + "reference": "d49695b909c3b7628b6289db5479a1c204601f11", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "time": "2021-05-03T11:20:27+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Psr\\Log\\": "Psr/Log/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "install-path": "../psr/log" + }, + { + "name": "slim/slim", + "version": "4.13.0", + "version_normalized": "4.13.0.0", + "source": { + "type": "git", + "url": "https://github.com/slimphp/Slim.git", + "reference": "038fd5713d5a41636fdff0e8dcceedecdd17fc17" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/slimphp/Slim/zipball/038fd5713d5a41636fdff0e8dcceedecdd17fc17", + "reference": "038fd5713d5a41636fdff0e8dcceedecdd17fc17", + "shasum": "" + }, + "require": { + "ext-json": "*", + "nikic/fast-route": "^1.3", + "php": "^7.4 || ^8.0", + "psr/container": "^1.0 || ^2.0", + "psr/http-factory": "^1.0", + "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" + }, + "require-dev": { + "adriansuter/php-autoload-override": "^1.4", + "ext-simplexml": "*", + "guzzlehttp/psr7": "^2.6", + "httpsoft/http-message": "^1.1", + "httpsoft/http-server-request": "^1.1", + "laminas/laminas-diactoros": "^2.17 || ^3", + "nyholm/psr7": "^1.8", + "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.9" + }, + "suggest": { + "ext-simplexml": "Needed to support XML format in BodyParsingMiddleware", + "ext-xml": "Needed to support XML format in BodyParsingMiddleware", + "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": "2024-03-03T21:25:30+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Slim\\": "Slim" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Josh Lockhart", + "email": "hello@joshlockhart.com", + "homepage": "https://joshlockhart.com" + }, + { + "name": "Andrew Smith", + "email": "a.smith@silentworks.co.uk", + "homepage": "http://silentworks.co.uk" + }, + { + "name": "Rob Allen", + "email": "rob@akrabat.com", + "homepage": "http://akrabat.com" + }, + { + "name": "Pierre Berube", + "email": "pierre@lgse.com", + "homepage": "http://www.lgse.com" + }, + { + "name": "Gabriel Manricks", + "email": "gmanricks@me.com", + "homepage": "http://gabrielmanricks.com" + } + ], + "description": "Slim is a PHP micro framework that helps you quickly write simple yet powerful web applications and APIs", + "homepage": "https://www.slimframework.com", + "keywords": [ + "api", + "framework", + "micro", + "router" + ], + "funding": [ + { + "url": "https://opencollective.com/slimphp", + "type": "open_collective" + }, + { + "url": "https://tidelift.com/funding/github/packagist/slim/slim", + "type": "tidelift" + } + ], + "install-path": "../slim/slim" + }, + { + "name": "symfony/cache", + "version": "v4.4.48", + "version_normalized": "4.4.48.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/cache.git", + "reference": "3b98ed664887ad197b8ede3da2432787212eb915" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/cache/zipball/3b98ed664887ad197b8ede3da2432787212eb915", + "reference": "3b98ed664887ad197b8ede3da2432787212eb915", + "shasum": "" + }, + "require": { + "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": { + "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|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|^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": "2022-10-17T20:21:54+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\Cache\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides extended PSR-6, PSR-16 (and tags) implementations", + "homepage": "https://symfony.com", + "keywords": [ + "caching", + "psr6" + ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "install-path": "../symfony/cache" + }, + { + "name": "symfony/cache-contracts", + "version": "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" + } + ], + "install-path": "../symfony/cache-contracts" + }, + { + "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" + } + ], + "install-path": "../symfony/deprecation-contracts" + }, + { + "name": "symfony/expression-language", + "version": "v3.4.47", + "version_normalized": "3.4.47.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/expression-language.git", + "reference": "de38e66398fca1fcb9c48e80279910e6889cb28f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/expression-language/zipball/de38e66398fca1fcb9c48e80279910e6889cb28f", + "reference": "de38e66398fca1fcb9c48e80279910e6889cb28f", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8", + "symfony/cache": "~3.1|~4.0", + "symfony/polyfill-php70": "~1.6" + }, + "time": "2020-10-24T10:57:07+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\ExpressionLanguage\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony ExpressionLanguage Component", + "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" + } + ], + "install-path": "../symfony/expression-language" + }, + { + "name": "symfony/polyfill-php70", + "version": "v1.20.0", + "version_normalized": "1.20.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php70.git", + "reference": "5f03a781d984aae42cebd18e7912fa80f02ee644" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/5f03a781d984aae42cebd18e7912fa80f02ee644", + "reference": "5f03a781d984aae42cebd18e7912fa80f02ee644", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "time": "2020-10-23T14:02:19+00:00", + "type": "metapackage", + "extra": { + "branch-alias": { + "dev-main": "1.20-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "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.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" + } + ], + "install-path": null + }, + { + "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" + } + ], + "install-path": "../symfony/polyfill-php73" + }, + { + "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" + } + ], + "install-path": "../symfony/polyfill-php80" + }, + { + "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" + } + ], + "install-path": "../symfony/service-contracts" + }, + { + "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" + } + ], + "install-path": "../symfony/var-exporter" + } + ], + "dev": false, + "dev-package-names": [] +} diff --git a/advancedcontentfilter/vendor/composer/installed.php b/advancedcontentfilter/vendor/composer/installed.php new file mode 100644 index 00000000..010b1da9 --- /dev/null +++ b/advancedcontentfilter/vendor/composer/installed.php @@ -0,0 +1,203 @@ + array( + 'name' => 'friendica-addons/advancedcontentfilter', + 'pretty_version' => 'dev-develop', + 'version' => 'dev-develop', + 'reference' => 'feb7722f723b21e76fdf20a7ce4b42fa5ffcdcb9', + 'type' => 'friendica-addon', + 'install_path' => __DIR__ . '/../../', + 'aliases' => array(), + 'dev' => false, + ), + 'versions' => array( + 'friendica-addons/advancedcontentfilter' => array( + 'pretty_version' => 'dev-develop', + 'version' => 'dev-develop', + 'reference' => 'feb7722f723b21e76fdf20a7ce4b42fa5ffcdcb9', + 'type' => 'friendica-addon', + 'install_path' => __DIR__ . '/../../', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'nikic/fast-route' => array( + 'pretty_version' => 'v1.3.0', + 'version' => '1.3.0.0', + 'reference' => '181d480e08d9476e61381e04a71b34dc0432e812', + 'type' => 'library', + 'install_path' => __DIR__ . '/../nikic/fast-route', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'psr/cache' => array( + 'pretty_version' => '1.0.1', + 'version' => '1.0.1.0', + 'reference' => 'd11b50ad223250cf17b86e38383413f5a6764bf8', + 'type' => 'library', + 'install_path' => __DIR__ . '/../psr/cache', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'psr/cache-implementation' => array( + 'dev_requirement' => false, + 'provided' => array( + 0 => '1.0|2.0', + ), + ), + 'psr/container' => array( + 'pretty_version' => '1.1.2', + 'version' => '1.1.2.0', + 'reference' => '513e0666f7216c7459170d56df27dfcefe1689ea', + 'type' => 'library', + 'install_path' => __DIR__ . '/../psr/container', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'psr/http-factory' => array( + 'pretty_version' => '1.0.2', + 'version' => '1.0.2.0', + 'reference' => 'e616d01114759c4c489f93b099585439f795fe35', + 'type' => 'library', + 'install_path' => __DIR__ . '/../psr/http-factory', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'psr/http-message' => array( + 'pretty_version' => '2.0', + 'version' => '2.0.0.0', + 'reference' => '402d35bcb92c70c026d1a6a9883f06b2ead23d71', + 'type' => 'library', + 'install_path' => __DIR__ . '/../psr/http-message', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'psr/http-server-handler' => array( + 'pretty_version' => '1.0.2', + 'version' => '1.0.2.0', + 'reference' => '84c4fb66179be4caaf8e97bd239203245302e7d4', + 'type' => 'library', + 'install_path' => __DIR__ . '/../psr/http-server-handler', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'psr/http-server-middleware' => array( + 'pretty_version' => '1.0.2', + 'version' => '1.0.2.0', + 'reference' => 'c1481f747daaa6a0782775cd6a8c26a1bf4a3829', + 'type' => 'library', + 'install_path' => __DIR__ . '/../psr/http-server-middleware', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'psr/log' => array( + 'pretty_version' => '1.1.4', + 'version' => '1.1.4.0', + 'reference' => 'd49695b909c3b7628b6289db5479a1c204601f11', + 'type' => 'library', + 'install_path' => __DIR__ . '/../psr/log', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'psr/simple-cache-implementation' => array( + 'dev_requirement' => false, + 'provided' => array( + 0 => '1.0|2.0', + ), + ), + 'slim/slim' => array( + 'pretty_version' => '4.13.0', + 'version' => '4.13.0.0', + 'reference' => '038fd5713d5a41636fdff0e8dcceedecdd17fc17', + 'type' => 'library', + 'install_path' => __DIR__ . '/../slim/slim', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'symfony/cache' => array( + 'pretty_version' => 'v4.4.48', + 'version' => '4.4.48.0', + 'reference' => '3b98ed664887ad197b8ede3da2432787212eb915', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/cache', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'symfony/cache-contracts' => array( + 'pretty_version' => 'v2.5.2', + 'version' => '2.5.2.0', + 'reference' => '64be4a7acb83b6f2bf6de9a02cee6dad41277ebc', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/cache-contracts', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'symfony/cache-implementation' => array( + 'dev_requirement' => false, + 'provided' => array( + 0 => '1.0|2.0', + ), + ), + 'symfony/deprecation-contracts' => array( + 'pretty_version' => 'v2.5.2', + 'version' => '2.5.2.0', + 'reference' => 'e8b495ea28c1d97b5e0c121748d6f9b53d075c66', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/deprecation-contracts', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'symfony/expression-language' => array( + 'pretty_version' => 'v3.4.47', + 'version' => '3.4.47.0', + 'reference' => 'de38e66398fca1fcb9c48e80279910e6889cb28f', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/expression-language', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'symfony/polyfill-php70' => array( + 'pretty_version' => 'v1.20.0', + 'version' => '1.20.0.0', + 'reference' => '5f03a781d984aae42cebd18e7912fa80f02ee644', + 'type' => 'metapackage', + 'install_path' => null, + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'symfony/polyfill-php73' => array( + 'pretty_version' => 'v1.29.0', + 'version' => '1.29.0.0', + 'reference' => '21bd091060673a1177ae842c0ef8fe30893114d2', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/polyfill-php73', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'symfony/polyfill-php80' => array( + 'pretty_version' => 'v1.29.0', + 'version' => '1.29.0.0', + 'reference' => '87b68208d5c1188808dd7839ee1e6c8ec3b02f1b', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/polyfill-php80', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'symfony/service-contracts' => array( + 'pretty_version' => 'v2.5.2', + 'version' => '2.5.2.0', + 'reference' => '4b426aac47d6427cc1a1d0f7e2ac724627f5966c', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/service-contracts', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'symfony/var-exporter' => array( + 'pretty_version' => 'v5.4.35', + 'version' => '5.4.35.0', + 'reference' => 'abb0a151b62d6b07e816487e20040464af96cae7', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/var-exporter', + 'aliases' => array(), + 'dev_requirement' => false, + ), + ), +); diff --git a/advancedcontentfilter/vendor/composer/platform_check.php b/advancedcontentfilter/vendor/composer/platform_check.php new file mode 100644 index 00000000..580fa960 --- /dev/null +++ b/advancedcontentfilter/vendor/composer/platform_check.php @@ -0,0 +1,26 @@ += 70400)) { + $issues[] = 'Your Composer dependencies require a PHP version ">= 7.4.0". You are running ' . PHP_VERSION . '.'; +} + +if ($issues) { + if (!headers_sent()) { + header('HTTP/1.1 500 Internal Server Error'); + } + if (!ini_get('display_errors')) { + if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') { + fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL); + } elseif (!headers_sent()) { + echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL; + } + } + trigger_error( + 'Composer detected issues in your platform: ' . implode(' ', $issues), + E_USER_ERROR + ); +} diff --git a/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 @@ 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/psr/simple-cache/README.md b/advancedcontentfilter/vendor/psr/simple-cache/README.md deleted file mode 100644 index 43641d17..00000000 --- a/advancedcontentfilter/vendor/psr/simple-cache/README.md +++ /dev/null @@ -1,8 +0,0 @@ -PHP FIG Simple Cache PSR -======================== - -This repository holds all interfaces related to PSR-16. - -Note that this is not a cache implementation of its own. It is merely an interface that describes a cache implementation. See [the specification](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-16-simple-cache.md) for more details. - -You can find implementations of the specification by looking for packages providing the [psr/simple-cache-implementation](https://packagist.org/providers/psr/simple-cache-implementation) virtual package. diff --git a/advancedcontentfilter/vendor/psr/simple-cache/composer.json b/advancedcontentfilter/vendor/psr/simple-cache/composer.json deleted file mode 100644 index 2978fa55..00000000 --- a/advancedcontentfilter/vendor/psr/simple-cache/composer.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "psr/simple-cache", - "description": "Common interfaces for simple caching", - "keywords": ["psr", "psr-16", "cache", "simple-cache", "caching"], - "license": "MIT", - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "require": { - "php": ">=5.3.0" - }, - "autoload": { - "psr-4": { - "Psr\\SimpleCache\\": "src/" - } - }, - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - } -} diff --git a/advancedcontentfilter/vendor/psr/simple-cache/src/CacheException.php b/advancedcontentfilter/vendor/psr/simple-cache/src/CacheException.php deleted file mode 100644 index eba53815..00000000 --- a/advancedcontentfilter/vendor/psr/simple-cache/src/CacheException.php +++ /dev/null @@ -1,10 +0,0 @@ - value pairs. Cache keys that do not exist or are stale will have $default as value. - * - * @throws \Psr\SimpleCache\InvalidArgumentException - * MUST be thrown if $keys is neither an array nor a Traversable, - * or if any of the $keys are not a legal value. - */ - public function getMultiple($keys, $default = null); - - /** - * Persists a set of key => value pairs in the cache, with an optional TTL. - * - * @param iterable $values A list of key => value pairs for a multiple-set operation. - * @param null|int|\DateInterval $ttl Optional. The TTL value of this item. If no value is sent and - * the driver supports TTL then the library may set a default value - * for it or let the driver take care of that. - * - * @return bool True on success and false on failure. - * - * @throws \Psr\SimpleCache\InvalidArgumentException - * MUST be thrown if $values is neither an array nor a Traversable, - * or if any of the $values are not a legal value. - */ - public function setMultiple($values, $ttl = null); - - /** - * Deletes multiple cache items in a single operation. - * - * @param iterable $keys A list of string-based keys to be deleted. - * - * @return bool True if the items were successfully removed. False if there was an error. - * - * @throws \Psr\SimpleCache\InvalidArgumentException - * MUST be thrown if $keys is neither an array nor a Traversable, - * or if any of the $keys are not a legal value. - */ - public function deleteMultiple($keys); - - /** - * Determines whether an item is present in the cache. - * - * NOTE: It is recommended that has() is only to be used for cache warming type purposes - * and not to be used within your live applications operations for get/set, as this method - * is subject to a race condition where your has() will return true and immediately after, - * another script can remove it making the state of your app out of date. - * - * @param string $key The cache item key. - * - * @return bool - * - * @throws \Psr\SimpleCache\InvalidArgumentException - * MUST be thrown if the $key string is not a legal value. - */ - public function has($key); -} diff --git a/advancedcontentfilter/vendor/psr/simple-cache/src/InvalidArgumentException.php b/advancedcontentfilter/vendor/psr/simple-cache/src/InvalidArgumentException.php deleted file mode 100644 index 6a9524a2..00000000 --- a/advancedcontentfilter/vendor/psr/simple-cache/src/InvalidArgumentException.php +++ /dev/null @@ -1,13 +0,0 @@ - + * + * 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/polyfill-apcu/LICENSE b/advancedcontentfilter/vendor/symfony/cache-contracts/LICENSE similarity index 95% rename from advancedcontentfilter/vendor/symfony/polyfill-apcu/LICENSE rename to advancedcontentfilter/vendor/symfony/cache-contracts/LICENSE index 6e3afce6..74cdc2db 100644 --- a/advancedcontentfilter/vendor/symfony/polyfill-apcu/LICENSE +++ b/advancedcontentfilter/vendor/symfony/cache-contracts/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2015-present Fabien Potencier +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 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/Tests/Adapter/AbstractRedisAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/AbstractRedisAdapterTest.php deleted file mode 100644 index 0e8ed001..00000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/AbstractRedisAdapterTest.php +++ /dev/null @@ -1,47 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Adapter; - -use Symfony\Component\Cache\Adapter\RedisAdapter; - -abstract class AbstractRedisAdapterTest extends AdapterTestCase -{ - protected $skippedTests = [ - 'testExpiration' => 'Testing expiration slows down the test suite', - 'testHasItemReturnsFalseWhenDeferredItemIsExpired' => 'Testing expiration slows down the test suite', - 'testDefaultLifeTime' => 'Testing expiration slows down the test suite', - ]; - - protected static $redis; - - public function createCachePool($defaultLifetime = 0) - { - return new RedisAdapter(self::$redis, str_replace('\\', '.', __CLASS__), $defaultLifetime); - } - - public static function setUpBeforeClass() - { - if (!\extension_loaded('redis')) { - self::markTestSkipped('Extension redis required.'); - } - try { - (new \Redis())->connect(getenv('REDIS_HOST')); - } catch (\Exception $e) { - self::markTestSkipped($e->getMessage()); - } - } - - public static function tearDownAfterClass() - { - self::$redis = null; - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/AdapterTestCase.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/AdapterTestCase.php deleted file mode 100644 index 5758a286..00000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/AdapterTestCase.php +++ /dev/null @@ -1,175 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Adapter; - -use Cache\IntegrationTests\CachePoolTest; -use Psr\Cache\CacheItemPoolInterface; -use Symfony\Component\Cache\PruneableInterface; - -abstract class AdapterTestCase extends CachePoolTest -{ - protected function setUp() - { - parent::setUp(); - - if (!\array_key_exists('testDeferredSaveWithoutCommit', $this->skippedTests) && \defined('HHVM_VERSION')) { - $this->skippedTests['testDeferredSaveWithoutCommit'] = 'Destructors are called late on HHVM.'; - } - - if (!\array_key_exists('testPrune', $this->skippedTests) && !$this->createCachePool() instanceof PruneableInterface) { - $this->skippedTests['testPrune'] = 'Not a pruneable cache pool.'; - } - } - - public function testDefaultLifeTime() - { - if (isset($this->skippedTests[__FUNCTION__])) { - $this->markTestSkipped($this->skippedTests[__FUNCTION__]); - } - - $cache = $this->createCachePool(2); - - $item = $cache->getItem('key.dlt'); - $item->set('value'); - $cache->save($item); - sleep(1); - - $item = $cache->getItem('key.dlt'); - $this->assertTrue($item->isHit()); - - sleep(2); - $item = $cache->getItem('key.dlt'); - $this->assertFalse($item->isHit()); - } - - public function testExpiration() - { - if (isset($this->skippedTests[__FUNCTION__])) { - $this->markTestSkipped($this->skippedTests[__FUNCTION__]); - } - - $cache = $this->createCachePool(); - $cache->save($cache->getItem('k1')->set('v1')->expiresAfter(2)); - $cache->save($cache->getItem('k2')->set('v2')->expiresAfter(366 * 86400)); - - sleep(3); - $item = $cache->getItem('k1'); - $this->assertFalse($item->isHit()); - $this->assertNull($item->get(), "Item's value must be null when isHit() is false."); - - $item = $cache->getItem('k2'); - $this->assertTrue($item->isHit()); - $this->assertSame('v2', $item->get()); - } - - public function testNotUnserializable() - { - if (isset($this->skippedTests[__FUNCTION__])) { - $this->markTestSkipped($this->skippedTests[__FUNCTION__]); - } - - $cache = $this->createCachePool(); - - $item = $cache->getItem('foo'); - $cache->save($item->set(new NotUnserializable())); - - $item = $cache->getItem('foo'); - $this->assertFalse($item->isHit()); - - foreach ($cache->getItems(['foo']) as $item) { - } - $cache->save($item->set(new NotUnserializable())); - - foreach ($cache->getItems(['foo']) as $item) { - } - $this->assertFalse($item->isHit()); - } - - public function testPrune() - { - if (isset($this->skippedTests[__FUNCTION__])) { - $this->markTestSkipped($this->skippedTests[__FUNCTION__]); - } - - if (!method_exists($this, 'isPruned')) { - $this->fail('Test classes for pruneable caches must implement `isPruned($cache, $name)` method.'); - } - - /** @var PruneableInterface|CacheItemPoolInterface $cache */ - $cache = $this->createCachePool(); - - $doSet = function ($name, $value, \DateInterval $expiresAfter = null) use ($cache) { - $item = $cache->getItem($name); - $item->set($value); - - if ($expiresAfter) { - $item->expiresAfter($expiresAfter); - } - - $cache->save($item); - }; - - $doSet('foo', 'foo-val', new \DateInterval('PT05S')); - $doSet('bar', 'bar-val', new \DateInterval('PT10S')); - $doSet('baz', 'baz-val', new \DateInterval('PT15S')); - $doSet('qux', 'qux-val', new \DateInterval('PT20S')); - - sleep(30); - $cache->prune(); - $this->assertTrue($this->isPruned($cache, 'foo')); - $this->assertTrue($this->isPruned($cache, 'bar')); - $this->assertTrue($this->isPruned($cache, 'baz')); - $this->assertTrue($this->isPruned($cache, 'qux')); - - $doSet('foo', 'foo-val'); - $doSet('bar', 'bar-val', new \DateInterval('PT20S')); - $doSet('baz', 'baz-val', new \DateInterval('PT40S')); - $doSet('qux', 'qux-val', new \DateInterval('PT80S')); - - $cache->prune(); - $this->assertFalse($this->isPruned($cache, 'foo')); - $this->assertFalse($this->isPruned($cache, 'bar')); - $this->assertFalse($this->isPruned($cache, 'baz')); - $this->assertFalse($this->isPruned($cache, 'qux')); - - sleep(30); - $cache->prune(); - $this->assertFalse($this->isPruned($cache, 'foo')); - $this->assertTrue($this->isPruned($cache, 'bar')); - $this->assertFalse($this->isPruned($cache, 'baz')); - $this->assertFalse($this->isPruned($cache, 'qux')); - - sleep(30); - $cache->prune(); - $this->assertFalse($this->isPruned($cache, 'foo')); - $this->assertTrue($this->isPruned($cache, 'baz')); - $this->assertFalse($this->isPruned($cache, 'qux')); - - sleep(30); - $cache->prune(); - $this->assertFalse($this->isPruned($cache, 'foo')); - $this->assertTrue($this->isPruned($cache, 'qux')); - } -} - -class NotUnserializable implements \Serializable -{ - public function serialize() - { - return serialize(123); - } - - public function unserialize($ser) - { - throw new \Exception(__CLASS__); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/ApcuAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/ApcuAdapterTest.php deleted file mode 100644 index f55a1b9b..00000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/ApcuAdapterTest.php +++ /dev/null @@ -1,124 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Adapter; - -use Psr\Log\NullLogger; -use Symfony\Component\Cache\Adapter\ApcuAdapter; - -class ApcuAdapterTest extends AdapterTestCase -{ - protected $skippedTests = [ - 'testExpiration' => 'Testing expiration slows down the test suite', - 'testHasItemReturnsFalseWhenDeferredItemIsExpired' => 'Testing expiration slows down the test suite', - 'testDefaultLifeTime' => 'Testing expiration slows down the test suite', - ]; - - public function createCachePool($defaultLifetime = 0) - { - if (!\function_exists('apcu_fetch') || !filter_var(ini_get('apc.enabled'), \FILTER_VALIDATE_BOOLEAN)) { - $this->markTestSkipped('APCu extension is required.'); - } - if ('cli' === \PHP_SAPI && !filter_var(ini_get('apc.enable_cli'), \FILTER_VALIDATE_BOOLEAN)) { - if ('testWithCliSapi' !== $this->getName()) { - $this->markTestSkipped('apc.enable_cli=1 is required.'); - } - } - if ('\\' === \DIRECTORY_SEPARATOR) { - $this->markTestSkipped('Fails transiently on Windows.'); - } - - return new ApcuAdapter(str_replace('\\', '.', __CLASS__), $defaultLifetime); - } - - public function testUnserializable() - { - $pool = $this->createCachePool(); - - $item = $pool->getItem('foo'); - $item->set(function () {}); - - $this->assertFalse($pool->save($item)); - - $item = $pool->getItem('foo'); - $this->assertFalse($item->isHit()); - } - - public function testVersion() - { - $namespace = str_replace('\\', '.', static::class); - - $pool1 = new ApcuAdapter($namespace, 0, 'p1'); - - $item = $pool1->getItem('foo'); - $this->assertFalse($item->isHit()); - $this->assertTrue($pool1->save($item->set('bar'))); - - $item = $pool1->getItem('foo'); - $this->assertTrue($item->isHit()); - $this->assertSame('bar', $item->get()); - - $pool2 = new ApcuAdapter($namespace, 0, 'p2'); - - $item = $pool2->getItem('foo'); - $this->assertFalse($item->isHit()); - $this->assertNull($item->get()); - - $item = $pool1->getItem('foo'); - $this->assertFalse($item->isHit()); - $this->assertNull($item->get()); - } - - public function testNamespace() - { - $namespace = str_replace('\\', '.', static::class); - - $pool1 = new ApcuAdapter($namespace.'_1', 0, 'p1'); - - $item = $pool1->getItem('foo'); - $this->assertFalse($item->isHit()); - $this->assertTrue($pool1->save($item->set('bar'))); - - $item = $pool1->getItem('foo'); - $this->assertTrue($item->isHit()); - $this->assertSame('bar', $item->get()); - - $pool2 = new ApcuAdapter($namespace.'_2', 0, 'p1'); - - $item = $pool2->getItem('foo'); - $this->assertFalse($item->isHit()); - $this->assertNull($item->get()); - - $item = $pool1->getItem('foo'); - $this->assertTrue($item->isHit()); - $this->assertSame('bar', $item->get()); - } - - public function testWithCliSapi() - { - try { - // disable PHPUnit error handler to mimic a production environment - $isCalled = false; - set_error_handler(function () use (&$isCalled) { - $isCalled = true; - }); - $pool = new ApcuAdapter(str_replace('\\', '.', __CLASS__)); - $pool->setLogger(new NullLogger()); - - $item = $pool->getItem('foo'); - $item->isHit(); - $pool->save($item->set('bar')); - $this->assertFalse($isCalled); - } finally { - restore_error_handler(); - } - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/ArrayAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/ArrayAdapterTest.php deleted file mode 100644 index e6adc9d0..00000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/ArrayAdapterTest.php +++ /dev/null @@ -1,56 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Adapter; - -use Symfony\Component\Cache\Adapter\ArrayAdapter; - -/** - * @group time-sensitive - */ -class ArrayAdapterTest extends AdapterTestCase -{ - protected $skippedTests = [ - 'testDeferredSaveWithoutCommit' => 'Assumes a shared cache which ArrayAdapter is not.', - 'testSaveWithoutExpire' => 'Assumes a shared cache which ArrayAdapter is not.', - ]; - - public function createCachePool($defaultLifetime = 0) - { - return new ArrayAdapter($defaultLifetime); - } - - public function testGetValuesHitAndMiss() - { - /** @var ArrayAdapter $cache */ - $cache = $this->createCachePool(); - - // Hit - $item = $cache->getItem('foo'); - $item->set('4711'); - $cache->save($item); - - $fooItem = $cache->getItem('foo'); - $this->assertTrue($fooItem->isHit()); - $this->assertEquals('4711', $fooItem->get()); - - // Miss (should be present as NULL in $values) - $cache->getItem('bar'); - - $values = $cache->getValues(); - - $this->assertCount(2, $values); - $this->assertArrayHasKey('foo', $values); - $this->assertSame(serialize('4711'), $values['foo']); - $this->assertArrayHasKey('bar', $values); - $this->assertNull($values['bar']); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/ChainAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/ChainAdapterTest.php deleted file mode 100644 index be811d6f..00000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/ChainAdapterTest.php +++ /dev/null @@ -1,233 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Adapter; - -use PHPUnit\Framework\MockObject\MockObject; -use Symfony\Component\Cache\Adapter\AdapterInterface; -use Symfony\Component\Cache\Adapter\ArrayAdapter; -use Symfony\Component\Cache\Adapter\ChainAdapter; -use Symfony\Component\Cache\Adapter\FilesystemAdapter; -use Symfony\Component\Cache\PruneableInterface; -use Symfony\Component\Cache\Tests\Fixtures\ExternalAdapter; - -/** - * @author Kévin Dunglas - * @group time-sensitive - */ -class ChainAdapterTest extends AdapterTestCase -{ - public function createCachePool($defaultLifetime = 0) - { - return new ChainAdapter([new ArrayAdapter($defaultLifetime), new ExternalAdapter($defaultLifetime), new FilesystemAdapter('', $defaultLifetime)], $defaultLifetime); - } - - public function testEmptyAdaptersException() - { - $this->expectException('Symfony\Component\Cache\Exception\InvalidArgumentException'); - $this->expectExceptionMessage('At least one adapter must be specified.'); - new ChainAdapter([]); - } - - public function testInvalidAdapterException() - { - $this->expectException('Symfony\Component\Cache\Exception\InvalidArgumentException'); - $this->expectExceptionMessage('The class "stdClass" does not implement'); - new ChainAdapter([new \stdClass()]); - } - - public function testPrune() - { - if (isset($this->skippedTests[__FUNCTION__])) { - $this->markTestSkipped($this->skippedTests[__FUNCTION__]); - } - - $cache = new ChainAdapter([ - $this->getPruneableMock(), - $this->getNonPruneableMock(), - $this->getPruneableMock(), - ]); - $this->assertTrue($cache->prune()); - - $cache = new ChainAdapter([ - $this->getPruneableMock(), - $this->getFailingPruneableMock(), - $this->getPruneableMock(), - ]); - $this->assertFalse($cache->prune()); - } - - public function testMultipleCachesExpirationWhenCommonTtlIsNotSet() - { - if (isset($this->skippedTests[__FUNCTION__])) { - $this->markTestSkipped($this->skippedTests[__FUNCTION__]); - } - - $adapter1 = new ArrayAdapter(4); - $adapter2 = new ArrayAdapter(2); - - $cache = new ChainAdapter([$adapter1, $adapter2]); - - $cache->save($cache->getItem('key')->set('value')); - - $item = $adapter1->getItem('key'); - $this->assertTrue($item->isHit()); - $this->assertEquals('value', $item->get()); - - $item = $adapter2->getItem('key'); - $this->assertTrue($item->isHit()); - $this->assertEquals('value', $item->get()); - - sleep(2); - - $item = $adapter1->getItem('key'); - $this->assertTrue($item->isHit()); - $this->assertEquals('value', $item->get()); - - $item = $adapter2->getItem('key'); - $this->assertFalse($item->isHit()); - - sleep(2); - - $item = $adapter1->getItem('key'); - $this->assertFalse($item->isHit()); - - $adapter2->save($adapter2->getItem('key1')->set('value1')); - - $item = $cache->getItem('key1'); - $this->assertTrue($item->isHit()); - $this->assertEquals('value1', $item->get()); - - sleep(2); - - $item = $adapter1->getItem('key1'); - $this->assertTrue($item->isHit()); - $this->assertEquals('value1', $item->get()); - - $item = $adapter2->getItem('key1'); - $this->assertFalse($item->isHit()); - - sleep(2); - - $item = $adapter1->getItem('key1'); - $this->assertFalse($item->isHit()); - } - - public function testMultipleCachesExpirationWhenCommonTtlIsSet() - { - if (isset($this->skippedTests[__FUNCTION__])) { - $this->markTestSkipped($this->skippedTests[__FUNCTION__]); - } - - $adapter1 = new ArrayAdapter(4); - $adapter2 = new ArrayAdapter(2); - - $cache = new ChainAdapter([$adapter1, $adapter2], 6); - - $cache->save($cache->getItem('key')->set('value')); - - $item = $adapter1->getItem('key'); - $this->assertTrue($item->isHit()); - $this->assertEquals('value', $item->get()); - - $item = $adapter2->getItem('key'); - $this->assertTrue($item->isHit()); - $this->assertEquals('value', $item->get()); - - sleep(2); - - $item = $adapter1->getItem('key'); - $this->assertTrue($item->isHit()); - $this->assertEquals('value', $item->get()); - - $item = $adapter2->getItem('key'); - $this->assertFalse($item->isHit()); - - sleep(2); - - $item = $adapter1->getItem('key'); - $this->assertFalse($item->isHit()); - - $adapter2->save($adapter2->getItem('key1')->set('value1')); - - $item = $cache->getItem('key1'); - $this->assertTrue($item->isHit()); - $this->assertEquals('value1', $item->get()); - - sleep(2); - - $item = $adapter1->getItem('key1'); - $this->assertTrue($item->isHit()); - $this->assertEquals('value1', $item->get()); - - $item = $adapter2->getItem('key1'); - $this->assertFalse($item->isHit()); - - sleep(2); - - $item = $adapter1->getItem('key1'); - $this->assertTrue($item->isHit()); - $this->assertEquals('value1', $item->get()); - - sleep(2); - - $item = $adapter1->getItem('key1'); - $this->assertFalse($item->isHit()); - } - - /** - * @return MockObject|PruneableCacheInterface - */ - private function getPruneableMock() - { - $pruneable = $this - ->getMockBuilder(PruneableCacheInterface::class) - ->getMock(); - - $pruneable - ->expects($this->atLeastOnce()) - ->method('prune') - ->willReturn(true); - - return $pruneable; - } - - /** - * @return MockObject|PruneableCacheInterface - */ - private function getFailingPruneableMock() - { - $pruneable = $this - ->getMockBuilder(PruneableCacheInterface::class) - ->getMock(); - - $pruneable - ->expects($this->atLeastOnce()) - ->method('prune') - ->willReturn(false); - - return $pruneable; - } - - /** - * @return MockObject|AdapterInterface - */ - private function getNonPruneableMock() - { - return $this - ->getMockBuilder(AdapterInterface::class) - ->getMock(); - } -} - -interface PruneableCacheInterface extends PruneableInterface, AdapterInterface -{ -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/DoctrineAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/DoctrineAdapterTest.php deleted file mode 100644 index 8f520cb5..00000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/DoctrineAdapterTest.php +++ /dev/null @@ -1,32 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Adapter; - -use Symfony\Component\Cache\Adapter\DoctrineAdapter; -use Symfony\Component\Cache\Tests\Fixtures\ArrayCache; - -/** - * @group time-sensitive - */ -class DoctrineAdapterTest extends AdapterTestCase -{ - protected $skippedTests = [ - 'testDeferredSaveWithoutCommit' => 'Assumes a shared cache which ArrayCache is not.', - 'testSaveWithoutExpire' => 'Assumes a shared cache which ArrayCache is not.', - 'testNotUnserializable' => 'ArrayCache does not use serialize/unserialize', - ]; - - public function createCachePool($defaultLifetime = 0) - { - return new DoctrineAdapter(new ArrayCache($defaultLifetime), '', $defaultLifetime); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/FilesystemAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/FilesystemAdapterTest.php deleted file mode 100644 index fa830682..00000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/FilesystemAdapterTest.php +++ /dev/null @@ -1,61 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Adapter; - -use Psr\Cache\CacheItemPoolInterface; -use Symfony\Component\Cache\Adapter\FilesystemAdapter; - -/** - * @group time-sensitive - */ -class FilesystemAdapterTest extends AdapterTestCase -{ - public function createCachePool($defaultLifetime = 0) - { - return new FilesystemAdapter('', $defaultLifetime); - } - - public static function tearDownAfterClass() - { - self::rmdir(sys_get_temp_dir().'/symfony-cache'); - } - - public static function rmdir($dir) - { - if (!file_exists($dir)) { - return; - } - if (!$dir || 0 !== strpos(\dirname($dir), sys_get_temp_dir())) { - throw new \Exception(__METHOD__."() operates only on subdirs of system's temp dir"); - } - $children = new \RecursiveIteratorIterator( - new \RecursiveDirectoryIterator($dir, \RecursiveDirectoryIterator::SKIP_DOTS), - \RecursiveIteratorIterator::CHILD_FIRST - ); - foreach ($children as $child) { - if ($child->isDir()) { - rmdir($child); - } else { - unlink($child); - } - } - rmdir($dir); - } - - protected function isPruned(CacheItemPoolInterface $cache, $name) - { - $getFileMethod = (new \ReflectionObject($cache))->getMethod('getFile'); - $getFileMethod->setAccessible(true); - - return !file_exists($getFileMethod->invoke($cache, $name)); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/MaxIdLengthAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/MaxIdLengthAdapterTest.php deleted file mode 100644 index 536e2c2d..00000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/MaxIdLengthAdapterTest.php +++ /dev/null @@ -1,87 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Adapter; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Cache\Adapter\AbstractAdapter; - -class MaxIdLengthAdapterTest extends TestCase -{ - public function testLongKey() - { - $cache = $this->getMockBuilder(MaxIdLengthAdapter::class) - ->setConstructorArgs([str_repeat('-', 10)]) - ->setMethods(['doHave', 'doFetch', 'doDelete', 'doSave', 'doClear']) - ->getMock(); - - $cache->expects($this->exactly(2)) - ->method('doHave') - ->withConsecutive( - [$this->equalTo('----------:0GTYWa9n4ed8vqNlOT2iEr:')], - [$this->equalTo('----------:---------------------------------------')] - ); - - $cache->hasItem(str_repeat('-', 40)); - $cache->hasItem(str_repeat('-', 39)); - } - - public function testLongKeyVersioning() - { - $cache = $this->getMockBuilder(MaxIdLengthAdapter::class) - ->setConstructorArgs([str_repeat('-', 26)]) - ->getMock(); - - $cache - ->method('doFetch') - ->willReturn(['2:']); - - $reflectionClass = new \ReflectionClass(AbstractAdapter::class); - - $reflectionMethod = $reflectionClass->getMethod('getId'); - $reflectionMethod->setAccessible(true); - - // No versioning enabled - $this->assertEquals('--------------------------:------------', $reflectionMethod->invokeArgs($cache, [str_repeat('-', 12)])); - $this->assertLessThanOrEqual(50, \strlen($reflectionMethod->invokeArgs($cache, [str_repeat('-', 12)]))); - $this->assertLessThanOrEqual(50, \strlen($reflectionMethod->invokeArgs($cache, [str_repeat('-', 23)]))); - $this->assertLessThanOrEqual(50, \strlen($reflectionMethod->invokeArgs($cache, [str_repeat('-', 40)]))); - - $reflectionProperty = $reflectionClass->getProperty('versioningIsEnabled'); - $reflectionProperty->setAccessible(true); - $reflectionProperty->setValue($cache, true); - - // Versioning enabled - $this->assertEquals('--------------------------:2:------------', $reflectionMethod->invokeArgs($cache, [str_repeat('-', 12)])); - $this->assertLessThanOrEqual(50, \strlen($reflectionMethod->invokeArgs($cache, [str_repeat('-', 12)]))); - $this->assertLessThanOrEqual(50, \strlen($reflectionMethod->invokeArgs($cache, [str_repeat('-', 23)]))); - $this->assertLessThanOrEqual(50, \strlen($reflectionMethod->invokeArgs($cache, [str_repeat('-', 40)]))); - } - - public function testTooLongNamespace() - { - $this->expectException('Symfony\Component\Cache\Exception\InvalidArgumentException'); - $this->expectExceptionMessage('Namespace must be 26 chars max, 40 given ("----------------------------------------")'); - $this->getMockBuilder(MaxIdLengthAdapter::class) - ->setConstructorArgs([str_repeat('-', 40)]) - ->getMock(); - } -} - -abstract class MaxIdLengthAdapter extends AbstractAdapter -{ - protected $maxIdLength = 50; - - public function __construct($ns) - { - parent::__construct($ns); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/MemcachedAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/MemcachedAdapterTest.php deleted file mode 100644 index a9a397dd..00000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/MemcachedAdapterTest.php +++ /dev/null @@ -1,204 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Adapter; - -use Symfony\Component\Cache\Adapter\AbstractAdapter; -use Symfony\Component\Cache\Adapter\MemcachedAdapter; - -class MemcachedAdapterTest extends AdapterTestCase -{ - protected $skippedTests = [ - 'testHasItemReturnsFalseWhenDeferredItemIsExpired' => 'Testing expiration slows down the test suite', - 'testDefaultLifeTime' => 'Testing expiration slows down the test suite', - ]; - - protected static $client; - - public static function setUpBeforeClass() - { - if (!MemcachedAdapter::isSupported()) { - self::markTestSkipped('Extension memcached >=2.2.0 required.'); - } - self::$client = AbstractAdapter::createConnection('memcached://'.getenv('MEMCACHED_HOST'), ['binary_protocol' => false]); - self::$client->get('foo'); - $code = self::$client->getResultCode(); - - if (\Memcached::RES_SUCCESS !== $code && \Memcached::RES_NOTFOUND !== $code) { - self::markTestSkipped('Memcached error: '.strtolower(self::$client->getResultMessage())); - } - } - - public function createCachePool($defaultLifetime = 0) - { - $client = $defaultLifetime ? AbstractAdapter::createConnection('memcached://'.getenv('MEMCACHED_HOST')) : self::$client; - - return new MemcachedAdapter($client, str_replace('\\', '.', __CLASS__), $defaultLifetime); - } - - public function testOptions() - { - $client = MemcachedAdapter::createConnection([], [ - 'libketama_compatible' => false, - 'distribution' => 'modula', - 'compression' => true, - 'serializer' => 'php', - 'hash' => 'md5', - ]); - - $this->assertSame(\Memcached::SERIALIZER_PHP, $client->getOption(\Memcached::OPT_SERIALIZER)); - $this->assertSame(\Memcached::HASH_MD5, $client->getOption(\Memcached::OPT_HASH)); - $this->assertTrue($client->getOption(\Memcached::OPT_COMPRESSION)); - $this->assertSame(0, $client->getOption(\Memcached::OPT_LIBKETAMA_COMPATIBLE)); - $this->assertSame(\Memcached::DISTRIBUTION_MODULA, $client->getOption(\Memcached::OPT_DISTRIBUTION)); - } - - /** - * @dataProvider provideBadOptions - */ - public function testBadOptions($name, $value) - { - if (\PHP_VERSION_ID < 80000) { - $this->expectException('ErrorException'); - $this->expectExceptionMessage('constant(): Couldn\'t find constant Memcached::'); - } else { - $this->expectException('Error'); - $this->expectExceptionMessage('Undefined constant Memcached::'); - } - - MemcachedAdapter::createConnection([], [$name => $value]); - } - - public function provideBadOptions() - { - return [ - ['foo', 'bar'], - ['hash', 'zyx'], - ['serializer', 'zyx'], - ['distribution', 'zyx'], - ]; - } - - public function testDefaultOptions() - { - $this->assertTrue(MemcachedAdapter::isSupported()); - - $client = MemcachedAdapter::createConnection([]); - - $this->assertTrue($client->getOption(\Memcached::OPT_COMPRESSION)); - $this->assertSame(1, $client->getOption(\Memcached::OPT_BINARY_PROTOCOL)); - $this->assertSame(1, $client->getOption(\Memcached::OPT_TCP_NODELAY)); - $this->assertSame(1, $client->getOption(\Memcached::OPT_LIBKETAMA_COMPATIBLE)); - } - - public function testOptionSerializer() - { - $this->expectException('Symfony\Component\Cache\Exception\CacheException'); - $this->expectExceptionMessage('MemcachedAdapter: "serializer" option must be "php" or "igbinary".'); - if (!\Memcached::HAVE_JSON) { - $this->markTestSkipped('Memcached::HAVE_JSON required'); - } - - new MemcachedAdapter(MemcachedAdapter::createConnection([], ['serializer' => 'json'])); - } - - /** - * @dataProvider provideServersSetting - */ - public function testServersSetting($dsn, $host, $port) - { - $client1 = MemcachedAdapter::createConnection($dsn); - $client2 = MemcachedAdapter::createConnection([$dsn]); - $client3 = MemcachedAdapter::createConnection([[$host, $port]]); - $expect = [ - 'host' => $host, - 'port' => $port, - ]; - - $f = function ($s) { return ['host' => $s['host'], 'port' => $s['port']]; }; - $this->assertSame([$expect], array_map($f, $client1->getServerList())); - $this->assertSame([$expect], array_map($f, $client2->getServerList())); - $this->assertSame([$expect], array_map($f, $client3->getServerList())); - } - - public function provideServersSetting() - { - yield [ - 'memcached://127.0.0.1/50', - '127.0.0.1', - 11211, - ]; - yield [ - 'memcached://localhost:11222?weight=25', - 'localhost', - 11222, - ]; - if (filter_var(ini_get('memcached.use_sasl'), \FILTER_VALIDATE_BOOLEAN)) { - yield [ - 'memcached://user:password@127.0.0.1?weight=50', - '127.0.0.1', - 11211, - ]; - } - yield [ - 'memcached:///var/run/memcached.sock?weight=25', - '/var/run/memcached.sock', - 0, - ]; - yield [ - 'memcached:///var/local/run/memcached.socket?weight=25', - '/var/local/run/memcached.socket', - 0, - ]; - if (filter_var(ini_get('memcached.use_sasl'), \FILTER_VALIDATE_BOOLEAN)) { - yield [ - 'memcached://user:password@/var/local/run/memcached.socket?weight=25', - '/var/local/run/memcached.socket', - 0, - ]; - } - } - - /** - * @dataProvider provideDsnWithOptions - */ - public function testDsnWithOptions($dsn, array $options, array $expectedOptions) - { - $client = MemcachedAdapter::createConnection($dsn, $options); - - foreach ($expectedOptions as $option => $expect) { - $this->assertSame($expect, $client->getOption($option)); - } - } - - public function provideDsnWithOptions() - { - if (!class_exists('\Memcached')) { - self::markTestSkipped('Extension memcached required.'); - } - - yield [ - 'memcached://localhost:11222?retry_timeout=10', - [\Memcached::OPT_RETRY_TIMEOUT => 8], - [\Memcached::OPT_RETRY_TIMEOUT => 10], - ]; - yield [ - 'memcached://localhost:11222?socket_recv_size=1&socket_send_size=2', - [\Memcached::OPT_RETRY_TIMEOUT => 8], - [\Memcached::OPT_SOCKET_RECV_SIZE => 1, \Memcached::OPT_SOCKET_SEND_SIZE => 2, \Memcached::OPT_RETRY_TIMEOUT => 8], - ]; - } - - public function testClear() - { - $this->assertTrue($this->createCachePool()->clear()); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/NamespacedProxyAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/NamespacedProxyAdapterTest.php deleted file mode 100644 index c2714033..00000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/NamespacedProxyAdapterTest.php +++ /dev/null @@ -1,26 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Adapter; - -use Symfony\Component\Cache\Adapter\ArrayAdapter; -use Symfony\Component\Cache\Adapter\ProxyAdapter; - -/** - * @group time-sensitive - */ -class NamespacedProxyAdapterTest extends ProxyAdapterTest -{ - public function createCachePool($defaultLifetime = 0) - { - return new ProxyAdapter(new ArrayAdapter($defaultLifetime), 'foo', $defaultLifetime); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/NullAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/NullAdapterTest.php deleted file mode 100644 index b771fa0e..00000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/NullAdapterTest.php +++ /dev/null @@ -1,128 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Adapter; - -use PHPUnit\Framework\TestCase; -use Psr\Cache\CacheItemInterface; -use Symfony\Component\Cache\Adapter\NullAdapter; - -/** - * @group time-sensitive - */ -class NullAdapterTest extends TestCase -{ - public function createCachePool() - { - return new NullAdapter(); - } - - public function testGetItem() - { - $adapter = $this->createCachePool(); - - $item = $adapter->getItem('key'); - $this->assertFalse($item->isHit()); - $this->assertNull($item->get(), "Item's value must be null when isHit is false."); - } - - public function testHasItem() - { - $this->assertFalse($this->createCachePool()->hasItem('key')); - } - - public function testGetItems() - { - $adapter = $this->createCachePool(); - - $keys = ['foo', 'bar', 'baz', 'biz']; - - /** @var CacheItemInterface[] $items */ - $items = $adapter->getItems($keys); - $count = 0; - - foreach ($items as $key => $item) { - $itemKey = $item->getKey(); - - $this->assertEquals($itemKey, $key, 'Keys must be preserved when fetching multiple items'); - $this->assertContains($key, $keys, 'Cache key can not change.'); - $this->assertFalse($item->isHit()); - - // Remove $key for $keys - foreach ($keys as $k => $v) { - if ($v === $key) { - unset($keys[$k]); - } - } - - ++$count; - } - - $this->assertSame(4, $count); - } - - public function testIsHit() - { - $adapter = $this->createCachePool(); - - $item = $adapter->getItem('key'); - $this->assertFalse($item->isHit()); - } - - public function testClear() - { - $this->assertTrue($this->createCachePool()->clear()); - } - - public function testDeleteItem() - { - $this->assertTrue($this->createCachePool()->deleteItem('key')); - } - - public function testDeleteItems() - { - $this->assertTrue($this->createCachePool()->deleteItems(['key', 'foo', 'bar'])); - } - - public function testSave() - { - $adapter = $this->createCachePool(); - - $item = $adapter->getItem('key'); - $this->assertFalse($item->isHit()); - $this->assertNull($item->get(), "Item's value must be null when isHit is false."); - - $this->assertFalse($adapter->save($item)); - } - - public function testDeferredSave() - { - $adapter = $this->createCachePool(); - - $item = $adapter->getItem('key'); - $this->assertFalse($item->isHit()); - $this->assertNull($item->get(), "Item's value must be null when isHit is false."); - - $this->assertFalse($adapter->saveDeferred($item)); - } - - public function testCommit() - { - $adapter = $this->createCachePool(); - - $item = $adapter->getItem('key'); - $this->assertFalse($item->isHit()); - $this->assertNull($item->get(), "Item's value must be null when isHit is false."); - - $this->assertFalse($adapter->saveDeferred($item)); - $this->assertFalse($this->createCachePool()->commit()); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PdoAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PdoAdapterTest.php deleted file mode 100644 index dd2a9118..00000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PdoAdapterTest.php +++ /dev/null @@ -1,73 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Adapter; - -use Symfony\Component\Cache\Adapter\PdoAdapter; -use Symfony\Component\Cache\Tests\Traits\PdoPruneableTrait; - -/** - * @group time-sensitive - */ -class PdoAdapterTest extends AdapterTestCase -{ - use PdoPruneableTrait; - - protected static $dbFile; - - public static function setUpBeforeClass() - { - if (!\extension_loaded('pdo_sqlite')) { - self::markTestSkipped('Extension pdo_sqlite required.'); - } - - self::$dbFile = tempnam(sys_get_temp_dir(), 'sf_sqlite_cache'); - - $pool = new PdoAdapter('sqlite:'.self::$dbFile); - $pool->createTable(); - } - - public static function tearDownAfterClass() - { - @unlink(self::$dbFile); - } - - public function createCachePool($defaultLifetime = 0) - { - return new PdoAdapter('sqlite:'.self::$dbFile, 'ns', $defaultLifetime); - } - - public function testCleanupExpiredItems() - { - $pdo = new \PDO('sqlite:'.self::$dbFile); - - $getCacheItemCount = function () use ($pdo) { - return (int) $pdo->query('SELECT COUNT(*) FROM cache_items')->fetch(\PDO::FETCH_COLUMN); - }; - - $this->assertSame(0, $getCacheItemCount()); - - $cache = $this->createCachePool(); - - $item = $cache->getItem('some_nice_key'); - $item->expiresAfter(1); - $item->set(1); - - $cache->save($item); - $this->assertSame(1, $getCacheItemCount()); - - sleep(2); - - $newItem = $cache->getItem($item->getKey()); - $this->assertFalse($newItem->isHit()); - $this->assertSame(0, $getCacheItemCount(), 'PDOAdapter must clean up expired items'); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PdoDbalAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PdoDbalAdapterTest.php deleted file mode 100644 index aa53958c..00000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PdoDbalAdapterTest.php +++ /dev/null @@ -1,48 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Adapter; - -use Doctrine\DBAL\DriverManager; -use Symfony\Component\Cache\Adapter\PdoAdapter; -use Symfony\Component\Cache\Tests\Traits\PdoPruneableTrait; - -/** - * @group time-sensitive - */ -class PdoDbalAdapterTest extends AdapterTestCase -{ - use PdoPruneableTrait; - - protected static $dbFile; - - public static function setUpBeforeClass() - { - if (!\extension_loaded('pdo_sqlite')) { - self::markTestSkipped('Extension pdo_sqlite required.'); - } - - self::$dbFile = tempnam(sys_get_temp_dir(), 'sf_sqlite_cache'); - - $pool = new PdoAdapter(DriverManager::getConnection(['driver' => 'pdo_sqlite', 'path' => self::$dbFile])); - $pool->createTable(); - } - - public static function tearDownAfterClass() - { - @unlink(self::$dbFile); - } - - public function createCachePool($defaultLifetime = 0) - { - return new PdoAdapter(DriverManager::getConnection(['driver' => 'pdo_sqlite', 'path' => self::$dbFile]), '', $defaultLifetime); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PhpArrayAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PhpArrayAdapterTest.php deleted file mode 100644 index f88a7187..00000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PhpArrayAdapterTest.php +++ /dev/null @@ -1,135 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Adapter; - -use Psr\Cache\CacheItemInterface; -use Symfony\Component\Cache\Adapter\NullAdapter; -use Symfony\Component\Cache\Adapter\PhpArrayAdapter; - -/** - * @group time-sensitive - */ -class PhpArrayAdapterTest extends AdapterTestCase -{ - protected $skippedTests = [ - 'testBasicUsage' => 'PhpArrayAdapter is read-only.', - 'testBasicUsageWithLongKey' => 'PhpArrayAdapter is read-only.', - 'testClear' => 'PhpArrayAdapter is read-only.', - 'testClearWithDeferredItems' => 'PhpArrayAdapter is read-only.', - 'testDeleteItem' => 'PhpArrayAdapter is read-only.', - 'testSaveExpired' => 'PhpArrayAdapter is read-only.', - 'testSaveWithoutExpire' => 'PhpArrayAdapter is read-only.', - 'testDeferredSave' => 'PhpArrayAdapter is read-only.', - 'testDeferredSaveWithoutCommit' => 'PhpArrayAdapter is read-only.', - 'testDeleteItems' => 'PhpArrayAdapter is read-only.', - 'testDeleteDeferredItem' => 'PhpArrayAdapter is read-only.', - 'testCommit' => 'PhpArrayAdapter is read-only.', - 'testSaveDeferredWhenChangingValues' => 'PhpArrayAdapter is read-only.', - 'testSaveDeferredOverwrite' => 'PhpArrayAdapter is read-only.', - 'testIsHitDeferred' => 'PhpArrayAdapter is read-only.', - - 'testExpiresAt' => 'PhpArrayAdapter does not support expiration.', - 'testExpiresAtWithNull' => 'PhpArrayAdapter does not support expiration.', - 'testExpiresAfterWithNull' => 'PhpArrayAdapter does not support expiration.', - 'testDeferredExpired' => 'PhpArrayAdapter does not support expiration.', - 'testExpiration' => 'PhpArrayAdapter does not support expiration.', - - 'testGetItemInvalidKeys' => 'PhpArrayAdapter does not throw exceptions on invalid key.', - 'testGetItemsInvalidKeys' => 'PhpArrayAdapter does not throw exceptions on invalid key.', - 'testHasItemInvalidKeys' => 'PhpArrayAdapter does not throw exceptions on invalid key.', - 'testDeleteItemInvalidKeys' => 'PhpArrayAdapter does not throw exceptions on invalid key.', - 'testDeleteItemsInvalidKeys' => 'PhpArrayAdapter does not throw exceptions on invalid key.', - - 'testDefaultLifeTime' => 'PhpArrayAdapter does not allow configuring a default lifetime.', - 'testPrune' => 'PhpArrayAdapter just proxies', - ]; - - protected static $file; - - public static function setUpBeforeClass() - { - self::$file = sys_get_temp_dir().'/symfony-cache/php-array-adapter-test.php'; - } - - protected function tearDown() - { - $this->createCachePool()->clear(); - - if (file_exists(sys_get_temp_dir().'/symfony-cache')) { - FilesystemAdapterTest::rmdir(sys_get_temp_dir().'/symfony-cache'); - } - } - - public function createCachePool() - { - return new PhpArrayAdapterWrapper(self::$file, new NullAdapter()); - } - - public function testStore() - { - $arrayWithRefs = []; - $arrayWithRefs[0] = 123; - $arrayWithRefs[1] = &$arrayWithRefs[0]; - - $object = (object) [ - 'foo' => 'bar', - 'foo2' => 'bar2', - ]; - - $expected = [ - 'null' => null, - 'serializedString' => serialize($object), - 'arrayWithRefs' => $arrayWithRefs, - 'object' => $object, - 'arrayWithObject' => ['bar' => $object], - ]; - - $adapter = $this->createCachePool(); - $adapter->warmUp($expected); - - foreach ($expected as $key => $value) { - $this->assertSame(serialize($value), serialize($adapter->getItem($key)->get()), 'Warm up should create a PHP file that OPCache can load in memory'); - } - } - - public function testStoredFile() - { - $expected = [ - 'integer' => 42, - 'float' => 42.42, - 'boolean' => true, - 'array_simple' => ['foo', 'bar'], - 'array_associative' => ['foo' => 'bar', 'foo2' => 'bar2'], - ]; - - $adapter = $this->createCachePool(); - $adapter->warmUp($expected); - - $values = eval(substr(file_get_contents(self::$file), 6)); - - $this->assertSame($expected, $values, 'Warm up should create a PHP file that OPCache can load in memory'); - } -} - -class PhpArrayAdapterWrapper extends PhpArrayAdapter -{ - public function save(CacheItemInterface $item) - { - \call_user_func(\Closure::bind(function () use ($item) { - $this->values[$item->getKey()] = $item->get(); - $this->warmUp($this->values); - $this->values = eval(substr(file_get_contents($this->file), 6)); - }, $this, PhpArrayAdapter::class)); - - return true; - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PhpArrayAdapterWithFallbackTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PhpArrayAdapterWithFallbackTest.php deleted file mode 100644 index 0bfd5c39..00000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PhpArrayAdapterWithFallbackTest.php +++ /dev/null @@ -1,51 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Adapter; - -use Symfony\Component\Cache\Adapter\FilesystemAdapter; -use Symfony\Component\Cache\Adapter\PhpArrayAdapter; - -/** - * @group time-sensitive - */ -class PhpArrayAdapterWithFallbackTest extends AdapterTestCase -{ - protected $skippedTests = [ - 'testGetItemInvalidKeys' => 'PhpArrayAdapter does not throw exceptions on invalid key.', - 'testGetItemsInvalidKeys' => 'PhpArrayAdapter does not throw exceptions on invalid key.', - 'testHasItemInvalidKeys' => 'PhpArrayAdapter does not throw exceptions on invalid key.', - 'testDeleteItemInvalidKeys' => 'PhpArrayAdapter does not throw exceptions on invalid key.', - 'testDeleteItemsInvalidKeys' => 'PhpArrayAdapter does not throw exceptions on invalid key.', - 'testPrune' => 'PhpArrayAdapter just proxies', - ]; - - protected static $file; - - public static function setUpBeforeClass() - { - self::$file = sys_get_temp_dir().'/symfony-cache/php-array-adapter-test.php'; - } - - protected function tearDown() - { - $this->createCachePool()->clear(); - - if (file_exists(sys_get_temp_dir().'/symfony-cache')) { - FilesystemAdapterTest::rmdir(sys_get_temp_dir().'/symfony-cache'); - } - } - - public function createCachePool($defaultLifetime = 0) - { - return new PhpArrayAdapter(self::$file, new FilesystemAdapter('php-array-fallback', $defaultLifetime)); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PhpFilesAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PhpFilesAdapterTest.php deleted file mode 100644 index 247160d5..00000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PhpFilesAdapterTest.php +++ /dev/null @@ -1,47 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Adapter; - -use Psr\Cache\CacheItemPoolInterface; -use Symfony\Component\Cache\Adapter\PhpFilesAdapter; - -/** - * @group time-sensitive - */ -class PhpFilesAdapterTest extends AdapterTestCase -{ - protected $skippedTests = [ - 'testDefaultLifeTime' => 'PhpFilesAdapter does not allow configuring a default lifetime.', - ]; - - public function createCachePool() - { - if (!PhpFilesAdapter::isSupported()) { - $this->markTestSkipped('OPcache extension is not enabled.'); - } - - return new PhpFilesAdapter('sf-cache'); - } - - public static function tearDownAfterClass() - { - FilesystemAdapterTest::rmdir(sys_get_temp_dir().'/symfony-cache'); - } - - protected function isPruned(CacheItemPoolInterface $cache, $name) - { - $getFileMethod = (new \ReflectionObject($cache))->getMethod('getFile'); - $getFileMethod->setAccessible(true); - - return !file_exists($getFileMethod->invoke($cache, $name)); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PredisAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PredisAdapterTest.php deleted file mode 100644 index 6aadbf26..00000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PredisAdapterTest.php +++ /dev/null @@ -1,53 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Adapter; - -use Predis\Connection\StreamConnection; -use Symfony\Component\Cache\Adapter\RedisAdapter; - -class PredisAdapterTest extends AbstractRedisAdapterTest -{ - public static function setUpBeforeClass() - { - parent::setUpBeforeClass(); - self::$redis = new \Predis\Client(['host' => getenv('REDIS_HOST')]); - } - - public function testCreateConnection() - { - $redisHost = getenv('REDIS_HOST'); - - $redis = RedisAdapter::createConnection('redis://'.$redisHost.'/1', ['class' => \Predis\Client::class, 'timeout' => 3]); - $this->assertInstanceOf(\Predis\Client::class, $redis); - - $connection = $redis->getConnection(); - $this->assertInstanceOf(StreamConnection::class, $connection); - - $params = [ - 'scheme' => 'tcp', - 'host' => $redisHost, - 'path' => '', - 'dbindex' => '1', - 'port' => 6379, - 'class' => 'Predis\Client', - 'timeout' => 3, - 'persistent' => 0, - 'persistent_id' => null, - 'read_timeout' => 0, - 'retry_interval' => 0, - 'lazy' => false, - 'database' => '1', - 'password' => null, - ]; - $this->assertSame($params, $connection->getParameters()->toArray()); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PredisClusterAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PredisClusterAdapterTest.php deleted file mode 100644 index 1afabaf1..00000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PredisClusterAdapterTest.php +++ /dev/null @@ -1,26 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Adapter; - -class PredisClusterAdapterTest extends AbstractRedisAdapterTest -{ - public static function setUpBeforeClass() - { - parent::setUpBeforeClass(); - self::$redis = new \Predis\Client([['host' => getenv('REDIS_HOST')]]); - } - - public static function tearDownAfterClass() - { - self::$redis = null; - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PredisRedisClusterAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PredisRedisClusterAdapterTest.php deleted file mode 100644 index 5b09919e..00000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PredisRedisClusterAdapterTest.php +++ /dev/null @@ -1,28 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Adapter; - -class PredisRedisClusterAdapterTest extends AbstractRedisAdapterTest -{ - public static function setUpBeforeClass() - { - if (!$hosts = getenv('REDIS_CLUSTER_HOSTS')) { - self::markTestSkipped('REDIS_CLUSTER_HOSTS env var is not defined.'); - } - self::$redis = new \Predis\Client(explode(' ', $hosts), ['cluster' => 'redis']); - } - - public static function tearDownAfterClass() - { - self::$redis = null; - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/ProxyAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/ProxyAdapterTest.php deleted file mode 100644 index 810cb31a..00000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/ProxyAdapterTest.php +++ /dev/null @@ -1,69 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Adapter; - -use Psr\Cache\CacheItemInterface; -use Symfony\Component\Cache\Adapter\ArrayAdapter; -use Symfony\Component\Cache\Adapter\ProxyAdapter; -use Symfony\Component\Cache\CacheItem; - -/** - * @group time-sensitive - */ -class ProxyAdapterTest extends AdapterTestCase -{ - protected $skippedTests = [ - 'testDeferredSaveWithoutCommit' => 'Assumes a shared cache which ArrayAdapter is not.', - 'testSaveWithoutExpire' => 'Assumes a shared cache which ArrayAdapter is not.', - 'testPrune' => 'ProxyAdapter just proxies', - ]; - - public function createCachePool($defaultLifetime = 0) - { - return new ProxyAdapter(new ArrayAdapter(), '', $defaultLifetime); - } - - public function testProxyfiedItem() - { - $this->expectException('Exception'); - $this->expectExceptionMessage('OK bar'); - $item = new CacheItem(); - $pool = new ProxyAdapter(new TestingArrayAdapter($item)); - - $proxyItem = $pool->getItem('foo'); - - $this->assertNotSame($item, $proxyItem); - $pool->save($proxyItem->set('bar')); - } -} - -class TestingArrayAdapter extends ArrayAdapter -{ - private $item; - - public function __construct(CacheItemInterface $item) - { - $this->item = $item; - } - - public function getItem($key) - { - return $this->item; - } - - public function save(CacheItemInterface $item) - { - if ($item === $this->item) { - throw new \Exception('OK '.$item->get()); - } - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/RedisAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/RedisAdapterTest.php deleted file mode 100644 index 6ec6321a..00000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/RedisAdapterTest.php +++ /dev/null @@ -1,92 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Adapter; - -use Symfony\Component\Cache\Adapter\AbstractAdapter; -use Symfony\Component\Cache\Adapter\RedisAdapter; -use Symfony\Component\Cache\Traits\RedisProxy; - -class RedisAdapterTest extends AbstractRedisAdapterTest -{ - public static function setUpBeforeClass() - { - parent::setUpBeforeClass(); - self::$redis = AbstractAdapter::createConnection('redis://'.getenv('REDIS_HOST'), ['lazy' => true]); - } - - public function createCachePool($defaultLifetime = 0) - { - $adapter = parent::createCachePool($defaultLifetime); - $this->assertInstanceOf(RedisProxy::class, self::$redis); - - return $adapter; - } - - public function testCreateConnection() - { - $redisHost = getenv('REDIS_HOST'); - - $redis = RedisAdapter::createConnection('redis://'.$redisHost); - $this->assertInstanceOf(\Redis::class, $redis); - $this->assertTrue($redis->isConnected()); - $this->assertSame(0, $redis->getDbNum()); - - $redis = RedisAdapter::createConnection('redis://'.$redisHost.'/2'); - $this->assertSame(2, $redis->getDbNum()); - - $redis = RedisAdapter::createConnection('redis://'.$redisHost, ['timeout' => 3]); - $this->assertEquals(3, $redis->getTimeout()); - - $redis = RedisAdapter::createConnection('redis://'.$redisHost.'?timeout=4'); - $this->assertEquals(4, $redis->getTimeout()); - - $redis = RedisAdapter::createConnection('redis://'.$redisHost, ['read_timeout' => 5]); - $this->assertEquals(5, $redis->getReadTimeout()); - } - - /** - * @dataProvider provideFailedCreateConnection - */ - public function testFailedCreateConnection($dsn) - { - $this->expectException('Symfony\Component\Cache\Exception\InvalidArgumentException'); - $this->expectExceptionMessage('Redis connection '); - RedisAdapter::createConnection($dsn); - } - - public function provideFailedCreateConnection() - { - return [ - ['redis://localhost:1234'], - ['redis://foo@localhost'], - ['redis://localhost/123'], - ]; - } - - /** - * @dataProvider provideInvalidCreateConnection - */ - public function testInvalidCreateConnection($dsn) - { - $this->expectException('Symfony\Component\Cache\Exception\InvalidArgumentException'); - $this->expectExceptionMessage('Invalid Redis DSN'); - RedisAdapter::createConnection($dsn); - } - - public function provideInvalidCreateConnection() - { - return [ - ['foo://localhost'], - ['redis://'], - ]; - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/RedisArrayAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/RedisArrayAdapterTest.php deleted file mode 100644 index bd9def32..00000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/RedisArrayAdapterTest.php +++ /dev/null @@ -1,24 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Adapter; - -class RedisArrayAdapterTest extends AbstractRedisAdapterTest -{ - public static function setUpBeforeClass() - { - parent::setupBeforeClass(); - if (!class_exists('RedisArray')) { - self::markTestSkipped('The RedisArray class is required.'); - } - self::$redis = new \RedisArray([getenv('REDIS_HOST')], ['lazy_connect' => true]); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/RedisClusterAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/RedisClusterAdapterTest.php deleted file mode 100644 index 9c339d2d..00000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/RedisClusterAdapterTest.php +++ /dev/null @@ -1,27 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Adapter; - -class RedisClusterAdapterTest extends AbstractRedisAdapterTest -{ - public static function setUpBeforeClass() - { - if (!class_exists('RedisCluster')) { - self::markTestSkipped('The RedisCluster class is required.'); - } - if (!$hosts = getenv('REDIS_CLUSTER_HOSTS')) { - self::markTestSkipped('REDIS_CLUSTER_HOSTS env var is not defined.'); - } - - self::$redis = new \RedisCluster(null, explode(' ', $hosts)); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/SimpleCacheAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/SimpleCacheAdapterTest.php deleted file mode 100644 index d8470a2e..00000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/SimpleCacheAdapterTest.php +++ /dev/null @@ -1,41 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Adapter; - -use Symfony\Component\Cache\Adapter\SimpleCacheAdapter; -use Symfony\Component\Cache\Simple\ArrayCache; -use Symfony\Component\Cache\Simple\FilesystemCache; - -/** - * @group time-sensitive - */ -class SimpleCacheAdapterTest extends AdapterTestCase -{ - protected $skippedTests = [ - 'testPrune' => 'SimpleCache just proxies', - ]; - - public function createCachePool($defaultLifetime = 0) - { - return new SimpleCacheAdapter(new FilesystemCache(), '', $defaultLifetime); - } - - public function testValidCacheKeyWithNamespace() - { - $cache = new SimpleCacheAdapter(new ArrayCache(), 'some_namespace', 0); - $item = $cache->getItem('my_key'); - $item->set('someValue'); - $cache->save($item); - - $this->assertTrue($cache->getItem('my_key')->isHit(), 'Stored item is successfully retrieved.'); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/TagAwareAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/TagAwareAdapterTest.php deleted file mode 100644 index 11907a03..00000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/TagAwareAdapterTest.php +++ /dev/null @@ -1,338 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Adapter; - -use PHPUnit\Framework\MockObject\MockObject; -use Psr\Cache\CacheItemInterface; -use Symfony\Component\Cache\Adapter\AdapterInterface; -use Symfony\Component\Cache\Adapter\ArrayAdapter; -use Symfony\Component\Cache\Adapter\FilesystemAdapter; -use Symfony\Component\Cache\Adapter\TagAwareAdapter; - -/** - * @group time-sensitive - */ -class TagAwareAdapterTest extends AdapterTestCase -{ - public function createCachePool($defaultLifetime = 0) - { - return new TagAwareAdapter(new FilesystemAdapter('', $defaultLifetime)); - } - - public static function tearDownAfterClass() - { - FilesystemAdapterTest::rmdir(sys_get_temp_dir().'/symfony-cache'); - } - - public function testInvalidTag() - { - $this->expectException('Psr\Cache\InvalidArgumentException'); - $pool = $this->createCachePool(); - $item = $pool->getItem('foo'); - $item->tag(':'); - } - - public function testInvalidateTags() - { - $pool = $this->createCachePool(); - - $i0 = $pool->getItem('i0'); - $i1 = $pool->getItem('i1'); - $i2 = $pool->getItem('i2'); - $i3 = $pool->getItem('i3'); - $foo = $pool->getItem('foo'); - - $pool->save($i0->tag('bar')); - $pool->save($i1->tag('foo')); - $pool->save($i2->tag('foo')->tag('bar')); - $pool->save($i3->tag('foo')->tag('baz')); - $pool->save($foo); - - $pool->invalidateTags(['bar']); - - $this->assertFalse($pool->getItem('i0')->isHit()); - $this->assertTrue($pool->getItem('i1')->isHit()); - $this->assertFalse($pool->getItem('i2')->isHit()); - $this->assertTrue($pool->getItem('i3')->isHit()); - $this->assertTrue($pool->getItem('foo')->isHit()); - - $pool->invalidateTags(['foo']); - - $this->assertFalse($pool->getItem('i1')->isHit()); - $this->assertFalse($pool->getItem('i3')->isHit()); - $this->assertTrue($pool->getItem('foo')->isHit()); - - $anotherPoolInstance = $this->createCachePool(); - - $this->assertFalse($anotherPoolInstance->getItem('i1')->isHit()); - $this->assertFalse($anotherPoolInstance->getItem('i3')->isHit()); - $this->assertTrue($anotherPoolInstance->getItem('foo')->isHit()); - } - - public function testInvalidateCommits() - { - $pool1 = $this->createCachePool(); - - $foo = $pool1->getItem('foo'); - $foo->tag('tag'); - - $pool1->saveDeferred($foo->set('foo')); - $pool1->invalidateTags(['tag']); - - $pool2 = $this->createCachePool(); - $foo = $pool2->getItem('foo'); - - $this->assertTrue($foo->isHit()); - } - - public function testTagsAreCleanedOnSave() - { - $pool = $this->createCachePool(); - - $i = $pool->getItem('k'); - $pool->save($i->tag('foo')); - - $i = $pool->getItem('k'); - $pool->save($i->tag('bar')); - - $pool->invalidateTags(['foo']); - $this->assertTrue($pool->getItem('k')->isHit()); - } - - public function testTagsAreCleanedOnDelete() - { - $pool = $this->createCachePool(); - - $i = $pool->getItem('k'); - $pool->save($i->tag('foo')); - $pool->deleteItem('k'); - - $pool->save($pool->getItem('k')); - $pool->invalidateTags(['foo']); - - $this->assertTrue($pool->getItem('k')->isHit()); - } - - public function testTagItemExpiry() - { - $pool = $this->createCachePool(10); - - $item = $pool->getItem('foo'); - $item->tag(['baz']); - $item->expiresAfter(100); - - $pool->save($item); - $pool->invalidateTags(['baz']); - $this->assertFalse($pool->getItem('foo')->isHit()); - - sleep(20); - - $this->assertFalse($pool->getItem('foo')->isHit()); - } - - public function testGetPreviousTags() - { - $pool = $this->createCachePool(); - - $i = $pool->getItem('k'); - $pool->save($i->tag('foo')); - - $i = $pool->getItem('k'); - $this->assertSame(['foo' => 'foo'], $i->getPreviousTags()); - } - - public function testPrune() - { - $cache = new TagAwareAdapter($this->getPruneableMock()); - $this->assertTrue($cache->prune()); - - $cache = new TagAwareAdapter($this->getNonPruneableMock()); - $this->assertFalse($cache->prune()); - - $cache = new TagAwareAdapter($this->getFailingPruneableMock()); - $this->assertFalse($cache->prune()); - } - - public function testKnownTagVersionsTtl() - { - $itemsPool = new FilesystemAdapter('', 10); - $tagsPool = $this - ->getMockBuilder(AdapterInterface::class) - ->getMock(); - - $pool = new TagAwareAdapter($itemsPool, $tagsPool, 10); - - $item = $pool->getItem('foo'); - $item->tag(['baz']); - $item->expiresAfter(100); - - $tag = $this->getMockBuilder(CacheItemInterface::class)->getMock(); - $tag->expects(self::exactly(2))->method('get')->willReturn(10); - - $tagsPool->expects(self::exactly(2))->method('getItems')->willReturn([ - 'baz'.TagAwareAdapter::TAGS_PREFIX => $tag, - ]); - - $pool->save($item); - $this->assertTrue($pool->getItem('foo')->isHit()); - $this->assertTrue($pool->getItem('foo')->isHit()); - - sleep(20); - - $this->assertTrue($pool->getItem('foo')->isHit()); - - sleep(5); - - $this->assertTrue($pool->getItem('foo')->isHit()); - } - - public function testTagEntryIsCreatedForItemWithoutTags() - { - $pool = $this->createCachePool(); - - $itemKey = 'foo'; - $item = $pool->getItem($itemKey); - $pool->save($item); - - $adapter = new FilesystemAdapter(); - $this->assertTrue($adapter->hasItem(TagAwareAdapter::TAGS_PREFIX.$itemKey)); - } - - public function testHasItemReturnsFalseWhenPoolDoesNotHaveItemTags() - { - $pool = $this->createCachePool(); - - $itemKey = 'foo'; - $item = $pool->getItem($itemKey); - $pool->save($item); - - $anotherPool = $this->createCachePool(); - - $adapter = new FilesystemAdapter(); - $adapter->deleteItem(TagAwareAdapter::TAGS_PREFIX.$itemKey); //simulate item losing tags pair - - $this->assertFalse($anotherPool->hasItem($itemKey)); - } - - public function testGetItemReturnsCacheMissWhenPoolDoesNotHaveItemTags() - { - $pool = $this->createCachePool(); - - $itemKey = 'foo'; - $item = $pool->getItem($itemKey); - $pool->save($item); - - $anotherPool = $this->createCachePool(); - - $adapter = new FilesystemAdapter(); - $adapter->deleteItem(TagAwareAdapter::TAGS_PREFIX.$itemKey); //simulate item losing tags pair - - $item = $anotherPool->getItem($itemKey); - $this->assertFalse($item->isHit()); - } - - public function testHasItemReturnsFalseWhenPoolDoesNotHaveItemAndOnlyHasTags() - { - $pool = $this->createCachePool(); - - $itemKey = 'foo'; - $item = $pool->getItem($itemKey); - $pool->save($item); - - $anotherPool = $this->createCachePool(); - - $adapter = new FilesystemAdapter(); - $adapter->deleteItem($itemKey); //simulate losing item but keeping tags - - $this->assertFalse($anotherPool->hasItem($itemKey)); - } - - public function testInvalidateTagsWithArrayAdapter() - { - $adapter = new TagAwareAdapter(new ArrayAdapter()); - - $item = $adapter->getItem('foo'); - - $this->assertFalse($item->isHit()); - - $item->tag('bar'); - $item->expiresAfter(100); - $adapter->save($item); - - $this->assertTrue($adapter->getItem('foo')->isHit()); - - $adapter->invalidateTags(['bar']); - - $this->assertFalse($adapter->getItem('foo')->isHit()); - } - - public function testGetItemReturnsCacheMissWhenPoolDoesNotHaveItemAndOnlyHasTags() - { - $pool = $this->createCachePool(); - - $itemKey = 'foo'; - $item = $pool->getItem($itemKey); - $pool->save($item); - - $anotherPool = $this->createCachePool(); - - $adapter = new FilesystemAdapter(); - $adapter->deleteItem($itemKey); //simulate losing item but keeping tags - - $item = $anotherPool->getItem($itemKey); - $this->assertFalse($item->isHit()); - } - - /** - * @return MockObject|PruneableCacheInterface - */ - private function getPruneableMock() - { - $pruneable = $this - ->getMockBuilder(PruneableCacheInterface::class) - ->getMock(); - - $pruneable - ->expects($this->atLeastOnce()) - ->method('prune') - ->willReturn(true); - - return $pruneable; - } - - /** - * @return MockObject|PruneableCacheInterface - */ - private function getFailingPruneableMock() - { - $pruneable = $this - ->getMockBuilder(PruneableCacheInterface::class) - ->getMock(); - - $pruneable - ->expects($this->atLeastOnce()) - ->method('prune') - ->willReturn(false); - - return $pruneable; - } - - /** - * @return MockObject|AdapterInterface - */ - private function getNonPruneableMock() - { - return $this - ->getMockBuilder(AdapterInterface::class) - ->getMock(); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/TagAwareAndProxyAdapterIntegrationTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/TagAwareAndProxyAdapterIntegrationTest.php deleted file mode 100644 index b11c1f28..00000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/TagAwareAndProxyAdapterIntegrationTest.php +++ /dev/null @@ -1,38 +0,0 @@ -getItem('foo'); - $item->tag(['tag1', 'tag2']); - $item->set('bar'); - $cache->save($item); - - $this->assertSame('bar', $cache->getItem('foo')->get()); - } - - public function dataProvider() - { - return [ - [new ArrayAdapter()], - // also testing with a non-AdapterInterface implementation - // because the ProxyAdapter behaves slightly different for those - [new ExternalAdapter()], - ]; - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/TraceableAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/TraceableAdapterTest.php deleted file mode 100644 index 35eba7d7..00000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/TraceableAdapterTest.php +++ /dev/null @@ -1,191 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Adapter; - -use Symfony\Component\Cache\Adapter\FilesystemAdapter; -use Symfony\Component\Cache\Adapter\TraceableAdapter; - -/** - * @group time-sensitive - */ -class TraceableAdapterTest extends AdapterTestCase -{ - protected $skippedTests = [ - 'testPrune' => 'TraceableAdapter just proxies', - ]; - - public function createCachePool($defaultLifetime = 0) - { - return new TraceableAdapter(new FilesystemAdapter('', $defaultLifetime)); - } - - public function testGetItemMissTrace() - { - $pool = $this->createCachePool(); - $pool->getItem('k'); - $calls = $pool->getCalls(); - $this->assertCount(1, $calls); - - $call = $calls[0]; - $this->assertSame('getItem', $call->name); - $this->assertSame(['k' => false], $call->result); - $this->assertSame(0, $call->hits); - $this->assertSame(1, $call->misses); - $this->assertNotEmpty($call->start); - $this->assertNotEmpty($call->end); - } - - public function testGetItemHitTrace() - { - $pool = $this->createCachePool(); - $item = $pool->getItem('k')->set('foo'); - $pool->save($item); - $pool->getItem('k'); - $calls = $pool->getCalls(); - $this->assertCount(3, $calls); - - $call = $calls[2]; - $this->assertSame(1, $call->hits); - $this->assertSame(0, $call->misses); - } - - public function testGetItemsMissTrace() - { - $pool = $this->createCachePool(); - $arg = ['k0', 'k1']; - $items = $pool->getItems($arg); - foreach ($items as $item) { - } - $calls = $pool->getCalls(); - $this->assertCount(1, $calls); - - $call = $calls[0]; - $this->assertSame('getItems', $call->name); - $this->assertSame(['k0' => false, 'k1' => false], $call->result); - $this->assertSame(2, $call->misses); - $this->assertNotEmpty($call->start); - $this->assertNotEmpty($call->end); - } - - public function testHasItemMissTrace() - { - $pool = $this->createCachePool(); - $pool->hasItem('k'); - $calls = $pool->getCalls(); - $this->assertCount(1, $calls); - - $call = $calls[0]; - $this->assertSame('hasItem', $call->name); - $this->assertSame(['k' => false], $call->result); - $this->assertNotEmpty($call->start); - $this->assertNotEmpty($call->end); - } - - public function testHasItemHitTrace() - { - $pool = $this->createCachePool(); - $item = $pool->getItem('k')->set('foo'); - $pool->save($item); - $pool->hasItem('k'); - $calls = $pool->getCalls(); - $this->assertCount(3, $calls); - - $call = $calls[2]; - $this->assertSame('hasItem', $call->name); - $this->assertSame(['k' => true], $call->result); - $this->assertNotEmpty($call->start); - $this->assertNotEmpty($call->end); - } - - public function testDeleteItemTrace() - { - $pool = $this->createCachePool(); - $pool->deleteItem('k'); - $calls = $pool->getCalls(); - $this->assertCount(1, $calls); - - $call = $calls[0]; - $this->assertSame('deleteItem', $call->name); - $this->assertSame(['k' => true], $call->result); - $this->assertSame(0, $call->hits); - $this->assertSame(0, $call->misses); - $this->assertNotEmpty($call->start); - $this->assertNotEmpty($call->end); - } - - public function testDeleteItemsTrace() - { - $pool = $this->createCachePool(); - $arg = ['k0', 'k1']; - $pool->deleteItems($arg); - $calls = $pool->getCalls(); - $this->assertCount(1, $calls); - - $call = $calls[0]; - $this->assertSame('deleteItems', $call->name); - $this->assertSame(['keys' => $arg, 'result' => true], $call->result); - $this->assertSame(0, $call->hits); - $this->assertSame(0, $call->misses); - $this->assertNotEmpty($call->start); - $this->assertNotEmpty($call->end); - } - - public function testSaveTrace() - { - $pool = $this->createCachePool(); - $item = $pool->getItem('k')->set('foo'); - $pool->save($item); - $calls = $pool->getCalls(); - $this->assertCount(2, $calls); - - $call = $calls[1]; - $this->assertSame('save', $call->name); - $this->assertSame(['k' => true], $call->result); - $this->assertSame(0, $call->hits); - $this->assertSame(0, $call->misses); - $this->assertNotEmpty($call->start); - $this->assertNotEmpty($call->end); - } - - public function testSaveDeferredTrace() - { - $pool = $this->createCachePool(); - $item = $pool->getItem('k')->set('foo'); - $pool->saveDeferred($item); - $calls = $pool->getCalls(); - $this->assertCount(2, $calls); - - $call = $calls[1]; - $this->assertSame('saveDeferred', $call->name); - $this->assertSame(['k' => true], $call->result); - $this->assertSame(0, $call->hits); - $this->assertSame(0, $call->misses); - $this->assertNotEmpty($call->start); - $this->assertNotEmpty($call->end); - } - - public function testCommitTrace() - { - $pool = $this->createCachePool(); - $pool->commit(); - $calls = $pool->getCalls(); - $this->assertCount(1, $calls); - - $call = $calls[0]; - $this->assertSame('commit', $call->name); - $this->assertTrue($call->result); - $this->assertSame(0, $call->hits); - $this->assertSame(0, $call->misses); - $this->assertNotEmpty($call->start); - $this->assertNotEmpty($call->end); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/TraceableTagAwareAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/TraceableTagAwareAdapterTest.php deleted file mode 100644 index 5cd4185c..00000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/TraceableTagAwareAdapterTest.php +++ /dev/null @@ -1,37 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Adapter; - -use Symfony\Component\Cache\Adapter\FilesystemAdapter; -use Symfony\Component\Cache\Adapter\TagAwareAdapter; -use Symfony\Component\Cache\Adapter\TraceableTagAwareAdapter; - -/** - * @group time-sensitive - */ -class TraceableTagAwareAdapterTest extends TraceableAdapterTest -{ - public function testInvalidateTags() - { - $pool = new TraceableTagAwareAdapter(new TagAwareAdapter(new FilesystemAdapter())); - $pool->invalidateTags(['foo']); - $calls = $pool->getCalls(); - $this->assertCount(1, $calls); - - $call = $calls[0]; - $this->assertSame('invalidateTags', $call->name); - $this->assertSame(0, $call->hits); - $this->assertSame(0, $call->misses); - $this->assertNotEmpty($call->start); - $this->assertNotEmpty($call->end); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/CacheItemTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/CacheItemTest.php deleted file mode 100644 index 28c681d1..00000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/CacheItemTest.php +++ /dev/null @@ -1,77 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Cache\CacheItem; - -class CacheItemTest extends TestCase -{ - public function testValidKey() - { - $this->assertSame('foo', CacheItem::validateKey('foo')); - } - - /** - * @dataProvider provideInvalidKey - */ - public function testInvalidKey($key) - { - $this->expectException('Symfony\Component\Cache\Exception\InvalidArgumentException'); - $this->expectExceptionMessage('Cache key'); - CacheItem::validateKey($key); - } - - public function provideInvalidKey() - { - return [ - [''], - ['{'], - ['}'], - ['('], - [')'], - ['/'], - ['\\'], - ['@'], - [':'], - [true], - [null], - [1], - [1.1], - [[[]]], - [new \Exception('foo')], - ]; - } - - public function testTag() - { - $item = new CacheItem(); - - $this->assertSame($item, $item->tag('foo')); - $this->assertSame($item, $item->tag(['bar', 'baz'])); - - \call_user_func(\Closure::bind(function () use ($item) { - $this->assertSame(['foo' => 'foo', 'bar' => 'bar', 'baz' => 'baz'], $item->tags); - }, $this, CacheItem::class)); - } - - /** - * @dataProvider provideInvalidKey - */ - public function testInvalidTag($tag) - { - $this->expectException('Symfony\Component\Cache\Exception\InvalidArgumentException'); - $this->expectExceptionMessage('Cache tag'); - $item = new CacheItem(); - $item->tag($tag); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/DoctrineProviderTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/DoctrineProviderTest.php deleted file mode 100644 index 91a5516a..00000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/DoctrineProviderTest.php +++ /dev/null @@ -1,45 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests; - -use Doctrine\Common\Cache\CacheProvider; -use PHPUnit\Framework\TestCase; -use Symfony\Component\Cache\Adapter\ArrayAdapter; -use Symfony\Component\Cache\DoctrineProvider; - -class DoctrineProviderTest extends TestCase -{ - public function testProvider() - { - $pool = new ArrayAdapter(); - $cache = new DoctrineProvider($pool); - - $this->assertInstanceOf(CacheProvider::class, $cache); - - $key = '{}()/\@:'; - - $this->assertTrue($cache->delete($key)); - $this->assertFalse($cache->contains($key)); - - $this->assertTrue($cache->save($key, 'bar')); - $this->assertTrue($cache->contains($key)); - $this->assertSame('bar', $cache->fetch($key)); - - $this->assertTrue($cache->delete($key)); - $this->assertFalse($cache->fetch($key)); - $this->assertTrue($cache->save($key, 'bar')); - - $cache->flushAll(); - $this->assertFalse($cache->fetch($key)); - $this->assertFalse($cache->contains($key)); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Fixtures/ArrayCache.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Fixtures/ArrayCache.php deleted file mode 100644 index 13b4f330..00000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Fixtures/ArrayCache.php +++ /dev/null @@ -1,52 +0,0 @@ -doContains($id) ? $this->data[$id][0] : false; - } - - protected function doContains($id) - { - if (!isset($this->data[$id])) { - return false; - } - - $expiry = $this->data[$id][1]; - - return !$expiry || time() < $expiry || !$this->doDelete($id); - } - - protected function doSave($id, $data, $lifeTime = 0) - { - $this->data[$id] = [$data, $lifeTime ? time() + $lifeTime : false]; - - return true; - } - - protected function doDelete($id) - { - unset($this->data[$id]); - - return true; - } - - protected function doFlush() - { - $this->data = []; - - return true; - } - - protected function doGetStats() - { - return null; - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Fixtures/ExternalAdapter.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Fixtures/ExternalAdapter.php deleted file mode 100644 index be1f9901..00000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Fixtures/ExternalAdapter.php +++ /dev/null @@ -1,76 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Fixtures; - -use Psr\Cache\CacheItemInterface; -use Psr\Cache\CacheItemPoolInterface; -use Symfony\Component\Cache\Adapter\ArrayAdapter; - -/** - * Adapter not implementing the {@see \Symfony\Component\Cache\Adapter\AdapterInterface}. - * - * @author Kévin Dunglas - */ -class ExternalAdapter implements CacheItemPoolInterface -{ - private $cache; - - public function __construct($defaultLifetime = 0) - { - $this->cache = new ArrayAdapter($defaultLifetime); - } - - public function getItem($key) - { - return $this->cache->getItem($key); - } - - public function getItems(array $keys = []) - { - return $this->cache->getItems($keys); - } - - public function hasItem($key) - { - return $this->cache->hasItem($key); - } - - public function clear() - { - return $this->cache->clear(); - } - - public function deleteItem($key) - { - return $this->cache->deleteItem($key); - } - - public function deleteItems(array $keys) - { - return $this->cache->deleteItems($keys); - } - - public function save(CacheItemInterface $item) - { - return $this->cache->save($item); - } - - public function saveDeferred(CacheItemInterface $item) - { - return $this->cache->saveDeferred($item); - } - - public function commit() - { - return $this->cache->commit(); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/AbstractRedisCacheTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/AbstractRedisCacheTest.php deleted file mode 100644 index 7a6cabe8..00000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/AbstractRedisCacheTest.php +++ /dev/null @@ -1,47 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Simple; - -use Symfony\Component\Cache\Simple\RedisCache; - -abstract class AbstractRedisCacheTest extends CacheTestCase -{ - protected $skippedTests = [ - 'testSetTtl' => 'Testing expiration slows down the test suite', - 'testSetMultipleTtl' => 'Testing expiration slows down the test suite', - 'testDefaultLifeTime' => 'Testing expiration slows down the test suite', - ]; - - protected static $redis; - - public function createSimpleCache($defaultLifetime = 0) - { - return new RedisCache(self::$redis, str_replace('\\', '.', __CLASS__), $defaultLifetime); - } - - public static function setUpBeforeClass() - { - if (!\extension_loaded('redis')) { - self::markTestSkipped('Extension redis required.'); - } - try { - (new \Redis())->connect(getenv('REDIS_HOST')); - } catch (\Exception $e) { - self::markTestSkipped($e->getMessage()); - } - } - - public static function tearDownAfterClass() - { - self::$redis = null; - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/ApcuCacheTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/ApcuCacheTest.php deleted file mode 100644 index fad0c043..00000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/ApcuCacheTest.php +++ /dev/null @@ -1,35 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Simple; - -use Symfony\Component\Cache\Simple\ApcuCache; - -class ApcuCacheTest extends CacheTestCase -{ - protected $skippedTests = [ - 'testSetTtl' => 'Testing expiration slows down the test suite', - 'testSetMultipleTtl' => 'Testing expiration slows down the test suite', - 'testDefaultLifeTime' => 'Testing expiration slows down the test suite', - ]; - - public function createSimpleCache($defaultLifetime = 0) - { - if (!\function_exists('apcu_fetch') || !filter_var(ini_get('apc.enabled'), \FILTER_VALIDATE_BOOLEAN) || ('cli' === \PHP_SAPI && !filter_var(ini_get('apc.enable_cli'), \FILTER_VALIDATE_BOOLEAN))) { - $this->markTestSkipped('APCu extension is required.'); - } - if ('\\' === \DIRECTORY_SEPARATOR) { - $this->markTestSkipped('Fails transiently on Windows.'); - } - - return new ApcuCache(str_replace('\\', '.', __CLASS__), $defaultLifetime); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/ArrayCacheTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/ArrayCacheTest.php deleted file mode 100644 index 26c3e14d..00000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/ArrayCacheTest.php +++ /dev/null @@ -1,25 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Simple; - -use Symfony\Component\Cache\Simple\ArrayCache; - -/** - * @group time-sensitive - */ -class ArrayCacheTest extends CacheTestCase -{ - public function createSimpleCache($defaultLifetime = 0) - { - return new ArrayCache($defaultLifetime); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/CacheTestCase.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/CacheTestCase.php deleted file mode 100644 index ff9944a3..00000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/CacheTestCase.php +++ /dev/null @@ -1,150 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Simple; - -use Cache\IntegrationTests\SimpleCacheTest; -use Psr\SimpleCache\CacheInterface; -use Symfony\Component\Cache\PruneableInterface; - -abstract class CacheTestCase extends SimpleCacheTest -{ - protected function setUp() - { - parent::setUp(); - - if (!\array_key_exists('testPrune', $this->skippedTests) && !$this->createSimpleCache() instanceof PruneableInterface) { - $this->skippedTests['testPrune'] = 'Not a pruneable cache pool.'; - } - } - - public static function validKeys() - { - if (\defined('HHVM_VERSION')) { - return parent::validKeys(); - } - - return array_merge(parent::validKeys(), [["a\0b"]]); - } - - public function testDefaultLifeTime() - { - if (isset($this->skippedTests[__FUNCTION__])) { - $this->markTestSkipped($this->skippedTests[__FUNCTION__]); - } - - $cache = $this->createSimpleCache(2); - $cache->clear(); - - $cache->set('key.dlt', 'value'); - sleep(1); - - $this->assertSame('value', $cache->get('key.dlt')); - - sleep(2); - $this->assertNull($cache->get('key.dlt')); - - $cache->clear(); - } - - public function testNotUnserializable() - { - if (isset($this->skippedTests[__FUNCTION__])) { - $this->markTestSkipped($this->skippedTests[__FUNCTION__]); - } - - $cache = $this->createSimpleCache(); - $cache->clear(); - - $cache->set('foo', new NotUnserializable()); - - $this->assertNull($cache->get('foo')); - - $cache->setMultiple(['foo' => new NotUnserializable()]); - - foreach ($cache->getMultiple(['foo']) as $value) { - } - $this->assertNull($value); - - $cache->clear(); - } - - public function testPrune() - { - if (isset($this->skippedTests[__FUNCTION__])) { - $this->markTestSkipped($this->skippedTests[__FUNCTION__]); - } - - if (!method_exists($this, 'isPruned')) { - $this->fail('Test classes for pruneable caches must implement `isPruned($cache, $name)` method.'); - } - - /** @var PruneableInterface|CacheInterface $cache */ - $cache = $this->createSimpleCache(); - $cache->clear(); - - $cache->set('foo', 'foo-val', new \DateInterval('PT05S')); - $cache->set('bar', 'bar-val', new \DateInterval('PT10S')); - $cache->set('baz', 'baz-val', new \DateInterval('PT15S')); - $cache->set('qux', 'qux-val', new \DateInterval('PT20S')); - - sleep(30); - $cache->prune(); - $this->assertTrue($this->isPruned($cache, 'foo')); - $this->assertTrue($this->isPruned($cache, 'bar')); - $this->assertTrue($this->isPruned($cache, 'baz')); - $this->assertTrue($this->isPruned($cache, 'qux')); - - $cache->set('foo', 'foo-val'); - $cache->set('bar', 'bar-val', new \DateInterval('PT20S')); - $cache->set('baz', 'baz-val', new \DateInterval('PT40S')); - $cache->set('qux', 'qux-val', new \DateInterval('PT80S')); - - $cache->prune(); - $this->assertFalse($this->isPruned($cache, 'foo')); - $this->assertFalse($this->isPruned($cache, 'bar')); - $this->assertFalse($this->isPruned($cache, 'baz')); - $this->assertFalse($this->isPruned($cache, 'qux')); - - sleep(30); - $cache->prune(); - $this->assertFalse($this->isPruned($cache, 'foo')); - $this->assertTrue($this->isPruned($cache, 'bar')); - $this->assertFalse($this->isPruned($cache, 'baz')); - $this->assertFalse($this->isPruned($cache, 'qux')); - - sleep(30); - $cache->prune(); - $this->assertFalse($this->isPruned($cache, 'foo')); - $this->assertTrue($this->isPruned($cache, 'baz')); - $this->assertFalse($this->isPruned($cache, 'qux')); - - sleep(30); - $cache->prune(); - $this->assertFalse($this->isPruned($cache, 'foo')); - $this->assertTrue($this->isPruned($cache, 'qux')); - - $cache->clear(); - } -} - -class NotUnserializable implements \Serializable -{ - public function serialize() - { - return serialize(123); - } - - public function unserialize($ser) - { - throw new \Exception(__CLASS__); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/ChainCacheTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/ChainCacheTest.php deleted file mode 100644 index f216bc1f..00000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/ChainCacheTest.php +++ /dev/null @@ -1,113 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Simple; - -use PHPUnit\Framework\MockObject\MockObject; -use Psr\SimpleCache\CacheInterface; -use Symfony\Component\Cache\PruneableInterface; -use Symfony\Component\Cache\Simple\ArrayCache; -use Symfony\Component\Cache\Simple\ChainCache; -use Symfony\Component\Cache\Simple\FilesystemCache; - -/** - * @group time-sensitive - */ -class ChainCacheTest extends CacheTestCase -{ - public function createSimpleCache($defaultLifetime = 0) - { - return new ChainCache([new ArrayCache($defaultLifetime), new FilesystemCache('', $defaultLifetime)], $defaultLifetime); - } - - public function testEmptyCachesException() - { - $this->expectException('Symfony\Component\Cache\Exception\InvalidArgumentException'); - $this->expectExceptionMessage('At least one cache must be specified.'); - new ChainCache([]); - } - - public function testInvalidCacheException() - { - $this->expectException('Symfony\Component\Cache\Exception\InvalidArgumentException'); - $this->expectExceptionMessage('The class "stdClass" does not implement'); - new ChainCache([new \stdClass()]); - } - - public function testPrune() - { - if (isset($this->skippedTests[__FUNCTION__])) { - $this->markTestSkipped($this->skippedTests[__FUNCTION__]); - } - - $cache = new ChainCache([ - $this->getPruneableMock(), - $this->getNonPruneableMock(), - $this->getPruneableMock(), - ]); - $this->assertTrue($cache->prune()); - - $cache = new ChainCache([ - $this->getPruneableMock(), - $this->getFailingPruneableMock(), - $this->getPruneableMock(), - ]); - $this->assertFalse($cache->prune()); - } - - /** - * @return MockObject|PruneableCacheInterface - */ - private function getPruneableMock() - { - $pruneable = $this - ->getMockBuilder(PruneableCacheInterface::class) - ->getMock(); - - $pruneable - ->expects($this->atLeastOnce()) - ->method('prune') - ->willReturn(true); - - return $pruneable; - } - - /** - * @return MockObject|PruneableCacheInterface - */ - private function getFailingPruneableMock() - { - $pruneable = $this - ->getMockBuilder(PruneableCacheInterface::class) - ->getMock(); - - $pruneable - ->expects($this->atLeastOnce()) - ->method('prune') - ->willReturn(false); - - return $pruneable; - } - - /** - * @return MockObject|CacheInterface - */ - private function getNonPruneableMock() - { - return $this - ->getMockBuilder(CacheInterface::class) - ->getMock(); - } -} - -interface PruneableCacheInterface extends PruneableInterface, CacheInterface -{ -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/DoctrineCacheTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/DoctrineCacheTest.php deleted file mode 100644 index af4331d6..00000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/DoctrineCacheTest.php +++ /dev/null @@ -1,31 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Simple; - -use Symfony\Component\Cache\Simple\DoctrineCache; -use Symfony\Component\Cache\Tests\Fixtures\ArrayCache; - -/** - * @group time-sensitive - */ -class DoctrineCacheTest extends CacheTestCase -{ - protected $skippedTests = [ - 'testObjectDoesNotChangeInCache' => 'ArrayCache does not use serialize/unserialize', - 'testNotUnserializable' => 'ArrayCache does not use serialize/unserialize', - ]; - - public function createSimpleCache($defaultLifetime = 0) - { - return new DoctrineCache(new ArrayCache($defaultLifetime), '', $defaultLifetime); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/FilesystemCacheTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/FilesystemCacheTest.php deleted file mode 100644 index 620305a5..00000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/FilesystemCacheTest.php +++ /dev/null @@ -1,34 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Simple; - -use Psr\SimpleCache\CacheInterface; -use Symfony\Component\Cache\Simple\FilesystemCache; - -/** - * @group time-sensitive - */ -class FilesystemCacheTest extends CacheTestCase -{ - public function createSimpleCache($defaultLifetime = 0) - { - return new FilesystemCache('', $defaultLifetime); - } - - protected function isPruned(CacheInterface $cache, $name) - { - $getFileMethod = (new \ReflectionObject($cache))->getMethod('getFile'); - $getFileMethod->setAccessible(true); - - return !file_exists($getFileMethod->invoke($cache, $name)); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/MemcachedCacheTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/MemcachedCacheTest.php deleted file mode 100644 index 6df682e9..00000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/MemcachedCacheTest.php +++ /dev/null @@ -1,178 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Simple; - -use Symfony\Component\Cache\Adapter\AbstractAdapter; -use Symfony\Component\Cache\Simple\MemcachedCache; - -class MemcachedCacheTest extends CacheTestCase -{ - protected $skippedTests = [ - 'testSetTtl' => 'Testing expiration slows down the test suite', - 'testSetMultipleTtl' => 'Testing expiration slows down the test suite', - 'testDefaultLifeTime' => 'Testing expiration slows down the test suite', - ]; - - protected static $client; - - public static function setUpBeforeClass() - { - if (!MemcachedCache::isSupported()) { - self::markTestSkipped('Extension memcached >=2.2.0 required.'); - } - self::$client = AbstractAdapter::createConnection('memcached://'.getenv('MEMCACHED_HOST')); - self::$client->get('foo'); - $code = self::$client->getResultCode(); - - if (\Memcached::RES_SUCCESS !== $code && \Memcached::RES_NOTFOUND !== $code) { - self::markTestSkipped('Memcached error: '.strtolower(self::$client->getResultMessage())); - } - } - - public function createSimpleCache($defaultLifetime = 0) - { - $client = $defaultLifetime ? AbstractAdapter::createConnection('memcached://'.getenv('MEMCACHED_HOST'), ['binary_protocol' => false]) : self::$client; - - return new MemcachedCache($client, str_replace('\\', '.', __CLASS__), $defaultLifetime); - } - - public function testCreatePersistentConnectionShouldNotDupServerList() - { - $instance = MemcachedCache::createConnection('memcached://'.getenv('MEMCACHED_HOST'), ['persistent_id' => 'persistent']); - $this->assertCount(1, $instance->getServerList()); - - $instance = MemcachedCache::createConnection('memcached://'.getenv('MEMCACHED_HOST'), ['persistent_id' => 'persistent']); - $this->assertCount(1, $instance->getServerList()); - } - - public function testOptions() - { - $client = MemcachedCache::createConnection([], [ - 'libketama_compatible' => false, - 'distribution' => 'modula', - 'compression' => true, - 'serializer' => 'php', - 'hash' => 'md5', - ]); - - $this->assertSame(\Memcached::SERIALIZER_PHP, $client->getOption(\Memcached::OPT_SERIALIZER)); - $this->assertSame(\Memcached::HASH_MD5, $client->getOption(\Memcached::OPT_HASH)); - $this->assertTrue($client->getOption(\Memcached::OPT_COMPRESSION)); - $this->assertSame(0, $client->getOption(\Memcached::OPT_LIBKETAMA_COMPATIBLE)); - $this->assertSame(\Memcached::DISTRIBUTION_MODULA, $client->getOption(\Memcached::OPT_DISTRIBUTION)); - } - - /** - * @dataProvider provideBadOptions - */ - public function testBadOptions($name, $value) - { - if (\PHP_VERSION_ID < 80000) { - $this->expectException('ErrorException'); - $this->expectExceptionMessage('constant(): Couldn\'t find constant Memcached::'); - } else { - $this->expectException('Error'); - $this->expectExceptionMessage('Undefined constant Memcached::'); - } - - MemcachedCache::createConnection([], [$name => $value]); - } - - public function provideBadOptions() - { - return [ - ['foo', 'bar'], - ['hash', 'zyx'], - ['serializer', 'zyx'], - ['distribution', 'zyx'], - ]; - } - - public function testDefaultOptions() - { - $this->assertTrue(MemcachedCache::isSupported()); - - $client = MemcachedCache::createConnection([]); - - $this->assertTrue($client->getOption(\Memcached::OPT_COMPRESSION)); - $this->assertSame(1, $client->getOption(\Memcached::OPT_BINARY_PROTOCOL)); - $this->assertSame(1, $client->getOption(\Memcached::OPT_LIBKETAMA_COMPATIBLE)); - } - - public function testOptionSerializer() - { - $this->expectException('Symfony\Component\Cache\Exception\CacheException'); - $this->expectExceptionMessage('MemcachedAdapter: "serializer" option must be "php" or "igbinary".'); - if (!\Memcached::HAVE_JSON) { - $this->markTestSkipped('Memcached::HAVE_JSON required'); - } - - new MemcachedCache(MemcachedCache::createConnection([], ['serializer' => 'json'])); - } - - /** - * @dataProvider provideServersSetting - */ - public function testServersSetting($dsn, $host, $port) - { - $client1 = MemcachedCache::createConnection($dsn); - $client2 = MemcachedCache::createConnection([$dsn]); - $client3 = MemcachedCache::createConnection([[$host, $port]]); - $expect = [ - 'host' => $host, - 'port' => $port, - ]; - - $f = function ($s) { return ['host' => $s['host'], 'port' => $s['port']]; }; - $this->assertSame([$expect], array_map($f, $client1->getServerList())); - $this->assertSame([$expect], array_map($f, $client2->getServerList())); - $this->assertSame([$expect], array_map($f, $client3->getServerList())); - } - - public function provideServersSetting() - { - yield [ - 'memcached://127.0.0.1/50', - '127.0.0.1', - 11211, - ]; - yield [ - 'memcached://localhost:11222?weight=25', - 'localhost', - 11222, - ]; - if (filter_var(ini_get('memcached.use_sasl'), \FILTER_VALIDATE_BOOLEAN)) { - yield [ - 'memcached://user:password@127.0.0.1?weight=50', - '127.0.0.1', - 11211, - ]; - } - yield [ - 'memcached:///var/run/memcached.sock?weight=25', - '/var/run/memcached.sock', - 0, - ]; - yield [ - 'memcached:///var/local/run/memcached.socket?weight=25', - '/var/local/run/memcached.socket', - 0, - ]; - if (filter_var(ini_get('memcached.use_sasl'), \FILTER_VALIDATE_BOOLEAN)) { - yield [ - 'memcached://user:password@/var/local/run/memcached.socket?weight=25', - '/var/local/run/memcached.socket', - 0, - ]; - } - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/MemcachedCacheTextModeTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/MemcachedCacheTextModeTest.php deleted file mode 100644 index 13865a60..00000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/MemcachedCacheTextModeTest.php +++ /dev/null @@ -1,25 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Simple; - -use Symfony\Component\Cache\Adapter\AbstractAdapter; -use Symfony\Component\Cache\Simple\MemcachedCache; - -class MemcachedCacheTextModeTest extends MemcachedCacheTest -{ - public function createSimpleCache($defaultLifetime = 0) - { - $client = AbstractAdapter::createConnection('memcached://'.getenv('MEMCACHED_HOST'), ['binary_protocol' => false]); - - return new MemcachedCache($client, str_replace('\\', '.', __CLASS__), $defaultLifetime); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/NullCacheTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/NullCacheTest.php deleted file mode 100644 index 31f42c32..00000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/NullCacheTest.php +++ /dev/null @@ -1,96 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Simple; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Cache\Simple\NullCache; - -/** - * @group time-sensitive - */ -class NullCacheTest extends TestCase -{ - public function createCachePool() - { - return new NullCache(); - } - - public function testGetItem() - { - $cache = $this->createCachePool(); - - $this->assertNull($cache->get('key')); - } - - public function testHas() - { - $this->assertFalse($this->createCachePool()->has('key')); - } - - public function testGetMultiple() - { - $cache = $this->createCachePool(); - - $keys = ['foo', 'bar', 'baz', 'biz']; - - $default = new \stdClass(); - $items = $cache->getMultiple($keys, $default); - $count = 0; - - foreach ($items as $key => $item) { - $this->assertContains($key, $keys, 'Cache key can not change.'); - $this->assertSame($default, $item); - - // Remove $key for $keys - foreach ($keys as $k => $v) { - if ($v === $key) { - unset($keys[$k]); - } - } - - ++$count; - } - - $this->assertSame(4, $count); - } - - public function testClear() - { - $this->assertTrue($this->createCachePool()->clear()); - } - - public function testDelete() - { - $this->assertTrue($this->createCachePool()->delete('key')); - } - - public function testDeleteMultiple() - { - $this->assertTrue($this->createCachePool()->deleteMultiple(['key', 'foo', 'bar'])); - } - - public function testSet() - { - $cache = $this->createCachePool(); - - $this->assertFalse($cache->set('key', 'val')); - $this->assertNull($cache->get('key')); - } - - public function testSetMultiple() - { - $cache = $this->createCachePool(); - - $this->assertFalse($cache->setMultiple(['key' => 'val'])); - $this->assertNull($cache->get('key')); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/PdoCacheTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/PdoCacheTest.php deleted file mode 100644 index f5a26341..00000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/PdoCacheTest.php +++ /dev/null @@ -1,47 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Simple; - -use Symfony\Component\Cache\Simple\PdoCache; -use Symfony\Component\Cache\Tests\Traits\PdoPruneableTrait; - -/** - * @group time-sensitive - */ -class PdoCacheTest extends CacheTestCase -{ - use PdoPruneableTrait; - - protected static $dbFile; - - public static function setUpBeforeClass() - { - if (!\extension_loaded('pdo_sqlite')) { - self::markTestSkipped('Extension pdo_sqlite required.'); - } - - self::$dbFile = tempnam(sys_get_temp_dir(), 'sf_sqlite_cache'); - - $pool = new PdoCache('sqlite:'.self::$dbFile); - $pool->createTable(); - } - - public static function tearDownAfterClass() - { - @unlink(self::$dbFile); - } - - public function createSimpleCache($defaultLifetime = 0) - { - return new PdoCache('sqlite:'.self::$dbFile, 'ns', $defaultLifetime); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/PdoDbalCacheTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/PdoDbalCacheTest.php deleted file mode 100644 index 4da2b603..00000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/PdoDbalCacheTest.php +++ /dev/null @@ -1,48 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Simple; - -use Doctrine\DBAL\DriverManager; -use Symfony\Component\Cache\Simple\PdoCache; -use Symfony\Component\Cache\Tests\Traits\PdoPruneableTrait; - -/** - * @group time-sensitive - */ -class PdoDbalCacheTest extends CacheTestCase -{ - use PdoPruneableTrait; - - protected static $dbFile; - - public static function setUpBeforeClass() - { - if (!\extension_loaded('pdo_sqlite')) { - self::markTestSkipped('Extension pdo_sqlite required.'); - } - - self::$dbFile = tempnam(sys_get_temp_dir(), 'sf_sqlite_cache'); - - $pool = new PdoCache(DriverManager::getConnection(['driver' => 'pdo_sqlite', 'path' => self::$dbFile])); - $pool->createTable(); - } - - public static function tearDownAfterClass() - { - @unlink(self::$dbFile); - } - - public function createSimpleCache($defaultLifetime = 0) - { - return new PdoCache(DriverManager::getConnection(['driver' => 'pdo_sqlite', 'path' => self::$dbFile]), '', $defaultLifetime); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/PhpArrayCacheTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/PhpArrayCacheTest.php deleted file mode 100644 index bcd7dea5..00000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/PhpArrayCacheTest.php +++ /dev/null @@ -1,145 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Simple; - -use Symfony\Component\Cache\Simple\NullCache; -use Symfony\Component\Cache\Simple\PhpArrayCache; -use Symfony\Component\Cache\Tests\Adapter\FilesystemAdapterTest; - -/** - * @group time-sensitive - */ -class PhpArrayCacheTest extends CacheTestCase -{ - protected $skippedTests = [ - 'testBasicUsageWithLongKey' => 'PhpArrayCache does no writes', - - 'testDelete' => 'PhpArrayCache does no writes', - 'testDeleteMultiple' => 'PhpArrayCache does no writes', - 'testDeleteMultipleGenerator' => 'PhpArrayCache does no writes', - - 'testSetTtl' => 'PhpArrayCache does no expiration', - 'testSetMultipleTtl' => 'PhpArrayCache does no expiration', - 'testSetExpiredTtl' => 'PhpArrayCache does no expiration', - 'testSetMultipleExpiredTtl' => 'PhpArrayCache does no expiration', - - 'testGetInvalidKeys' => 'PhpArrayCache does no validation', - 'testGetMultipleInvalidKeys' => 'PhpArrayCache does no validation', - 'testSetInvalidKeys' => 'PhpArrayCache does no validation', - 'testDeleteInvalidKeys' => 'PhpArrayCache does no validation', - 'testDeleteMultipleInvalidKeys' => 'PhpArrayCache does no validation', - 'testSetInvalidTtl' => 'PhpArrayCache does no validation', - 'testSetMultipleInvalidKeys' => 'PhpArrayCache does no validation', - 'testSetMultipleInvalidTtl' => 'PhpArrayCache does no validation', - 'testHasInvalidKeys' => 'PhpArrayCache does no validation', - 'testSetValidData' => 'PhpArrayCache does no validation', - - 'testDefaultLifeTime' => 'PhpArrayCache does not allow configuring a default lifetime.', - 'testPrune' => 'PhpArrayCache just proxies', - ]; - - protected static $file; - - public static function setUpBeforeClass() - { - self::$file = sys_get_temp_dir().'/symfony-cache/php-array-adapter-test.php'; - } - - protected function tearDown() - { - $this->createSimpleCache()->clear(); - - if (file_exists(sys_get_temp_dir().'/symfony-cache')) { - FilesystemAdapterTest::rmdir(sys_get_temp_dir().'/symfony-cache'); - } - } - - public function createSimpleCache() - { - return new PhpArrayCacheWrapper(self::$file, new NullCache()); - } - - public function testStore() - { - $arrayWithRefs = []; - $arrayWithRefs[0] = 123; - $arrayWithRefs[1] = &$arrayWithRefs[0]; - - $object = (object) [ - 'foo' => 'bar', - 'foo2' => 'bar2', - ]; - - $expected = [ - 'null' => null, - 'serializedString' => serialize($object), - 'arrayWithRefs' => $arrayWithRefs, - 'object' => $object, - 'arrayWithObject' => ['bar' => $object], - ]; - - $cache = new PhpArrayCache(self::$file, new NullCache()); - $cache->warmUp($expected); - - foreach ($expected as $key => $value) { - $this->assertSame(serialize($value), serialize($cache->get($key)), 'Warm up should create a PHP file that OPCache can load in memory'); - } - } - - public function testStoredFile() - { - $expected = [ - 'integer' => 42, - 'float' => 42.42, - 'boolean' => true, - 'array_simple' => ['foo', 'bar'], - 'array_associative' => ['foo' => 'bar', 'foo2' => 'bar2'], - ]; - - $cache = new PhpArrayCache(self::$file, new NullCache()); - $cache->warmUp($expected); - - $values = eval(substr(file_get_contents(self::$file), 6)); - - $this->assertSame($expected, $values, 'Warm up should create a PHP file that OPCache can load in memory'); - } -} - -class PhpArrayCacheWrapper extends PhpArrayCache -{ - public function set($key, $value, $ttl = null) - { - \call_user_func(\Closure::bind(function () use ($key, $value) { - $this->values[$key] = $value; - $this->warmUp($this->values); - $this->values = eval(substr(file_get_contents($this->file), 6)); - }, $this, PhpArrayCache::class)); - - return true; - } - - public function setMultiple($values, $ttl = null) - { - if (!\is_array($values) && !$values instanceof \Traversable) { - return parent::setMultiple($values, $ttl); - } - \call_user_func(\Closure::bind(function () use ($values) { - foreach ($values as $key => $value) { - $this->values[$key] = $value; - } - $this->warmUp($this->values); - $this->values = eval(substr(file_get_contents($this->file), 6)); - }, $this, PhpArrayCache::class)); - - return true; - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/PhpArrayCacheWithFallbackTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/PhpArrayCacheWithFallbackTest.php deleted file mode 100644 index b08c1604..00000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/PhpArrayCacheWithFallbackTest.php +++ /dev/null @@ -1,57 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Simple; - -use Symfony\Component\Cache\Simple\FilesystemCache; -use Symfony\Component\Cache\Simple\PhpArrayCache; -use Symfony\Component\Cache\Tests\Adapter\FilesystemAdapterTest; - -/** - * @group time-sensitive - */ -class PhpArrayCacheWithFallbackTest extends CacheTestCase -{ - protected $skippedTests = [ - 'testGetInvalidKeys' => 'PhpArrayCache does no validation', - 'testGetMultipleInvalidKeys' => 'PhpArrayCache does no validation', - 'testDeleteInvalidKeys' => 'PhpArrayCache does no validation', - 'testDeleteMultipleInvalidKeys' => 'PhpArrayCache does no validation', - //'testSetValidData' => 'PhpArrayCache does no validation', - 'testSetInvalidKeys' => 'PhpArrayCache does no validation', - 'testSetInvalidTtl' => 'PhpArrayCache does no validation', - 'testSetMultipleInvalidKeys' => 'PhpArrayCache does no validation', - 'testSetMultipleInvalidTtl' => 'PhpArrayCache does no validation', - 'testHasInvalidKeys' => 'PhpArrayCache does no validation', - 'testPrune' => 'PhpArrayCache just proxies', - ]; - - protected static $file; - - public static function setUpBeforeClass() - { - self::$file = sys_get_temp_dir().'/symfony-cache/php-array-adapter-test.php'; - } - - protected function tearDown() - { - $this->createSimpleCache()->clear(); - - if (file_exists(sys_get_temp_dir().'/symfony-cache')) { - FilesystemAdapterTest::rmdir(sys_get_temp_dir().'/symfony-cache'); - } - } - - public function createSimpleCache($defaultLifetime = 0) - { - return new PhpArrayCache(self::$file, new FilesystemCache('php-array-fallback', $defaultLifetime)); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/PhpFilesCacheTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/PhpFilesCacheTest.php deleted file mode 100644 index 936f29a4..00000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/PhpFilesCacheTest.php +++ /dev/null @@ -1,42 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Simple; - -use Psr\SimpleCache\CacheInterface; -use Symfony\Component\Cache\Simple\PhpFilesCache; - -/** - * @group time-sensitive - */ -class PhpFilesCacheTest extends CacheTestCase -{ - protected $skippedTests = [ - 'testDefaultLifeTime' => 'PhpFilesCache does not allow configuring a default lifetime.', - ]; - - public function createSimpleCache() - { - if (!PhpFilesCache::isSupported()) { - $this->markTestSkipped('OPcache extension is not enabled.'); - } - - return new PhpFilesCache('sf-cache'); - } - - protected function isPruned(CacheInterface $cache, $name) - { - $getFileMethod = (new \ReflectionObject($cache))->getMethod('getFile'); - $getFileMethod->setAccessible(true); - - return !file_exists($getFileMethod->invoke($cache, $name)); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/Psr6CacheTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/Psr6CacheTest.php deleted file mode 100644 index 1bc75c90..00000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/Psr6CacheTest.php +++ /dev/null @@ -1,30 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Simple; - -use Symfony\Component\Cache\Adapter\FilesystemAdapter; -use Symfony\Component\Cache\Simple\Psr6Cache; - -/** - * @group time-sensitive - */ -class Psr6CacheTest extends CacheTestCase -{ - protected $skippedTests = [ - 'testPrune' => 'Psr6Cache just proxies', - ]; - - public function createSimpleCache($defaultLifetime = 0) - { - return new Psr6Cache(new FilesystemAdapter('', $defaultLifetime)); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/RedisArrayCacheTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/RedisArrayCacheTest.php deleted file mode 100644 index ec5e4c06..00000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/RedisArrayCacheTest.php +++ /dev/null @@ -1,24 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Simple; - -class RedisArrayCacheTest extends AbstractRedisCacheTest -{ - public static function setUpBeforeClass() - { - parent::setupBeforeClass(); - if (!class_exists('RedisArray')) { - self::markTestSkipped('The RedisArray class is required.'); - } - self::$redis = new \RedisArray([getenv('REDIS_HOST')], ['lazy_connect' => true]); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/RedisCacheTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/RedisCacheTest.php deleted file mode 100644 index 8e3f6088..00000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/RedisCacheTest.php +++ /dev/null @@ -1,82 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Simple; - -use Symfony\Component\Cache\Simple\RedisCache; - -class RedisCacheTest extends AbstractRedisCacheTest -{ - public static function setUpBeforeClass() - { - parent::setupBeforeClass(); - self::$redis = RedisCache::createConnection('redis://'.getenv('REDIS_HOST')); - } - - public function testCreateConnection() - { - $redisHost = getenv('REDIS_HOST'); - - $redis = RedisCache::createConnection('redis://'.$redisHost); - $this->assertInstanceOf(\Redis::class, $redis); - $this->assertTrue($redis->isConnected()); - $this->assertSame(0, $redis->getDbNum()); - - $redis = RedisCache::createConnection('redis://'.$redisHost.'/2'); - $this->assertSame(2, $redis->getDbNum()); - - $redis = RedisCache::createConnection('redis://'.$redisHost, ['timeout' => 3]); - $this->assertEquals(3, $redis->getTimeout()); - - $redis = RedisCache::createConnection('redis://'.$redisHost.'?timeout=4'); - $this->assertEquals(4, $redis->getTimeout()); - - $redis = RedisCache::createConnection('redis://'.$redisHost, ['read_timeout' => 5]); - $this->assertEquals(5, $redis->getReadTimeout()); - } - - /** - * @dataProvider provideFailedCreateConnection - */ - public function testFailedCreateConnection($dsn) - { - $this->expectException('Symfony\Component\Cache\Exception\InvalidArgumentException'); - $this->expectExceptionMessage('Redis connection '); - RedisCache::createConnection($dsn); - } - - public function provideFailedCreateConnection() - { - return [ - ['redis://localhost:1234'], - ['redis://foo@localhost'], - ['redis://localhost/123'], - ]; - } - - /** - * @dataProvider provideInvalidCreateConnection - */ - public function testInvalidCreateConnection($dsn) - { - $this->expectException('Symfony\Component\Cache\Exception\InvalidArgumentException'); - $this->expectExceptionMessage('Invalid Redis DSN'); - RedisCache::createConnection($dsn); - } - - public function provideInvalidCreateConnection() - { - return [ - ['foo://localhost'], - ['redis://'], - ]; - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/RedisClusterCacheTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/RedisClusterCacheTest.php deleted file mode 100644 index 6b7f8039..00000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/RedisClusterCacheTest.php +++ /dev/null @@ -1,27 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Simple; - -class RedisClusterCacheTest extends AbstractRedisCacheTest -{ - public static function setUpBeforeClass() - { - if (!class_exists('RedisCluster')) { - self::markTestSkipped('The RedisCluster class is required.'); - } - if (!$hosts = getenv('REDIS_CLUSTER_HOSTS')) { - self::markTestSkipped('REDIS_CLUSTER_HOSTS env var is not defined.'); - } - - self::$redis = new \RedisCluster(null, explode(' ', $hosts)); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/TraceableCacheTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/TraceableCacheTest.php deleted file mode 100644 index e684caf3..00000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/TraceableCacheTest.php +++ /dev/null @@ -1,171 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Simple; - -use Symfony\Component\Cache\Simple\FilesystemCache; -use Symfony\Component\Cache\Simple\TraceableCache; - -/** - * @group time-sensitive - */ -class TraceableCacheTest extends CacheTestCase -{ - protected $skippedTests = [ - 'testPrune' => 'TraceableCache just proxies', - ]; - - public function createSimpleCache($defaultLifetime = 0) - { - return new TraceableCache(new FilesystemCache('', $defaultLifetime)); - } - - public function testGetMissTrace() - { - $pool = $this->createSimpleCache(); - $pool->get('k'); - $calls = $pool->getCalls(); - $this->assertCount(1, $calls); - - $call = $calls[0]; - $this->assertSame('get', $call->name); - $this->assertSame(['k' => false], $call->result); - $this->assertSame(0, $call->hits); - $this->assertSame(1, $call->misses); - $this->assertNotEmpty($call->start); - $this->assertNotEmpty($call->end); - } - - public function testGetHitTrace() - { - $pool = $this->createSimpleCache(); - $pool->set('k', 'foo'); - $pool->get('k'); - $calls = $pool->getCalls(); - $this->assertCount(2, $calls); - - $call = $calls[1]; - $this->assertSame(1, $call->hits); - $this->assertSame(0, $call->misses); - } - - public function testGetMultipleMissTrace() - { - $pool = $this->createSimpleCache(); - $pool->set('k1', 123); - $values = $pool->getMultiple(['k0', 'k1']); - foreach ($values as $value) { - } - $calls = $pool->getCalls(); - $this->assertCount(2, $calls); - - $call = $calls[1]; - $this->assertSame('getMultiple', $call->name); - $this->assertSame(['k1' => true, 'k0' => false], $call->result); - $this->assertSame(1, $call->misses); - $this->assertNotEmpty($call->start); - $this->assertNotEmpty($call->end); - } - - public function testHasMissTrace() - { - $pool = $this->createSimpleCache(); - $pool->has('k'); - $calls = $pool->getCalls(); - $this->assertCount(1, $calls); - - $call = $calls[0]; - $this->assertSame('has', $call->name); - $this->assertSame(['k' => false], $call->result); - $this->assertNotEmpty($call->start); - $this->assertNotEmpty($call->end); - } - - public function testHasHitTrace() - { - $pool = $this->createSimpleCache(); - $pool->set('k', 'foo'); - $pool->has('k'); - $calls = $pool->getCalls(); - $this->assertCount(2, $calls); - - $call = $calls[1]; - $this->assertSame('has', $call->name); - $this->assertSame(['k' => true], $call->result); - $this->assertNotEmpty($call->start); - $this->assertNotEmpty($call->end); - } - - public function testDeleteTrace() - { - $pool = $this->createSimpleCache(); - $pool->delete('k'); - $calls = $pool->getCalls(); - $this->assertCount(1, $calls); - - $call = $calls[0]; - $this->assertSame('delete', $call->name); - $this->assertSame(['k' => true], $call->result); - $this->assertSame(0, $call->hits); - $this->assertSame(0, $call->misses); - $this->assertNotEmpty($call->start); - $this->assertNotEmpty($call->end); - } - - public function testDeleteMultipleTrace() - { - $pool = $this->createSimpleCache(); - $arg = ['k0', 'k1']; - $pool->deleteMultiple($arg); - $calls = $pool->getCalls(); - $this->assertCount(1, $calls); - - $call = $calls[0]; - $this->assertSame('deleteMultiple', $call->name); - $this->assertSame(['keys' => $arg, 'result' => true], $call->result); - $this->assertSame(0, $call->hits); - $this->assertSame(0, $call->misses); - $this->assertNotEmpty($call->start); - $this->assertNotEmpty($call->end); - } - - public function testTraceSetTrace() - { - $pool = $this->createSimpleCache(); - $pool->set('k', 'foo'); - $calls = $pool->getCalls(); - $this->assertCount(1, $calls); - - $call = $calls[0]; - $this->assertSame('set', $call->name); - $this->assertSame(['k' => true], $call->result); - $this->assertSame(0, $call->hits); - $this->assertSame(0, $call->misses); - $this->assertNotEmpty($call->start); - $this->assertNotEmpty($call->end); - } - - public function testSetMultipleTrace() - { - $pool = $this->createSimpleCache(); - $pool->setMultiple(['k' => 'foo']); - $calls = $pool->getCalls(); - $this->assertCount(1, $calls); - - $call = $calls[0]; - $this->assertSame('setMultiple', $call->name); - $this->assertSame(['keys' => ['k'], 'result' => true], $call->result); - $this->assertSame(0, $call->hits); - $this->assertSame(0, $call->misses); - $this->assertNotEmpty($call->start); - $this->assertNotEmpty($call->end); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Traits/PdoPruneableTrait.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Traits/PdoPruneableTrait.php deleted file mode 100644 index c405de70..00000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Traits/PdoPruneableTrait.php +++ /dev/null @@ -1,34 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Traits; - -trait PdoPruneableTrait -{ - protected function isPruned($cache, $name) - { - $o = new \ReflectionObject($cache); - - if (!$o->hasMethod('getConnection')) { - self::fail('Cache does not have "getConnection()" method.'); - } - - $getPdoConn = $o->getMethod('getConnection'); - $getPdoConn->setAccessible(true); - - /** @var \Doctrine\DBAL\Statement|\PDOStatement $select */ - $select = $getPdoConn->invoke($cache)->prepare('SELECT 1 FROM cache_items WHERE item_id LIKE :id'); - $select->bindValue(':id', sprintf('%%%s', $name)); - $result = $select->execute(); - - return 1 !== (int) (\is_object($result) ? $result->fetchOne() : $select->fetch(\PDO::FETCH_COLUMN)); - } -} 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/cache/phpunit.xml.dist b/advancedcontentfilter/vendor/symfony/cache/phpunit.xml.dist deleted file mode 100644 index c35458ca..00000000 --- a/advancedcontentfilter/vendor/symfony/cache/phpunit.xml.dist +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - ./Tests/ - - - - - - ./ - - ./Tests - ./vendor - - - - - - - - - - - Cache\IntegrationTests - Doctrine\Common\Cache - Symfony\Component\Cache - Symfony\Component\Cache\Tests\Fixtures - Symfony\Component\Cache\Traits - - - - - - - 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-apcu/Apcu.php b/advancedcontentfilter/vendor/symfony/polyfill-apcu/Apcu.php deleted file mode 100644 index 4dc5bf9a..00000000 --- a/advancedcontentfilter/vendor/symfony/polyfill-apcu/Apcu.php +++ /dev/null @@ -1,106 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Polyfill\Apcu; - -/** - * Apcu for Zend Server Data Cache. - * - * @author Kate Gray - * @author Nicolas Grekas - * - * @internal - */ -final class Apcu -{ - public static function apcu_add($key, $var = null, $ttl = 0) - { - if (!\is_array($key)) { - return apc_add($key, $var, $ttl); - } - - $errors = []; - foreach ($key as $k => $v) { - if (!apc_add($k, $v, $ttl)) { - $errors[$k] = -1; - } - } - - return $errors; - } - - public static function apcu_store($key, $var = null, $ttl = 0) - { - if (!\is_array($key)) { - return apc_store($key, $var, $ttl); - } - - $errors = []; - foreach ($key as $k => $v) { - if (!apc_store($k, $v, $ttl)) { - $errors[$k] = -1; - } - } - - return $errors; - } - - public static function apcu_exists($keys) - { - if (!\is_array($keys)) { - return apc_exists($keys); - } - - $existing = []; - foreach ($keys as $k) { - if (apc_exists($k)) { - $existing[$k] = true; - } - } - - return $existing; - } - - public static function apcu_fetch($key, &$success = null) - { - if (!\is_array($key)) { - return apc_fetch($key, $success); - } - - $succeeded = true; - $values = []; - foreach ($key as $k) { - $v = apc_fetch($k, $success); - if ($success) { - $values[$k] = $v; - } else { - $succeeded = false; - } - } - $success = $succeeded; - - return $values; - } - - public static function apcu_delete($key) - { - if (!\is_array($key)) { - return apc_delete($key); - } - - $success = true; - foreach ($key as $k) { - $success = apc_delete($k) && $success; - } - - return $success; - } -} diff --git a/advancedcontentfilter/vendor/symfony/polyfill-apcu/README.md b/advancedcontentfilter/vendor/symfony/polyfill-apcu/README.md deleted file mode 100644 index 57f4bf6b..00000000 --- a/advancedcontentfilter/vendor/symfony/polyfill-apcu/README.md +++ /dev/null @@ -1,12 +0,0 @@ -Symfony Polyfill / APCu -======================== - -This component provides `apcu_*` functions and the `APCuIterator` class to users of the legacy APC extension. - -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-apcu/bootstrap.php b/advancedcontentfilter/vendor/symfony/polyfill-apcu/bootstrap.php deleted file mode 100644 index 96b2706a..00000000 --- a/advancedcontentfilter/vendor/symfony/polyfill-apcu/bootstrap.php +++ /dev/null @@ -1,83 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -use Symfony\Polyfill\Apcu as p; - -if (!extension_loaded('apc') && !extension_loaded('apcu')) { - return; -} - -if (\PHP_VERSION_ID >= 80000) { - return require __DIR__.'/bootstrap80.php'; -} - -if (extension_loaded('Zend Data Cache')) { - if (!function_exists('apcu_add')) { - function apcu_add($key, $value = null, $ttl = 0) { return p\Apcu::apcu_add($key, $value, $ttl); } - } - if (!function_exists('apcu_delete')) { - function apcu_delete($key) { return p\Apcu::apcu_delete($key); } - } - if (!function_exists('apcu_exists')) { - function apcu_exists($key) { return p\Apcu::apcu_exists($key); } - } - if (!function_exists('apcu_fetch')) { - function apcu_fetch($key, &$success = null) { return p\Apcu::apcu_fetch($key, $success); } - } - if (!function_exists('apcu_store')) { - function apcu_store($key, $value = null, $ttl = 0) { return p\Apcu::apcu_store($key, $value, $ttl); } - } -} else { - if (!function_exists('apcu_add')) { - function apcu_add($key, $value = null, $ttl = 0) { return apc_add($key, $value, $ttl); } - } - if (!function_exists('apcu_delete')) { - function apcu_delete($key) { return apc_delete($key); } - } - if (!function_exists('apcu_exists')) { - function apcu_exists($key) { return apc_exists($key); } - } - if (!function_exists('apcu_fetch')) { - function apcu_fetch($key, &$success = null) { return apc_fetch($key, $success); } - } - if (!function_exists('apcu_store')) { - function apcu_store($key, $value = null, $ttl = 0) { return apc_store($key, $value, $ttl); } - } -} - -if (!function_exists('apcu_cache_info')) { - function apcu_cache_info($limited = false) { return apc_cache_info('user', $limited); } -} -if (!function_exists('apcu_cas')) { - function apcu_cas($key, $old, $new) { return apc_cas($key, $old, $new); } -} -if (!function_exists('apcu_clear_cache')) { - function apcu_clear_cache() { return apc_clear_cache('user'); } -} -if (!function_exists('apcu_dec')) { - function apcu_dec($key, $step = 1, &$success = false) { return apc_dec($key, $step, $success); } -} -if (!function_exists('apcu_inc')) { - function apcu_inc($key, $step = 1, &$success = false) { return apc_inc($key, $step, $success); } -} -if (!function_exists('apcu_sma_info')) { - function apcu_sma_info($limited = false) { return apc_sma_info($limited); } -} - -if (!class_exists('APCuIterator', false) && class_exists('APCIterator', false)) { - class APCuIterator extends APCIterator - { - public function __construct($search = null, $format = \APC_ITER_ALL, $chunk_size = 100, $list = \APC_LIST_ACTIVE) - { - parent::__construct('user', $search, $format, $chunk_size, $list); - } - } -} diff --git a/advancedcontentfilter/vendor/symfony/polyfill-apcu/bootstrap80.php b/advancedcontentfilter/vendor/symfony/polyfill-apcu/bootstrap80.php deleted file mode 100644 index 69e9f160..00000000 --- a/advancedcontentfilter/vendor/symfony/polyfill-apcu/bootstrap80.php +++ /dev/null @@ -1,75 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -use Symfony\Polyfill\Apcu as p; - -if (extension_loaded('Zend Data Cache')) { - if (!function_exists('apcu_add')) { - function apcu_add($key, mixed $value, ?int $ttl = 0): array|bool { return p\Apcu::apcu_add($key, $value, (int) $ttl); } - } - if (!function_exists('apcu_delete')) { - function apcu_delete($key): array|bool { return p\Apcu::apcu_delete($key); } - } - if (!function_exists('apcu_exists')) { - function apcu_exists($key): array|bool { return p\Apcu::apcu_exists($key); } - } - if (!function_exists('apcu_fetch')) { - function apcu_fetch($key, &$success = null): mixed { return p\Apcu::apcu_fetch($key, $success); } - } - if (!function_exists('apcu_store')) { - function apcu_store($key, mixed $value, ?int $ttl = 0): array|bool { return p\Apcu::apcu_store($key, $value, (int) $ttl); } - } -} else { - if (!function_exists('apcu_add')) { - function apcu_add($key, mixed $value, ?int $ttl = 0): array|bool { return apc_add($key, $value, (int) $ttl); } - } - if (!function_exists('apcu_delete')) { - function apcu_delete($key): array|bool { return apc_delete($key); } - } - if (!function_exists('apcu_exists')) { - function apcu_exists($key): array|bool { return apc_exists($key); } - } - if (!function_exists('apcu_fetch')) { - function apcu_fetch($key, &$success = null) { return apc_fetch($key, $success); } - } - if (!function_exists('apcu_store')) { - function apcu_store($key, mixed $value, ?int $ttl = 0): array|bool { return apc_store($key, $value, (int) $ttl); } - } -} - -if (!function_exists('apcu_cache_info')) { - function apcu_cache_info($limited = false) { return apc_cache_info('user', $limited); } -} -if (!function_exists('apcu_cas')) { - function apcu_cas($key, $old, $new) { return apc_cas($key, $old, $new); } -} -if (!function_exists('apcu_clear_cache')) { - function apcu_clear_cache() { return apc_clear_cache('user'); } -} -if (!function_exists('apcu_dec')) { - function apcu_dec($key, $step = 1, &$success = false) { return apc_dec($key, $step, $success); } -} -if (!function_exists('apcu_inc')) { - function apcu_inc($key, $step = 1, &$success = false) { return apc_inc($key, $step, $success); } -} -if (!function_exists('apcu_sma_info')) { - function apcu_sma_info($limited = false) { return apc_sma_info($limited); } -} - -if (!class_exists('APCuIterator', false) && class_exists('APCIterator', false)) { - class APCuIterator extends APCIterator - { - public function __construct($search = null, $format = APC_ITER_ALL, $chunk_size = 100, $list = APC_LIST_ACTIVE) - { - parent::__construct('user', $search, $format, $chunk_size, $list); - } - } -} 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-apcu/composer.json b/advancedcontentfilter/vendor/symfony/polyfill-php73/composer.json similarity index 68% rename from advancedcontentfilter/vendor/symfony/polyfill-apcu/composer.json rename to advancedcontentfilter/vendor/symfony/polyfill-php73/composer.json index e92524f3..3d47d154 100644 --- a/advancedcontentfilter/vendor/symfony/polyfill-apcu/composer.json +++ b/advancedcontentfilter/vendor/symfony/polyfill-php73/composer.json @@ -1,8 +1,8 @@ { - "name": "symfony/polyfill-apcu", + "name": "symfony/polyfill-php73", "type": "library", - "description": "Symfony polyfill backporting apcu_* functions to lower PHP versions", - "keywords": ["polyfill", "shim", "compatibility", "portable", "apcu"], + "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": [ @@ -19,14 +19,12 @@ "php": ">=7.1" }, "autoload": { - "psr-4": { "Symfony\\Polyfill\\Apcu\\": "" }, - "files": [ "bootstrap.php" ] + "psr-4": { "Symfony\\Polyfill\\Php73\\": "" }, + "files": [ "bootstrap.php" ], + "classmap": [ "Resources/stubs" ] }, "minimum-stability": "dev", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "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" +} diff --git a/birdavatar/birdavatar.php b/birdavatar/birdavatar.php index 4841ba52..cd49b183 100644 --- a/birdavatar/birdavatar.php +++ b/birdavatar/birdavatar.php @@ -6,9 +6,7 @@ * Author: Fabio */ -use Friendica\App; use Friendica\Core\Hook; -use Friendica\Core\Logger; use Friendica\Core\Renderer; use Friendica\Database\DBA; use Friendica\DI; @@ -28,7 +26,7 @@ function birdavatar_install() Hook::register('addon_settings', __FILE__, 'birdavatar_addon_settings'); Hook::register('addon_settings_post', __FILE__, 'birdavatar_addon_settings_post'); - Logger::info('registered birdavatar'); + DI::logger()->info('registered birdavatar'); } /** diff --git a/blackout/blackout.php b/blackout/blackout.php index 55fb8d32..ac1ee3e6 100644 --- a/blackout/blackout.php +++ b/blackout/blackout.php @@ -44,9 +44,7 @@ * THE SOFTWARE. */ -use Friendica\App; use Friendica\Core\Hook; -use Friendica\Core\Logger; use Friendica\Core\Renderer; use Friendica\Core\System; use Friendica\DI; @@ -78,7 +76,7 @@ function blackout_redirect ($b) } if (( $date1 <= $now ) && ( $now <= $date2 )) { - Logger::notice('redirecting user to blackout page'); + DI::logger()->notice('redirecting user to blackout page'); System::externalRedirect($myurl); } } diff --git a/blockbot/blockbot.php b/blockbot/blockbot.php index e11f23f7..71e35c93 100644 --- a/blockbot/blockbot.php +++ b/blockbot/blockbot.php @@ -2,7 +2,7 @@ /** * Name: blockbot * Description: Blocking bots based on detecting bots/crawlers/spiders via the user agent and http_from header. - * Version: 0.2 + * Version: 1.0 * Author: Philipp Holzer * Author: Michael Vogel * @@ -11,9 +11,11 @@ use Friendica\Core\Hook; use Friendica\DI; use Jaybizzle\CrawlerDetect\CrawlerDetect; -use Friendica\Core\Logger; use Friendica\Core\Renderer; +use Friendica\Core\System; use Friendica\Network\HTTPException\ForbiddenException; +use Friendica\Util\HTTPSignature; +use Friendica\Util\Network; require_once __DIR__ . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php'; @@ -28,115 +30,127 @@ function blockbot_addon_admin(string &$o) $o = Renderer::replaceMacros($t, [ '$submit' => DI::l10n()->t('Save Settings'), - '$good_crawlers' => ['good_crawlers', DI::l10n()->t('Allow "good" crawlers'), DI::config()->get('blockbot', 'good_crawlers'), DI::l10n()->t("Don't block fediverse crawlers, relay servers and other bots with good purposes.")], - '$socialmedia_agents' => ['socialmedia_agents', DI::l10n()->t('Allow preview agents'), DI::config()->get('blockbot', 'socialmedia_agents'), DI::l10n()->t("Don't block agents from social media systems that want to generate preview data for links that had been set by their users.")], + '$security_checker' => ['security_checker', DI::l10n()->t('Allow security checkers'), DI::config()->get('blockbot', 'security_checker'), DI::l10n()->t("Don't block security checkers. They can be used for good or bad.")], '$http_libraries' => ['http_libraries', DI::l10n()->t('Allow generic HTTP libraries'), DI::config()->get('blockbot', 'http_libraries'), DI::l10n()->t("Don't block agents from generic HTTP libraries that could be used for good or for bad and that currently can't be traced back to any known Fediverse project.")], - '$block_gab' => ['block_gab', DI::l10n()->t('Block GabSocial'), DI::config()->get('blockbot', 'block_gab'), DI::l10n()->t('Block the software GabSocial. This will block every access for that software. You can block dedicated gab instances in the blocklist settings in the admin section.')], '$training' => ['training', DI::l10n()->t('Training mode'), DI::config()->get('blockbot', 'training'), DI::l10n()->t("Activates the training mode. This is only meant for developing purposes. Don't activate this on a production machine. This can cut communication with some systems.")], ]); } function blockbot_addon_admin_post() { - DI::config()->set('blockbot', 'good_crawlers', $_POST['good_crawlers'] ?? false); - DI::config()->set('blockbot', 'socialmedia_agents', $_POST['socialmedia_agents'] ?? false); + DI::config()->set('blockbot', 'security_checker', $_POST['security_checker'] ?? false); DI::config()->set('blockbot', 'http_libraries', $_POST['http_libraries'] ?? false); - DI::config()->set('blockbot', 'block_gab', $_POST['block_gab'] ?? false); DI::config()->set('blockbot', 'training', $_POST['training'] ?? false); } +function blockbot_reject() +{ + throw new ForbiddenException('Bots are not allowed. If you consider this a mistake, create an issue at https://github.com/friendica/friendica'); +} + function blockbot_init_1() { if (empty($_SERVER['HTTP_USER_AGENT'])) { return; } - $logdata = ['agent' => $_SERVER['HTTP_USER_AGENT'], 'uri' => $_SERVER['REQUEST_URI']]; + $crawlerDetect = new CrawlerDetect(); - // List of known unwanted crawlers. - $agents = [ - 'SemrushBot', 's~feedly-nikon3', 'Qwantify/Bleriot/', 'ltx71', 'Sogou web spider/', - 'Diffbot/', 'YisouSpider', 'evc-batch/', 'LivelapBot/', 'TrendsmapResolver/', - 'PaperLiBot/', 'Nuzzel', 'um-LN/', 'Google Favicon', 'Datanyze', 'BLEXBot/', '360Spider', - 'adscanner/', 'HeadlessChrome', 'wpif', 'startmebot/', 'Googlebot/', 'Applebot/', - 'GoogleImageProxy', 'bingbot/', 'heritrix/', 'ldspider', - 'AwarioRssBot/', 'TweetmemeBot/', 'dcrawl/', 'PhantomJS/', 'Googlebot-Image/', - 'CrowdTanglebot/', 'Mediapartners-Google', 'Baiduspider', 'datagnionbot', - 'MegaIndex.ru/', 'SMUrlExpander', 'Hatena-Favicon/', 'Wappalyzer', 'FlipboardProxy/', - 'NetcraftSurveyAgent/', 'Dataprovider.com', 'SMTBot/', 'Nimbostratus-Bot/', - 'DuckDuckGo-Favicons-Bot/', 'IndieWebCards/', 'proximic', 'netEstate NE Crawler', - 'AhrefsBot/', 'YandexBot/', 'Exabot/', 'Mediumbot-MetaTagFetcher/', - 'SurdotlyBot/', 'BingPreview/', 'SabsimBot/', 'CCBot/', 'WbSrch/', - 'DuckDuckBot-Https/', 'HTTP Banner Detection', 'YandexImages/', 'archive.org_bot', - 'ArchiveTeam ArchiveBot/', 'yacybot', 'https://developers.google.com/+/web/snippet/', - 'Scrapy/', 'MJ12bot/', 'DotBot/', 'Pinterestbot/', 'Jooblebot/', - 'Cliqzbot/', 'YaK/', 'Mediatoolkitbot', 'Snacktory', 'FunWebProducts', 'oBot/', - '7Siters/', 'KOCMOHABT', 'Google-SearchByImage', 'FemtosearchBot/', - 'HubSpot Crawler', 'DomainStatsBot/', 'Re-re Studio', 'AwarioSmartBot/', - 'DNSResearchBot/', 'PetalBot;', 'Nmap Scripting Engine;', - 'Google-Apps-Script; beanserver;', 'woorankreview/', 'Seekport Crawler;', 'AHC/', - 'Semanticbot/', 'XoviOnpageCrawler;', 'Pinterest/', - 'GetHPinfo.com-Bot/', 'BoardReader Favicon Fetcher', 'Google-Adwords-Instant', 'newspaper/', - 'YurichevBot/', 'Crawling at Home Project', 'InfoTigerBot/', 'AdIdxBot/', - 'MicrosoftPreview/', 'masscan/', 'Timpibot/', 'everyfeed-spider/', 'AndroidDownloadManager/', - 'WebZIP/', 'WDG_Validator/', 'Screaming Frog SEO Spider/', ' Bytespider;', 'ISSCyberRiskCrawler/', - 'BitSightBot/', 'ev-crawler/', 'CensysInspect/1.1', 'Protopage/', 'Gaisbot/', 'WellKnownBot/', - 'SuperBot/', 'Googlebot-Mobile/', 'GPTBot/', 'GenomeCrawlerd/', '2ip bot/', 'Ocarinabot', - 'Yahoo! Slurp;', 'AdsBot-Google', 'Gregarius/', 'FAST-WebCrawler/', 'Xenu Link Sleuth/', - 'Ask Jeeves', 'alexa site audit/', 'Yahoo! Slurp China;', 'Microsoft URL Control', - 'Facebot', 'Googlebot-Video/', 'msnbot/', 'Offline Explorer/', 'YandexNews/', 'msnbot-media/', - 'EmailWolf', 'Download Demon/', 'FeedFetcher-Google;', 'WebCopier', '+ONB_Bot_Btrix', - 'scoopit-crawler/', 'ia_archiver', 'Quora-Bot/', 'WebwikiBot/', 'FullStoryBot/', - 'wpbot/', 'SearchExpress', 'DuckDuckBot/', 'Google Web Preview', - ]; + $isCrawler = $crawlerDetect->isCrawler(); - if (DI::config()->get('blockbot', 'block_gab')) { - $agents[] = 'GabSocial/'; + blockbot_save('all-agents', $_SERVER['HTTP_USER_AGENT']); + + $parts = blockbot_get_parts($_SERVER['HTTP_USER_AGENT']); + + $logdata = ['isCrawler' => $isCrawler, 'agent' => $_SERVER['HTTP_USER_AGENT'], 'method' => $_SERVER['REQUEST_METHOD'], 'uri' => $_SERVER['REQUEST_URI'], 'parts' => $parts]; + + if ($isCrawler) { + blockbot_check_login_attempt($_SERVER['REQUEST_URI'], $logdata); } - // List of "good" crawlers, mostly from the fediverse. - $good_agents = [ - 'fediverse.space crawler', 'fediverse.network crawler', 'Active_Pods_CheckBot_3.0', - 'Social-Relay/', 'Test Certificate Info', 'Uptimebot/', 'GNUSocialBot', 'UptimeRobot/', - 'PTST/', 'Zabbix', 'Poduptime/', 'FediFetcher', 'lemmy-stats-crawler', - 'FedditLemmyverseCrawler/', 'lemmy-explorer-crawler/', 'URIports Validator', - 'rss-is-dead.lol web bot;', 'fedistatsCrawler/', 'W3C_CSS_Validator_JFouffa/', - 'IABot/', 'Slackbot 1', 'BeeperBot/', 'Matrix-Media-Repo/', 'P3P Validator', - 'KeybaseBot;', - ]; - - if (!DI::config()->get('blockbot', 'good_crawlers')) { - $agents = array_merge($agents, $good_agents); - } elseif (blockbot_match($good_agents)) { + if (empty($parts)) { + DI::logger()->debug('Known frontend found - accept', $logdata); + if ($isCrawler) { + blockbot_save('badly-parsed-agents', $_SERVER['HTTP_USER_AGENT']); + } return; } - // List of agents from social media systems that fetch preview data via opem graph or twitter cards. - $socialmedia_agents = ['Twitterbot', 'facebookexternalhit/', 'SkypeUriPreview Preview/', - 'TelegramBot', 'WhatsApp/', 'github-camo', 'Bluesky Cardyb/', 'XING-contenttabreceiver/', - 'LinkedInBot/', 'Instagram ', 'Synapse (bot; ', 'Discordbot/', 'SummalyBot/', - 'Slackbot-LinkExpanding', 'Slack-ImgProxy', 'Iframely/', - ]; + blockbot_log_activitypub($_SERVER['REQUEST_URI'], $_SERVER['HTTP_USER_AGENT']); - if (!DI::config()->get('blockbot', 'socialmedia_agents')) { - $agents = array_merge($agents, $socialmedia_agents); - } elseif (blockbot_match($socialmedia_agents)) { - return; + if (blockbot_is_crawler($parts)) { + DI::logger()->debug('Crawler found - reject', $logdata); + blockbot_reject(); } - - // HTTP Libraries - $http_libraries = ['ReactorNetty/', 'GuzzleHttp/', 'Embed PHP library', 'python-urllib3/', - 'EventMachine HttpClient', 'HTMLParser/' - ]; - if (!DI::config()->get('blockbot', 'http_libraries')) { - $agents = array_merge($agents, $http_libraries); - } elseif (blockbot_match($http_libraries)) { + if (blockbot_is_searchbot($parts)) { + DI::logger()->debug('Search bot found - reject', $logdata); + blockbot_reject(); + } + + if (blockbot_is_unwanted($parts)) { + DI::logger()->debug('Uncategorized unwanted agent found - reject', $logdata); + blockbot_reject(); + } + + if (blockbot_is_security_checker($parts)) { + if (!DI::config()->get('blockbot', 'security_checker')) { + DI::logger()->debug('Security checker found - reject', $logdata); + blockbot_reject(); + } + DI::logger()->debug('Security checker found - accept', $logdata); return; } - if (blockbot_match($agents)) { - throw new ForbiddenException('Bots are not allowed. If you consider this a mistake, create an issue at https://github.com/friendica/friendica'); + if (blockbot_is_social_media($parts)) { + DI::logger()->debug('Social media service found - accept', $logdata); + return; + } + + if (blockbot_is_fediverse_client($parts)) { + DI::logger()->debug('Fediverse client found - accept', $logdata); + return; + } + + if (blockbot_is_feed_reader($parts)) { + DI::logger()->debug('Feed reader found - accept', $logdata); + return; + } + + if (blockbot_is_fediverse_tool($parts)) { + DI::logger()->debug('Fediverse tool found - accept', $logdata); + return; + } + + if (blockbot_is_service_agent($parts)) { + DI::logger()->debug('Service agent found - accept', $logdata); + return; + } + + if (blockbot_is_monitor($parts)) { + DI::logger()->debug('Monitoring service found - accept', $logdata); + return; + } + + if (blockbot_is_validator($parts)) { + DI::logger()->debug('Validation service found - accept', $logdata); + return; + } + + if (blockbot_is_good_tool($parts)) { + DI::logger()->debug('Uncategorized helpful service found - accept', $logdata); + return; + } + + // Needs to be checked at the end, since other services might use these libraries + if (blockbot_is_http_library($parts)) { + blockbot_check_login_attempt($_SERVER['REQUEST_URI'], $logdata); + if (!DI::config()->get('blockbot', 'http_libraries')) { + DI::logger()->debug('HTTP Library found - reject', $logdata); + blockbot_reject(); + } + DI::logger()->debug('HTTP Library found - accept', $logdata); + return; } // This switch here is only meant for developers who want to add more bots to the list above, it is not safe for production. @@ -144,44 +158,684 @@ function blockbot_init_1() return; } - $crawlerDetect = new CrawlerDetect(); - - if (!$crawlerDetect->isCrawler()) { - logger::debug('Good user agent detected', $logdata); + if (!$isCrawler) { + blockbot_save('good-agents', $_SERVER['HTTP_USER_AGENT']); + DI::logger()->debug('Non-bot user agent detected', $logdata); return; } - // List of known "good" agents, mostly used by Fediverse systems, feed readers, ... - $agents = [ - 'curl', 'zgrab', 'Go-http-client', 'curb', 'github.com', 'reqwest', 'Feedly/', - 'Python-urllib/', 'Liferea/', 'aiohttp/', 'WordPress.com Reader', 'hackney/', - 'Faraday v', 'okhttp', 'UniversalFeedParser', 'PixelFedBot', 'python-requests', - 'WordPress/', 'http.rb/', 'Apache-HttpClient/', 'WordPress.com;', 'Pleroma', - 'Dispatch/', 'Ruby', 'Java/', 'libwww-perl/', 'Mastodon/', 'FeedlyApp/', - 'lua-resty-http/', 'Tiny Tiny RSS/', 'Wget/', 'PostmanRuntime/', - 'W3C_Validator/', 'NetNewsWire', 'FeedValidator/', 'theoldreader.com', 'axios/', - 'Paw/', 'PeerTube/', 'fedi.inex.dev', 'FediDB/', 'index.community crawler', - 'Slackbot-LinkExpanding', 'Firefish/', 'Takahe/', 'Akkoma ', 'Misskey/', 'Lynx/', - 'camo-rs asset proxy', 'gotosocial/', 'incestoma ', 'SpaceCowboys Android RSS Reader', - 'NewsBlur Feed Finder', 'Lemmy/', 'enby-town/', 'rss2tg bot;', '; HTTrack ', - 'MbinBot', 'kbinBot', 'Pixelfed/', 'NewsBlur Feed Fetcher', 'NewsBlur Page Fetcher', - ]; - - if (blockbot_match($agents)) { - logger::info('False positive', $logdata); - return; - } - - logger::notice('Blocked bot', $logdata); - throw new ForbiddenException('Bots are not allowed. If you consider this a mistake, create an issue at https://github.com/friendica/friendica'); + blockbot_save('bad-agents', $_SERVER['HTTP_USER_AGENT']); + DI::logger()->notice('Possible bot found - reject', $logdata); + blockbot_reject(); } -function blockbot_match(array $agents) +function blockbot_save($database, $userAgent) { - foreach ($agents as $agent) { - if (stristr($_SERVER['HTTP_USER_AGENT'], $agent)) { + if (!DI::config()->get('blockbot', 'logging') || !function_exists('dba_open')) { + return; + } + + $resource = dba_open(System::getTempPath() . '/' . $database, 'cl'); + $result = dba_fetch($userAgent, $resource); + if ($result === false) { + dba_insert($userAgent, true, $resource); + } + dba_close($resource); +} + +function blockbot_log_activitypub(string $url, string $agent) +{ + if (!DI::config()->get('blockbot', 'logging')) { + return; + } + + $bot = ['/.well-known/nodeinfo', '/nodeinfo/2.0', '/nodeinfo/1.0']; + if (in_array($url, $bot)) { + blockbot_save('activitypub-stats', $agent); + } + + $bot = ['/api/v1/instance', '/api/v2/instance', '/api/v1/instance/extended_description', + '/api/v1/instance/peers']; + if (in_array($url, $bot)) { + blockbot_save('activitypub-api-stats', $agent); + } + + if (substr($url, 0, 6) == '/api/v') { + blockbot_save('activitypub-api', $agent); + } + + if (($_SERVER['REQUEST_METHOD'] == 'POST') && in_array('inbox', explode('/', parse_url($url, PHP_URL_PATH)))) { + blockbot_save('activitypub-inbox-agents', $agent); + } + + if (!empty($_SERVER['HTTP_SIGNATURE']) && !empty(HTTPSignature::getSigner('', $_SERVER, false))) { + blockbot_save('activitypub-signature-agents', $agent); + } +} + +function blockbot_check_login_attempt(string $url, array $logdata) +{ + if (in_array(trim(parse_url($url, PHP_URL_PATH), '/'), ['login', 'lostpass', 'register'])) { + DI::logger()->debug('Login attempt detected - reject', $logdata); + blockbot_reject(); + } +} + +/** + * Uncategorized and unwanted services + * + * @param array $parts + * @return boolean + */ +function blockbot_is_unwanted(array $parts): bool +{ + $agents = [ + 'oii-research', 'yisouspider', 'bots.retroverse.social', 'gaisbot', 'bloglines', 'emailwolf', + 'webtech', 'facebookscraper', 'www.ecsl.cs.sunysb.edu/~maxim/cgi-bin/link', + 'gulper', 'magellan', 'linkcheck', 'nerdybot', 'ms search robot', 'fast-webcrawler', + 'yioopbot', 'webster', 'www.admantx.com', 'openhosebot', 'lssrocketcrawler', 'dow jones searchbot', + 'gomezagent', 'domainsigmacrawler', 'netseer crawler', 'superbot', 'searchexpress', + 'alittle client', 'amazon-kendra', 'scanner.ducks.party', 'isscyberriskcrawler', + 'google wireless transcoder', + ]; + + foreach ($parts as $part) { + if (in_array($part, $agents)) { return true; } } return false; -} \ No newline at end of file +} + +/** + * Services defined as "crawlers" + * + * @param array $parts + * @return boolean + */ +function blockbot_is_crawler(array $parts): bool +{ + $agents = [ + '+http://yourls.org', 'adbeat.com/policy', 'https://gtmetrix.com', 'hubspot', 'nutch-', + 'openwebspider' + ]; + foreach ($parts as $part) { + foreach ($agents as $agent) { + if (strpos($part, $agent) !== false) { + return true; + } + } + } + + $agents = [ + 'ahrefsbot', 'pinterest', 'proximic', 'applebot', 'synapseworkstation.3.2.1', + 'slackbot-linkexpanding', 'semrushbot-sa', 'qwantify', 'google search console', + 'tbot-nutch', 'screaming frog seo spider', 'exaleadcloudview', 'dotbot', 'exabot', + 'spbot', 'surdotlybot', 'tweetmemebot', 'cliqzbot', 'startmebot', 'ccbot', 'zoombot', + 'domain re-animator bot', 'nutch', 'archive.org_bot http://www.archive.org/details', + 'yahoo link preview', 'mxt', 'grapeshotcrawler', 'maxpointcrawler', 'vagabondo', + 'archive.org_bot', 'infegyatlas', '2ip bot', 'accompanybot', 'antbot', 'anthropic-ai', + 'aspiegelbot', 'cispa web analyzer', 'claudebot', 'colly', 'petalbot', 'ioncrawl', + 'embedly +support@embed.ly', 'gitcrawlerbot', 'google favicon', 'httpx', 'seokicks', + 'kocmohabt', 'masscan-ng', 'mixnodecache', 'nicecrawler', 'birdcrawlerbot', 'seolyt', + 'dataprovider.com', 'dnsresearchbot', 'domains project', 'evc-batch', 'ev-crawler', + 'example3', 'geedobot', 'internetmeasurement', 'ips-agent', 'semanticscholarbot', + 'sputnikfaviconbot', 't3versionsbot', 'tchelebi', 'thinkchaos', 'velenpublicwebcrawler', + 'webwikibot', 'woobot', 'project-resonance', 'mtrobot', 'webprosbot', 'youbot', + 'queryseekerspider', 'scanning for research', 'semrushbot', 'senutobot', 'spawning-ai', + 'statista.com publication finder crawler', 'turnitin', 'who.is bot', 'zaldamosearchbot', + 'nuzzel', 'boardreader blog indexer', 'hatena-favicon', 'nbertaupete95', 'scrapy', + "electronic frontier foundation's do not track verifier", 'synapse', 'trendsmapresolver', + 'pinterestbot', 'um-ln', 'slack-imgproxy', 'diffbot', 'dataforseobot', 'bw', 'bitlybot', + 'twingly recon-klondike', 'imagesiftbot', 'rogerbot', 'yahoocachesystem', 'favicon', + 'vkshare', 'appid: s~virustotalcloud', 'clickagy intelligence bot v2', 'gptbot', + 'archive.org_bot http://archive.org/details', 'wellknownbot', 'archiveteam archivebot', + 'megaindex.ru', 'adbeat_bot', 'masscan', 'embedly', 'cloudflare-amp', 'exabot-thumbnails', + 'yahoo ad monitoring', 'seokicks-robot', 'trendiction search', 'semrushbot-si', 'plukkie', + 'hubpages v0.2.2', 'aream.bot', 'safednsbot', 'linkpadbot', 'gluten free crawler', + 'turnitinbot', 'xovibot', 'domaincrawler', 'nettrack', 'domaincrawler', 'yak', 'bubing', + 'netestate ne crawler', 'blexbot', 'the knowledge ai', 'optimizer', 'hubspot webcrawler', + 'venuscrawler', 'adstxtcrawler', 'iframely', 'checkmarknetwork', 'semrushbot-ba', + 'archive.org bot', 'aihitbot', 'sitesucker', 'adstxtlab.com crawler', 'jobboersebot', + 'http://www.archive.org/details/archive.org_bot', 'heritrix', 'appid: s~snapchat-proxy', + 'icc-crawler', 'mbcrawler', 'slackbot', 'trumind-crawler', 'newspaper', 'online-webceo-bot', + 'haena-pepper', 'y! crawler', 'linkwalker', 'seznamemailproxy', 'seekport crawler', + 'domainstatsbot', 'qwantify/mermoz', 'sprinklr', 'komodiabot', 'seoscanners.net', + 'domainappender', 'mixrankbot', 'abonti', 'urlappendbot', 'sistrix crawler', + 'hatenabookmark', 'metainspector', 'ezooms', 'quora link preview', 'semrushbot-bm', + 'barkrowler', 'panscient.com', 'http://tweetedtimes.com', 'twingly recon', + 'collection@infegy.com', 'mediatoolkitbot', 'cloudflare-amphtml', 'ramblermail', + 'tineye', 'adscanner', 'datagnionbot', 'aa_crawler', 'http://www.profound.net/domainappender', + 'appid: e~arsnova-filter-system', 'kinglandsystemscorp', 'crmnlcrawlagent', 'techfetch-bot', + ]; + + foreach ($parts as $part) { + if (substr($part, -13) == ' accompanybot') { + return true; + } + + if (in_array($part, $agents)) { + return true; + } + } + return false; +} + +/** + * Services defined as search bots + * + * @param array $parts + * @return boolean + */ +function blockbot_is_searchbot(array $parts): bool +{ + $agents = ['baiduspider']; + foreach ($parts as $part) { + foreach ($agents as $agent) { + if (strpos($part, $agent) !== false) { + return true; + } + } + } + + $agents = [ + 'yahoo! slurp', 'linkcheck by siteimprove.com', 'googlebot', '360spider', 'haosouspider', + 'mj12bot', 'feedfetcher-google', 'mediapartners-google', 'duckduckgo-favicons-bot', + 'googlebot-mobile', 'gigablastopensource', 'bingbot', 'surveybot', 'yandexbot', + 'google web preview', 'meanpathbot', 'wesee_bot:we_help_monitize_your_site', + 'seznambot', 'sogou web spider', 'linkdexbot', 'msnbot', 'smtbot', 'yandexmetrika', + 'google-site-verification', 'netcraft ssl server survey - contact info@netcraft.com', + 'orangebot', 'google-adwords-instant', 'googlebot-richsnippets', 'google-lens', + 'googleother', 'google-test', 'linkdex.com', 'mail.ru', 'awariobot', 'bytespider', + 'coccocbot-image', 'discobot', 'google-inspectiontool', 'netcraftsurveyagent', + 'tineye-bot', 'tineye-bot-live', 'bingpreview', 'ask jeeves', 'adsbot-google', "msnbot-media ", + 'googlebot-image', 'googlebot-news', 'googlebot-video', 'msnbot-media', 'yahoo! slurp china', + 'inoreader.com-like feedfetcher-google', 'google-amphtml', 'duckduckbot', 'coccocbot-web', + 'googleassociationservice', 'yandexwebmaster', 'yacybot', 'duckduckbot-https', 'yandexmobilebot', + 'mail.ru_bot/fast', 'yandeximages', 'mail.ru_bot/img', 'ia_archiver', 'yandexblogs', + 'yandexaccessibilitybot', 'yandeximageresizer', 'mail.ru_bot', 'yeti', 'obot', 'baiduspider-render', + 'netcraft web server survey', 'yandexnews', 'google', 'yandexrenderresourcesbot', + 'match by siteimprove.com', 'yandexsitelinks', 'yandexantivirus', 'daum', 'mail.ru_bot/robots', + 'yandexmedia', 'msnbot-products', 'yandexvideo', 'yandexvertis', 'catexplorador', 'yandexcalendar', + 'yandexfavicons', 'user-agent\x09baiduspider', 'baiduspider-image', 'yandexpagechecker', 'mojeekbot', + 'adsbot-google-mobile', 'google-adwords-displayads-webrender', 'seznam screenshot-generator', + 'yandexscreenshotbot', 'zumbot', 'tracemyfile', 'wotbox', 'google-adwords-express', + 'google-adwords-displayads', 'google-youtube-links', 'yandexvideoparser', 'paperlibot', + 'weborama-fetcher', 'googleproducer', 'coccoc', 'acoonbot', 'psbot', 'sosospider', 'voilabot', + 'blekkobot', 'easouspider', 'omgili', 'yadirectfetcher', 'sogou pic spider', 'daumoa', + ]; + + foreach ($parts as $part) { + if (in_array($part, $agents)) { + return true; + } + } + return false; +} + +/** + * Services in the "security" context + * + * @param array $parts + * @return boolean + */ +function blockbot_is_security_checker(array $parts): bool +{ + $agents = [ + 'http banner detection', 'l9explore', 'l9tcpid', 'lkx-apache2449traversalplugin', + 'bitsightbot', 'censysinspect', 'pathspider', 'repolookoutbot', 'sqlmap', 'ltx71', + 'netsystemsresearch studies the availability of various services across the internet. our website is netsystemsresearch.com', + 'expanse a palo alto networks company searches across the global ipv4 space multiple times per day to identify customers'', + 'zgrab', 'nmap scripting engine', 'l9scan', 'riddler', 'cloud mapping experiment. contact research@pdrlabs.net', + ]; + + foreach ($parts as $part) { + if (in_array($part, $agents)) { + return true; + } + } + return false; +} + +/** + * Services that check pages for e.g. valid HTML + * + * @param array $parts + * @return boolean + */ +function blockbot_is_validator(array $parts): bool +{ + $agents = [ + 'jigsaw', 'ssl labs', 'w3c_validator', 'w3c-checklink', 'p3p validator', 'csscheck', 'validator.nu', + 'google-structured-data-testing-tool https://search.google.com/structured-data', 'w3c_unicorn', + ]; + + foreach ($parts as $part) { + if (in_array($part, $agents)) { + return true; + } + } + return false; +} + +/** + * Services that monitor a page + * + * @param array $parts + * @return boolean + */ +function blockbot_is_monitor(array $parts): bool +{ + $agents = [ + 'alexa site audit', 'catchpoint', 'google page speed insights', 'checkhost', + 'poduptime', 'chrome-lighthouse', 'zabbix', 'cloudflare-alwaysonline', 'ptst', + 'pingadmin.ru', 'pingdomtms', 'nimbostratus-bot', 'uptimebot', 'uptimerobot', + 'http://notifyninja.com/monitoring', 'http://www.freewebmonitoring.com', + ]; + + foreach ($parts as $part) { + if (in_array($part, $agents)) { + return true; + } + } + return false; +} + +/** + * Services in the centralized and decentralized social media environment + * + * @param array $parts + * @return boolean + */ +function blockbot_is_social_media(array $parts): bool +{ + $agents = ['camo-rs asset proxy', 'camo asset proxy']; + foreach ($parts as $part) { + foreach ($agents as $agent) { + if (strpos($part, $agent) !== false) { + return true; + } + } + } + + $agents = [ + 'facebookexternalhit', 'twitterbot', 'mastodon', 'facebookexternalua', + 'friendica', 'diasporafederation', 'buzzrelay', 'activityrelay', 'drupal', + 'aoderelay', 'ap-relay', 'peertube', 'misskey', 'pleroma', 'foundkey', 'akkoma', + 'lemmy', 'calckey', 'mobilizon', 'zot', 'camo-rs', 'gotosocial', 'pixelfed', + 'pixelfedbot', 'app.wafrn.net', 'go-camo', 'http://a.gup.pe', 'iceshrimp', + 'firefish', 'activity-relay', 'juick', 'camo', 'python/federation', 'nextcloud', + 'snac', 'bovine', 'takahe', 'freedica', 'gnu social', 'microblogpub', + 'mbin', 'mammoth', 'kbinbot', 'honksnonk', 'misskeymediaproxy', 'kbinbot', 'jistflow', + 'mastodon/3.4.1 fedibird', 'fedibird', 'funkwhale', 'linkedinbot', + 'wafrn-cache-generator', 'simple social network', 'mbinbot', 'wordpress.com', + 'catnip', 'castopod', 'enby-town', 'vernissage', 'iceshrimp.net', 'plasmatrap', + 'imgproxy', 'rustypub', 'flipboard activitypub', 'gnu social activitypub plugin', + 'micro.blog', 'mastodon-bookmark-rss', 'bookwyrm', 'damus', 'primal', 'misskeyadmin', + 'ruby, mastodon', 'nextcloud social', 'camo asset proxy', 'smithereen', 'sorasns', + 'cherrypick', 'bonfire activitypub federation', 'upub+0.1.0', 'plume', 'incestoma', + 'gyptazyfedi', 'apogee', 'quolibet', 'magpie-crawler', 'redditbot', 'facebookplatform', + ]; + + foreach ($parts as $part) { + if (in_array($part, $agents)) { + return true; + } + } + return false; +} + +/** + * Fediverse clients + * + * @param array $parts + * @return boolean + */ +function blockbot_is_fediverse_client(array $parts): bool +{ + $agents = [ + 'mastodonandroid', 'tootdeck-worker', 'piefed', 'brighteon', 'pachli', 'tusky', 'mona', 'mitra', + 'megalodonandroid', 'fedilab', 'mastodonapp', 'toot!', 'intravnews', + 'pixeldroid', 'greatnews', 'protopage', 'newsfox', 'vienna', 'wp-urldetails', 'husky', + 'activitypub-go-http-client', 'mobilesafari', 'mastodon-ios', 'mastodonpy', 'techniverse', + 'relatica', + ]; + + foreach ($parts as $part) { + if (in_array($part, $agents)) { + return true; + } + } + return false; +} + +/** + * Feed reading clients and services + * + * @param array $parts + * @return boolean + */ +function blockbot_is_feed_reader(array $parts): bool +{ + $agents = [ + 'tiny tiny rss', 'mlem', 'feedly', 'flipboardproxy', 'reeder', 'netnewswire', + 'freshrss', 'feedlyapp', 'feedlybot', 'feeddemon', 'rssowl', 'simplepie', + 'magpierss', 'universalfeedparser', 'newsgatoronline', 'theoldreader.com', + 'quiterss', 'feedburner', 'digg feed fetcher', 'r6_feedfetcher', 'apple-pubsub', + 'netvibes', 'newsblur page fetcher', 'newsblur favicon fetcher', 'newsblur favicon fetcher', + 'liferea', 'http://www.jetbrains.com/omea_reader/', 'feedblitz', 'bloglovin', + 'windows-rss-platform', 'feedshow', 'feedreader', 'rssbandit', 'everyfeed-spider', + 'feeeed', 'spacecowboys android rss reader', 'gregarius', 'feedspot', + 'feedspot ssl asset proxy', 'newsgator', 'newsgator fetchlinks extension', + 'akregator', 'appid: s~feedly-nikon3', + ]; + + foreach ($parts as $part) { + if (in_array($part, $agents)) { + return true; + } + } + return false; +} + +function blockbot_is_fediverse_tool(array $parts): bool +{ + $agents = [ + 'diaspora-connection-tester', 'fediblock.manalejandro.com', + 'mastodoninstances', 'fedilist agent', 'https://fedilist.com/', 'fedidb', + 'https://wiki.communitydata.science/communitydata:fediverse_research', 'mastofeed.com', + 'lemmy-explorer-crawler', 'fedicheck.online v1.0', 'momostr', 'fedditlemmyversecrawler', + 'fediseer', 'fedistatscrawler', 'gnusocialbot', 'fedifetcher', 'fedineko', 'bird.makeup', + 'fediverse', 'fedicheck.online', 'https://fed.brid.gy/', 'lemmy-stats-crawler', + "fediverse's stats", 'friendicadirectory', 'rss discovery engine', + 'python-opengraph-jaywink', 'connect.rocks', 'tootsdk', + ]; + + + foreach ($parts as $part) { + if (in_array($part, $agents)) { + return true; + } + } + return false; +} + +/** + * General services + * + * @param array $parts + * @return boolean + */ +function blockbot_is_service_agent(array $parts): bool +{ + $agents = ['wordpress.com']; + foreach ($parts as $part) { + foreach ($agents as $agent) { + if (strpos($part, $agent) !== false) { + return true; + } + } + } + + $agents = [ + 'chrome privacy preserving prefetch proxy', 'http compression test', 'microsoftpreview', + 'pocketimagecache', 'wordpress', 'skypeuripreview preview', 'wordpress.com', 'discordbot', + 'summalybot', 'livelapbot', 'whatsapp', 'facebot', 'skypeuripreview', + 'plasmatrap image proxy server', 'grammarly', 'browsershots', 'google-apps-script', + 'yahoomailproxy', 'pocketparser', 'apachebench', + ]; + + foreach ($parts as $part) { + if (in_array($part, $agents)) { + return true; + } + } + return false; +} + +/** + * Libraries that perform HTTP requests + * + * @param array $parts + * @return boolean + */ +function blockbot_is_http_library(array $parts): bool +{ + if ((count($parts) == 1) && in_array($parts[0], ['okhttp', 'useragent', 'faraday'])) { + return true; + } + + $agents = ['faraday ']; + foreach ($parts as $part) { + foreach ($agents as $agent) { + if (strpos($part, $agent) !== false) { + return true; + } + } + } + + $agents = [ + 'python-urllib', 'go-http-client', 'axios', 'java', 'undici', 'node', 'ruby', + 'mint', 'wget', 'dart:io', 'dart', 'caveman-sieve', 'guzzlehttp', 'deno', + 'aiohttp', 'networkingextension', 'python-asks', 'fasthttp', 't7', 'scalaj-http', + 'curl', 'python-requests', 'node-fetch', 'offline explorer', 'aria2', + 'link_thumbnailer', 'python-httpx', 'com.apple.safari.searchhelper', + 'com.apple.webkit.networking', 'luasocket', 'libwww-perl', 'google-http-java-client', + 'appengine-google', 'reqwest', 'htmlparser', 'headlesschrome', 'winhttp', + 'webcopier', 'webzip', 'http.jl', 'got', 'hackney', 'oca\mail\vendor\favicon', + 'winhttp.winhttprequest.5', 'go package http', 'jakarta commons-httpclient', + 'cpp-httplib', 'fuzz faster u fool v1.3.1-dev', 'fuzz faster u fool v1.5.0-dev', + 'go http package', 'go-resty', 'http.rb', 'ivre-masscan', 'java1.0.21.0', + 'jsdom', 'python-urllib3', 'reactornetty', 'req', 'restsharp', 'ruby-rdf-distiller', + 'pycurl', 'fdm', 'fdmx', 'lua-resty-http', 'python-httplib2', 'anyevent-http', + 'node-superagent', 'unirest-java', 'gvfs', 'http_request2', 'java browser', 'cakephp', + 'curly http client', 'lavf', 'typhoeus', + ]; + + foreach ($parts as $part) { + if (in_array($part, $agents)) { + return true; + } + } + return false; +} + +/** + * Uncategorized helpful services + * + * @param array $parts + * @return boolean + */ +function blockbot_is_good_tool(array $parts): bool +{ + $agents = [ + 'easy-feed-oven', 'cutycapt', 'rss-is-dead.lol web bot', 'dnt-policy@eff.org', + 'https://socnetv.org', 'opengraphreader', 'trendfetcher', 'iabot', 'rss-is-dead.lol feed bot', + 'androiddownloadmanager', 'readybot.io', 'hydra', 'httrack', 'vlc', 'wdg_validator', 'download demon', + ]; + + + foreach ($parts as $part) { + if (in_array($part, $agents)) { + return true; + } + } + return false; +} + +function blockbot_get_parts(string $agent): array +{ + $parts = []; + $level = 0; + $start = 0; + $end = 0; + $has_brackets = false; + for ($pos = 0; $pos < strlen($agent); $pos++) { + if ((strpos(substr($agent, $pos), '(') === false) && ($level == 0)) { + $part = substr($agent, $pos); + $parts = array_merge($parts, blockbot_split_parts($part, strpos($part, '/'), !$has_brackets)); + break; + } elseif (substr($agent, $pos, 1) == '(') { + $level++; + $has_brackets = true; + if ($level == 1) { + $part = substr($agent, $end, $pos - $end); + $parts = array_merge($parts, blockbot_split_parts($part, $start != 0, false)); + $start = $pos + 1; + } + } elseif (substr($agent, $pos, 1) == ')') { + $level--; + if ($level == 0) { + $part = substr($agent, $start, $pos - $start); + $parts = array_merge($parts, blockbot_split_parts($part, false, true)); + $end = $pos + 1; + } + } + } + return blockbot_remove_browser_parts($parts); +} + +function blockbot_remove_browser_parts(array $parts): array +{ + $cleaned = []; + foreach ($parts as $part) { + if (substr($part, -6) == ' build') { + continue; + } + $known = [ + 'mozilla', 'x11', 'ubuntu', 'linux x86_64', 'gecko', 'firefox', 'windows nt', + 'win64', 'x64', 'android', 'applewebkit', 'khtml', 'like', 'chrome', 'safari', 'edg', + 'unsupported', 'compatible', 'macintosh', 'intel mac os x', 'version', 'windows', + 'u', 'en-us', '.net', '.net', 'wow64', 'linux', 'k', 'mobile', 'opr', 'msie', + 'dalvik', 'build', 'nt', 'mobile safari', 'gecko/firefox', 'zh-cn', 'en-gb', 'clr', + 'trident', '.net clr', 'qtwebengine', 'linux i686', 'tablet pc', 'ppc mac os x', + 'en', 'fedora', 'ppc', 'edge', 'yabrowser', 'yowser', 'media center pc', 'arm_64', + 'android 9', 'cros x86_64', 'iphone', 'cpu iphone os like mac os x', 'core', + 'qqbrowser', 'beta', 'khtml like gecko', 'psp (playstation portable)', 'ia64', + 'firephp', 'live', 'slcc2', 'infopath.2', 'bidubrowser', 'ubrowser', 'baiduboxapp', + 'waterfox', 'lynx', 'libwww-fm', 'ssl-mm', 'openssl', 'gnutls', '.net4.0c', '.net4.0e', + 'infopath.3', 'opera', 'palemoon', 'goanna', 'vivaldi', 'presto', 'intrepid', 'ru', + 'ipad', 'cpu os like mac os x', 'omniweb', 'chromium', 'thunderbird', 'ubuntu lts', + 'os', 'qupzilla', 'seamonkey', 'warp', 'konqueror', 'meego', 'nokian9', 'nokiabrowser', + 'profile', 'configuration', 'untrusted', 'samsungbrowser', 'es-us', 'pocophone f1', + 'sonyericssonw995', 'crios', 'lbbrowser', 'gwx:qualified', 'gwx:red', 'gwx:reserved', + 'microsoft outlook', 'word', 'microsoft', 'office', 'powerpoint', 'excel', + 'internet explorer', 'like gecko', 'shuame', 'qianniu', 'khtml, like gecko', + 'cutycapt version', 'khtml, live gecko', '68k', 'sv1', 'aef', 'gtb7.5', 'gfe', + 'embedded web browser from: http://bsalsa.com', 'wv', 'malnjs', '2.00', + 'fsl', 'lcjb', 'malcjs', 'touch', 'masmjs', 'malc', 'maln', 'foxy', 'bri', 'lcte', + 'embeddedwb from: http://www.bsalsa.com', '2345explorer', 'hpntdfjs', 'h4213', + 'rb.gy', 'sm-a505fn', 'lenovo tb-8504x', 'silk', 'lya-al00', 'windows xp', 'openbsd', + 'netbsd amd64', 'sa', 'samsung sm-g950f', 'redmi note', 'hry-lx1', 'cph2205', + '16th', 'redmi note pro', 'xiaomi/miuibrowser', 'sk-sk', 'linux i686 on x86_64', + 'debian iceweasel', 'rmx2101', 'mi note pro', 'rmx1921', 'nokia6100', '04.01', + 'fr-fr', 'slackware', 'sm-a225f', 'fennec', 'links', 'i386', 'windows phone os', + 'blackberry', 'maxthon', 'opera mini', 'j2me', 'winnt4.0', 'phoenix', 'avant browser', + 'iceweasel', 'moto e(7) plus', 'like geckoo', 'wpdesktop', 'nokia', 'lumia', 'arm', + 'de-at', 'pixel', 'puffin', 'zte blade a7', 'linux armv7l', 'hd1913', 'symbianos', + 'symbian os', 'de', '452', 'opera [en-us]', 'iemobile', 'windows phone', 'sm-g991b', + 'sm-j810g', 'da-dk', 'symbian', 'series60', 'nokiax7-00', 'freebsd amd64', 'openbsd amd64', + 'sm-n920c', 'blazer', 'palmsource', '16;320x320', 'sm-g998b', 'sm-a505g', 'freebsd i386', + 'jaunty', 'shiretoko', 'playbook', 'rim tablet os', 'asus;galaxy6', 'minimo', + 'linux arm7tdmi', 'blackberry7520', 'dl1036', '100011886a', 'lt-gtklauncher', + 'browserng', 'nokiae7-00', 'ubuntu chromium', 'silk-accelerated=true', 'openbsd i386', + 'windows ce', 'microsoft zunehd', 'epiphany', 'es-es', 'ru-ru', 'netbsd', 'ipod', + 'safari', 'xbox', 'xbox one', 'fxios', 'opx', 'ucbrowser', 'u3', + 'webos', 'desktop', 'compatible msie windows nt', 'sm-a525f', 'sm-g991u', 'ze520kl', + 'cros i686', 'de-de', 'en-ca', 'config', 'i686', 'sm-g970u', 'win95', 'i', + 'nokia7250', 'oneplus a6003', 'i2126', 'nintendo wii', 'vog-l29', 'msoffice', 'ms-office', + 'oneplus a5010', 'linux mint', 'blackberry8320', 'observatory', 'qdesk', + 'alexatoolbar', 'se metasr', 'qqdownload', 'alexa toolbar', 'baiduclient', 'ddg_android', + 'com.duckduckgo.mobile.android', 'android api', 'duckduckgo', 'googletoolbar', 'amaya', + ]; + if (!in_array($part, $known) && !preg_match('=^rv:[\d]+\S*$=', $part)) { + $cleaned[] = $part; + } + } + return $cleaned; +} + +function blockbot_clean_part(string $part): string +{ + $part = trim($part); + $subparts = []; + foreach (explode(' ', $part) as $subpart) { + $subpart = trim($subpart, ' +,'); + if (!empty($subpart) && (!preg_match('=^\d+[\w\-\+\.]+$=', $subpart) || empty($subparts))) { + $subparts[] = $subpart; + } + } + return implode(' ', $subparts); +} + +function blockbot_split_parts(string $agent, bool $parse_spaces, bool $parse_semicolon): array +{ + $agent = strtolower(trim($agent, ' ;')); + $cleaned = []; + + while (preg_match('=\w+[\s\w/\._\-]*/\d+[^;\s]*=', $agent, $matches)) { + $part = $matches[0]; + if (preg_match('=/\d+[^;\s]*=', $part, $matches, PREG_OFFSET_CAPTURE)) { + $cleaned[] = substr($part, 0, $matches[0][1]); + $part = substr($part, 0, $matches[0][1] + strlen($matches[0][0])); + } + $agent = trim(str_replace($part, '', $agent)); + } + if ($parse_semicolon && strpos($agent, ';') !== false) { + $parse_spaces = false; + $parts = []; + foreach (explode(';', $agent) as $part) { + $parts[] = blockbot_clean_part($part); + } + } elseif (strpos($agent, ' - ') !== false) { + $parts = []; + foreach (explode(' - ', $agent) as $part) { + $parts[] = blockbot_clean_part($part); + } + } elseif ($parse_spaces) { + $parts = explode(' ', $agent); + } else { + $parts = [$agent]; + } + + if ($parse_spaces) { + $subparts = []; + foreach ($parts as $part) { + while (($pos_space = strpos($part, ' ')) !== false && ($pos_slash = strpos($part, '/')) !== false) { + if ($pos_space > $pos_slash) { + $subparts[] = substr($part, 0, $pos_space); + $part = trim(substr($part, $pos_space + 1), ' +,-;'); + } else { + $subparts[] = $part; + $part = ''; + } + } + if ($part != '') { + $subparts[] = $part; + } + } + $parts = $subparts; + } + + foreach ($parts as $part) { + $part = trim($part, ' +'); + + if (!Network::isValidHttpUrl($part) && strpos($part, '/') !== false) { + $split = explode('/', $part); + array_pop($split); + $part = implode('/', $split); + } + + $pos1 = strpos($part, "'"); + $pos2 = strrpos($part, "'"); + if ($pos1 != $pos2) { + $part = substr($part, 0, $pos1 - 1) . substr($part, $pos2 + 1); + } + + $part = trim(preg_replace('=(.*) [\d\.]+=', '$1', $part), " +,-;\u{00AD}"); + if (!empty($part)) { + $cleaned[] = $part; + } + } + return $cleaned; +} diff --git a/blockbot/composer.json b/blockbot/composer.json index f13a2d17..40583e20 100644 --- a/blockbot/composer.json +++ b/blockbot/composer.json @@ -1,24 +1,24 @@ { - "name": "friendica-addons/blockbot", - "description": "Blocking bots based on detecting bots/crawlers/spiders via the user agent and http_from header.", - "type": "friendica-addon", - "authors": [ - { - "name": "Philipp Holzer", - "email": "admin@philipp.info", - "homepage": "https://friendica.philipp.info/profile/nupplaphil", - "role": "Developer" - } - ], - "require": { - "php": ">=5.6.0", - "jaybizzle/crawler-detect": "1.*" - }, - "license": "3-clause BSD license", - "minimum-stability": "stable", - "config": { - "optimize-autoloader": true, - "autoloader-suffix": "BlockBotAddon", - "preferred-install": "dist" - } + "name": "friendica-addons/blockbot", + "description": "Blocking bots based on detecting bots/crawlers/spiders via the user agent and http_from header.", + "type": "friendica-addon", + "authors": [ + { + "name": "Philipp Holzer", + "email": "admin@philipp.info", + "homepage": "https://friendica.philipp.info/profile/nupplaphil", + "role": "Developer" + } + ], + "require": { + "php": ">=5.6.0", + "jaybizzle/crawler-detect": "1.*" + }, + "license": "3-clause BSD license", + "minimum-stability": "stable", + "config": { + "optimize-autoloader": true, + "autoloader-suffix": "BlockBotAddon", + "preferred-install": "dist" + } } diff --git a/blockbot/composer.lock b/blockbot/composer.lock index 26b021b1..50f71a37 100644 --- a/blockbot/composer.lock +++ b/blockbot/composer.lock @@ -8,24 +8,23 @@ "packages": [ { "name": "jaybizzle/crawler-detect", - "version": "v1.2.80", + "version": "v1.2.116", "source": { "type": "git", "url": "https://github.com/JayBizzle/Crawler-Detect.git", - "reference": "af6a36e6d69670df3f0a3ed8e21d4b8cc67a7847" + "reference": "97e9fe30219e60092e107651abb379a38b342921" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/JayBizzle/Crawler-Detect/zipball/af6a36e6d69670df3f0a3ed8e21d4b8cc67a7847", - "reference": "af6a36e6d69670df3f0a3ed8e21d4b8cc67a7847", + "url": "https://api.github.com/repos/JayBizzle/Crawler-Detect/zipball/97e9fe30219e60092e107651abb379a38b342921", + "reference": "97e9fe30219e60092e107651abb379a38b342921", "shasum": "" }, "require": { "php": ">=5.3.0" }, "require-dev": { - "phpunit/phpunit": "^4.8|^5.5|^6.5", - "satooshi/php-coveralls": "1.*" + "phpunit/phpunit": "^4.8|^5.5|^6.5|^9.4" }, "type": "library", "autoload": { @@ -53,7 +52,7 @@ "crawlerdetect", "php crawler detect" ], - "time": "2019-04-05T19:52:02+00:00" + "time": "2023-07-21T15:49:49+00:00" } ], "packages-dev": [], @@ -65,5 +64,6 @@ "platform": { "php": ">=5.6.0" }, - "platform-dev": [] + "platform-dev": [], + "plugin-api-version": "1.1.0" } diff --git a/blockbot/lang/C/messages.po b/blockbot/lang/C/messages.po index a99ccc5a..6926c8a1 100644 --- a/blockbot/lang/C/messages.po +++ b/blockbot/lang/C/messages.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-03-05 04:51+0000\n" +"POT-Creation-Date: 2024-04-30 12:12+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,52 +17,29 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: blockbot.php:30 +#: blockbot.php:32 msgid "Save Settings" msgstr "" -#: blockbot.php:31 -msgid "Allow \"good\" crawlers" -msgstr "" - -#: blockbot.php:31 -msgid "" -"Don't block fediverse crawlers, relay servers and other bots with good " -"purposes." -msgstr "" - -#: blockbot.php:32 -msgid "Allow preview agents" -msgstr "" - -#: blockbot.php:32 -msgid "" -"Don't block agents from social media systems that want to generate preview " -"data for links that had been set by their users." +#: blockbot.php:33 +msgid "Allow security checkers" msgstr "" #: blockbot.php:33 +msgid "Don't block security checkers. They can be used for good or bad." +msgstr "" + +#: blockbot.php:34 msgid "Allow generic HTTP libraries" msgstr "" -#: blockbot.php:33 +#: blockbot.php:34 msgid "" "Don't block agents from generic HTTP libraries that could be used for good " "or for bad and that currently can't be traced back to any known Fediverse " "project." msgstr "" -#: blockbot.php:34 -msgid "Block GabSocial" -msgstr "" - -#: blockbot.php:34 -msgid "" -"Block the software GabSocial. This will block every access for that " -"software. You can block dedicated gab instances in the blocklist settings in " -"the admin section." -msgstr "" - #: blockbot.php:35 msgid "Training mode" msgstr "" diff --git a/blockbot/templates/admin.tpl b/blockbot/templates/admin.tpl index 5f41ae70..86a462da 100644 --- a/blockbot/templates/admin.tpl +++ b/blockbot/templates/admin.tpl @@ -1,6 +1,4 @@ -{{include file="field_checkbox.tpl" field=$good_crawlers}} -{{include file="field_checkbox.tpl" field=$socialmedia_agents}} +{{include file="field_checkbox.tpl" field=$security_checker}} {{include file="field_checkbox.tpl" field=$http_libraries}} -{{include file="field_checkbox.tpl" field=$block_gab}} {{include file="field_checkbox.tpl" field=$training}} -
+
\ No newline at end of file diff --git a/blockbot/vendor/composer/ClassLoader.php b/blockbot/vendor/composer/ClassLoader.php index 95f7e097..03b9bb9c 100644 --- a/blockbot/vendor/composer/ClassLoader.php +++ b/blockbot/vendor/composer/ClassLoader.php @@ -60,7 +60,7 @@ class ClassLoader public function getPrefixes() { if (!empty($this->prefixesPsr0)) { - return call_user_func_array('array_merge', $this->prefixesPsr0); + return call_user_func_array('array_merge', array_values($this->prefixesPsr0)); } return array(); @@ -279,7 +279,7 @@ class ClassLoader */ public function setApcuPrefix($apcuPrefix) { - $this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null; + $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null; } /** diff --git a/blockbot/vendor/composer/autoload_real.php b/blockbot/vendor/composer/autoload_real.php index ccb886a2..404079e0 100644 --- a/blockbot/vendor/composer/autoload_real.php +++ b/blockbot/vendor/composer/autoload_real.php @@ -13,6 +13,9 @@ class ComposerAutoloaderInitBlockBotAddon } } + /** + * @return \Composer\Autoload\ClassLoader + */ public static function getLoader() { if (null !== self::$loader) { diff --git a/blockbot/vendor/composer/installed.json b/blockbot/vendor/composer/installed.json index d255d573..db9064b6 100644 --- a/blockbot/vendor/composer/installed.json +++ b/blockbot/vendor/composer/installed.json @@ -1,27 +1,26 @@ [ { "name": "jaybizzle/crawler-detect", - "version": "v1.2.80", - "version_normalized": "1.2.80.0", + "version": "v1.2.116", + "version_normalized": "1.2.116.0", "source": { "type": "git", "url": "https://github.com/JayBizzle/Crawler-Detect.git", - "reference": "af6a36e6d69670df3f0a3ed8e21d4b8cc67a7847" + "reference": "97e9fe30219e60092e107651abb379a38b342921" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/JayBizzle/Crawler-Detect/zipball/af6a36e6d69670df3f0a3ed8e21d4b8cc67a7847", - "reference": "af6a36e6d69670df3f0a3ed8e21d4b8cc67a7847", + "url": "https://api.github.com/repos/JayBizzle/Crawler-Detect/zipball/97e9fe30219e60092e107651abb379a38b342921", + "reference": "97e9fe30219e60092e107651abb379a38b342921", "shasum": "" }, "require": { "php": ">=5.3.0" }, "require-dev": { - "phpunit/phpunit": "^4.8|^5.5|^6.5", - "satooshi/php-coveralls": "1.*" + "phpunit/phpunit": "^4.8|^5.5|^6.5|^9.4" }, - "time": "2019-04-05T19:52:02+00:00", + "time": "2023-07-21T15:49:49+00:00", "type": "library", "installation-source": "dist", "autoload": { diff --git a/blockbot/vendor/jaybizzle/crawler-detect/.github/workflows/php-cs-fixer.yml b/blockbot/vendor/jaybizzle/crawler-detect/.github/workflows/php-cs-fixer.yml new file mode 100644 index 00000000..1c083c40 --- /dev/null +++ b/blockbot/vendor/jaybizzle/crawler-detect/.github/workflows/php-cs-fixer.yml @@ -0,0 +1,23 @@ +name: Check & fix styling + +on: [ push ] + +jobs: + php-cs-fixer: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v2 + with: + ref: ${{ github.head_ref }} + + - name: Run PHP CS Fixer + uses: docker://oskarstark/php-cs-fixer-ga:2.18.6 + with: + args: --config=.php_cs.dist --allow-risky=yes + + - name: Commit changes + uses: stefanzweifel/git-auto-commit-action@v4 + with: + commit_message: Fix styling \ No newline at end of file diff --git a/blockbot/vendor/jaybizzle/crawler-detect/.github/workflows/test.yml b/blockbot/vendor/jaybizzle/crawler-detect/.github/workflows/test.yml new file mode 100644 index 00000000..22911114 --- /dev/null +++ b/blockbot/vendor/jaybizzle/crawler-detect/.github/workflows/test.yml @@ -0,0 +1,56 @@ +name: Test + +on: + push: + branches: + - "master" + pull_request: + +jobs: + build: + runs-on: ubuntu-latest + strategy: + fail-fast: true + matrix: + php: [5.3, 5.4, 5.5, 5.6, 7.0, 7.1, 7.2, 7.3, 7.4, 8.0, 8.1, 8.2] + + name: PHP:${{ matrix.php }} + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Setup PHP, with composer + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + tools: composer:v2 + coverage: xdebug + + - name: Get composer cache directory + id: composer-cache + run: | + echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + shell: bash + + - name: Cache composer dependencies + uses: actions/cache@v3 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: dependencies-php-${{ matrix.php }}-composer-${{ hashFiles('composer.json') }} + restore-keys: dependencies-php-${{ matrix.php }}-composer- + + - name: Install Composer dependencies + run: | + composer install --prefer-dist --no-interaction --no-suggest + + - name: Run Unit tests + run: | + vendor/bin/phpunit --coverage-clover=tests/logs/clover.xml + + - name: Upload coverage results to Coveralls + env: + COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + composer global require php-coveralls/php-coveralls "^1.0" + coveralls --coverage_clover=tests/logs/clover.xml -v diff --git a/blockbot/vendor/jaybizzle/crawler-detect/.php_cs.dist b/blockbot/vendor/jaybizzle/crawler-detect/.php_cs.dist new file mode 100644 index 00000000..91c91af9 --- /dev/null +++ b/blockbot/vendor/jaybizzle/crawler-detect/.php_cs.dist @@ -0,0 +1,33 @@ +in([ + __DIR__.'/src', + __DIR__.'/tests', + ]) + ->name('*.php') + ->ignoreDotFiles(true) + ->ignoreVCS(true); + +return PhpCsFixer\Config::create() + ->setRules([ + '@PSR2' => true, + 'array_syntax' => ['syntax' => 'long'], + 'ordered_imports' => ['sortAlgorithm' => 'alpha'], + 'no_unused_imports' => true, + 'not_operator_with_successor_space' => true, + 'trailing_comma_in_multiline_array' => true, + 'phpdoc_scalar' => true, + 'unary_operator_spaces' => true, + 'binary_operator_spaces' => true, + 'blank_line_before_statement' => [ + 'statements' => ['break', 'continue', 'declare', 'return', 'throw', 'try'], + ], + 'phpdoc_single_line_var_spacing' => true, + 'phpdoc_var_without_name' => true, + 'method_argument_space' => [ + 'on_multiline' => 'ensure_fully_multiline', + 'keep_multiple_spaces_after_comma' => true, + ], + ]) + ->setFinder($finder); \ No newline at end of file diff --git a/blockbot/vendor/jaybizzle/crawler-detect/LICENSE b/blockbot/vendor/jaybizzle/crawler-detect/LICENSE index 2f4e15e2..569c7b4f 100644 --- a/blockbot/vendor/jaybizzle/crawler-detect/LICENSE +++ b/blockbot/vendor/jaybizzle/crawler-detect/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2015-2018 Mark Beech +Copyright (c) 2015-2020 Mark Beech 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/blockbot/vendor/jaybizzle/crawler-detect/README.md b/blockbot/vendor/jaybizzle/crawler-detect/README.md index e7c25f3b..57ec8e8b 100644 --- a/blockbot/vendor/jaybizzle/crawler-detect/README.md +++ b/blockbot/vendor/jaybizzle/crawler-detect/README.md @@ -1,24 +1,23 @@ -



-crawlerdetect.io +



+crawlerdetect.io

-

- +GitHub Workflow Status - -

## About CrawlerDetect -CrawlerDetect is a PHP class for detecting bots/crawlers/spiders via the user agent and http_from header. Currently able to detect 1,000's of bots/spiders/crawlers. +CrawlerDetect is a PHP class for detecting bots/crawlers/spiders via the `user agent` and `http_from` header. Currently able to detect 1,000's of bots/spiders/crawlers. ### Installation -Run `composer require jaybizzle/crawler-detect 1.*` or add `"jaybizzle/crawler-detect" :"1.*"` to your `composer.json`. +``` +composer require jaybizzle/crawler-detect +``` ### Usage ```PHP @@ -46,7 +45,7 @@ If you find a bot/spider/crawler user agent that CrawlerDetect fails to detect, Failing that, just create an issue with the user agent you have found, and we'll take it from there :) ### Laravel Package -If you would like to use this with Laravel 4/5, please see [Laravel-Crawler-Detect](https://github.com/JayBizzle/Laravel-Crawler-Detect) +If you would like to use this with Laravel, please see [Laravel-Crawler-Detect](https://github.com/JayBizzle/Laravel-Crawler-Detect) ### Symfony Bundle To use this library with Symfony 2/3/4, check out the [CrawlerDetectBundle](https://github.com/nicolasmure/CrawlerDetectBundle). @@ -57,16 +56,21 @@ To use this library with the YII2 framework, check out [yii2-crawler-detect](htt ### ES6 Library To use this library with NodeJS or any ES6 application based, check out [es6-crawler-detect](https://github.com/JefferyHus/es6-crawler-detect). +### Python Library +To use this library in a Python project, check out [crawlerdetect](https://github.com/moskrc/CrawlerDetect). + +### JVM Library (written in Java) +To use this library in a JVM project (including Java, Scala, Kotlin, etc.), check out [CrawlerDetect](https://github.com/nekosoftllc/crawler-detect). + ### .NET Library To use this library in a .net standard (including .net core) based project, check out [NetCrawlerDetect](https://github.com/gplumb/NetCrawlerDetect). -### Nette Extension -To use this library with the Nette framework, checkout [NetteCrawlerDetect](https://github.com/JanGalek/Crawler-Detect). - ### Ruby Gem - To use this library with Ruby on Rails or any Ruby-based application, check out [crawler_detect](https://github.com/loadkpi/crawler_detect) gem. +### Go Module +To use this library with Go, check out the [crawlerdetect](https://github.com/x-way/crawlerdetect) module. + _Parts of this class are based on the brilliant [MobileDetect](https://github.com/serbanghita/Mobile-Detect)_ [![Analytics](https://ga-beacon.appspot.com/UA-72430465-1/Crawler-Detect/readme?pixel)](https://github.com/JayBizzle/Crawler-Detect) diff --git a/blockbot/vendor/jaybizzle/crawler-detect/composer.json b/blockbot/vendor/jaybizzle/crawler-detect/composer.json index 0c0babe6..4774117e 100755 --- a/blockbot/vendor/jaybizzle/crawler-detect/composer.json +++ b/blockbot/vendor/jaybizzle/crawler-detect/composer.json @@ -16,8 +16,7 @@ "php": ">=5.3.0" }, "require-dev": { - "phpunit/phpunit": "^4.8|^5.5|^6.5", - "satooshi/php-coveralls": "1.*" + "phpunit/phpunit": "^4.8|^5.5|^6.5|^9.4" }, "autoload": { "psr-4": { diff --git a/blockbot/vendor/jaybizzle/crawler-detect/export.php b/blockbot/vendor/jaybizzle/crawler-detect/export.php index 4c4b9d5d..6c7459c4 100644 --- a/blockbot/vendor/jaybizzle/crawler-detect/export.php +++ b/blockbot/vendor/jaybizzle/crawler-detect/export.php @@ -37,5 +37,5 @@ function outputJson($object) function outputTxt($object) { $className = (new ReflectionClass($object))->getShortName(); - file_put_contents("raw/$className.txt", implode($object->getAll(), PHP_EOL)); + file_put_contents("raw/$className.txt", implode(PHP_EOL, $object->getAll())); } diff --git a/blockbot/vendor/jaybizzle/crawler-detect/raw/Crawlers.json b/blockbot/vendor/jaybizzle/crawler-detect/raw/Crawlers.json index a1e690eb..003b87c8 100644 --- a/blockbot/vendor/jaybizzle/crawler-detect/raw/Crawlers.json +++ b/blockbot/vendor/jaybizzle/crawler-detect/raw/Crawlers.json @@ -1 +1 @@ -[".*Java.*outbrain"," YLT","^b0t$","^bluefish ","^Calypso v\\\/","^COMODO DCV","^DangDang","^DavClnt","^FDM ","^git\\\/","^Goose\\\/","^Grabber","^HTTPClient\\\/","^Java\\\/","^Jeode\\\/","^Jetty\\\/","^Mail\\\/","^Mget","^Microsoft URL Control","^NG\\\/[0-9\\.]","^NING\\\/","^PHP\\\/[0-9]","^RMA\\\/","^Ruby|Ruby\\\/[0-9]","^VSE\\\/[0-9]","^WordPress\\.com","^XRL\\\/[0-9]","^ZmEu","008\\\/","13TABS","192\\.comAgent","2ip\\.ru","404enemy","7Siters","80legs","a\\.pr-cy\\.ru","a3logics\\.in","A6-Indexer","Abonti","Aboundex","aboutthedomain","Accoona-AI-Agent","acoon","acrylicapps\\.com\\\/pulp","Acunetix","AdAuth\\\/","adbeat","AddThis","ADmantX","AdminLabs","adressendeutschland","adscanner","Adstxtaggregator","agentslug","AHC","aihit","aiohttp\\\/","Airmail","akka-http\\\/","akula\\\/","alertra","alexa site audit","Alibaba\\.Security\\.Heimdall","Alligator","allloadin","AllSubmitter","alyze\\.info","amagit","Anarchie","AndroidDownloadManager","Anemone","AngleSharp","annotate_google","Ant\\.com","Anturis Agent","AnyEvent-HTTP\\\/","Apache Droid","Apache OpenOffice","Apache-HttpAsyncClient","Apache-HttpClient","ApacheBench","Apexoo","APIs-Google","AportWorm\\\/","AppBeat\\\/","AppEngine-Google","AppStoreScraperZ","Aprc\\\/[0-9]","Arachmo","arachnode","Arachnophilia","aria2","Arukereso","asafaweb","AskQuickly","Ask Jeeves","ASPSeek","Asterias","Astute","asynchttp","Attach","autocite","Autonomy","axios\\\/","B-l-i-t-z-B-O-T","Backlink-Ceck","backlink-check","BacklinkHttpStatus","BackStreet","BackWeb","Bad-Neighborhood","Badass","baidu\\.com","Bandit","basicstate","BatchFTP","Battleztar Bazinga","baypup\\\/","BazQux","BBBike","BCKLINKS","BDFetch","BegunAdvertising","Bidtellect","BigBozz","Bigfoot","biglotron","BingLocalSearch","BingPreview","binlar","biNu image cacher","Bitacle","biz_Directory","Black Hole","Blackboard Safeassign","BlackWidow","BlockNote\\.Net","Bloglines","Bloglovin","BlogPulseLive","BlogSearch","Blogtrottr","BlowFish","boitho\\.com-dc","BPImageWalker","Braintree-Webhooks","Branch Metrics API","Branch-Passthrough","Brandprotect","BrandVerity","Brandwatch","Brodie\\\/","Browsershots","BUbiNG","Buck\\\/","Buddy","BuiltWith","Bullseye","BunnySlippers","Burf Search","Butterfly\\\/","BuzzSumo","CAAM\\\/[0-9]","CakePHP","Calculon","Canary%20Mail","CaretNail","catexplorador","CC Metadata Scaper","Cegbfeieh","censys","Cerberian Drtrs","CERT\\.at-Statistics-Survey","cg-eye","changedetection","ChangesMeter","Charlotte","CheckHost","checkprivacy","CherryPicker","ChinaClaw","Chirp\\\/","chkme\\.com","Chlooe","Chromaxa","CirrusExplorer","CISPA Vulnerability Notification","Citoid","CJNetworkQuality","Clarsentia","clips\\.ua\\.ac\\.be","Cloud mapping","CloudEndure","CloudFlare-AlwaysOnline","Cloudinary","cmcm\\.com","coccoc","cognitiveseo","colly -","CommaFeed","Commons-HttpClient","commonscan","contactbigdatafr","contentkingapp","convera","CookieReports","copyright sheriff","CopyRightCheck","Copyscape","Cosmos4j\\.feedback","Covario-IDS","Crescent","Crowsnest","Criteo","CSHttp","curb","Curious George","curl","cuwhois\\\/","cybo\\.com","DAP\\\/NetHTTP","DareBoost","DatabaseDriverMysqli","DataCha0s","Datafeedwatch","Datanyze","DataparkSearch","dataprovider","DataXu","Daum(oa)?[ \\\/][0-9]","Demon","DeuSu","developers\\.google\\.com\\\/\\+\\\/web\\\/snippet\\\/","Devil","Digg","Digincore","DigitalPebble","Dirbuster","Discourse Forum Onebox","Disqus\\\/","Dispatch\\\/","DittoSpyder","dlvr","DMBrowser","DNSPod-reporting","docoloc","Dolphin http client","DomainAppender","Donuts Content Explorer","dotMailer content retrieval","dotSemantic","downforeveryoneorjustme","Download Wonder","downnotifier","DowntimeDetector","Drip","drupact","Drupal \\(\\+http:\\\/\\\/drupal\\.org\\\/\\)","DTS Agent","dubaiindex","EARTHCOM","Easy-Thumb","EasyDL","Ebingbong","ec2linkfinder","eCairn-Grabber","eCatch","ECCP","eContext\\\/","Ecxi","EirGrabber","ElectricMonk","elefent","EMail Exractor","EMail Wolf","EmailWolf","Embarcadero","Embed PHP Library","Embedly","endo\\\/","europarchive\\.org","evc-batch","EventMachine HttpClient","Everwall Link Expander","Evidon","Evrinid","ExactSearch","ExaleadCloudview","Excel\\\/","exif","Exploratodo","Express WebPictures","Extreme Picture Finder","EyeNetIE","ezooms","facebookexternalhit","facebookplatform","fairshare","Faraday v","fasthttp","Faveeo","Favicon downloader","faviconkit","faviconarchive","FavOrg","Feed Wrangler","Feedable\\\/","Feedbin","FeedBooster","FeedBucket","FeedBunch\\\/","FeedBurner","feeder","Feedly","FeedshowOnline","Feedspot","Feedwind\\\/","FeedZcollector","feeltiptop","Fetch API","Fetch\\\/[0-9]","Fever\\\/[0-9]","FHscan","Fimap","findlink","findthatfile","FlashGet","FlipboardBrowserProxy","FlipboardProxy","FlipboardRSS","Flock\\\/","fluffy","Flunky","flynxapp","forensiq","FoundSeoTool","http:\\\/\\\/www.neomo.de\\\/","free thumbnails","Freeuploader","Funnelback","G-i-g-a-b-o-t","g00g1e\\.net","ganarvisitas","geek-tools","Genieo","GentleSource","GetCode","Getintent","GetLinkInfo","getprismatic","GetRight","getroot","GetURLInfo\\\/","GetWeb","Ghost Inspector","GigablastOpenSource","GIS-LABS","github-camo","github\\.com","Go [\\d\\.]* package http","Go http package","Go-Ahead-Got-It","Go-http-client","Go!Zilla","gobyus","gofetch","GomezAgent","gooblog","Goodzer\\\/","Google AppsViewer","Google Desktop","Google favicon","Google Keyword Suggestion","Google Keyword Tool","Google Page Speed Insights","Google PP Default","Google Search Console","Google Web Preview","Google-Adwords","Google-Apps-Script","Google-Calendar-Importer","Google-HotelAdsVerifier","Google-HTTP-Java-Client","Google-Publisher-Plugin","Google-SearchByImage","Google-Site-Verification","Google-Structured-Data-Testing-Tool","Google-Youtube-Links","google-xrawler","GoogleDocs","GoogleHC\\\/","GoogleProducer","GoogleSites","Google-Transparency-Report","Gookey","GoScraper","GoSpotCheck","gosquared-thumbnailer","Gotit","GoZilla","grabify","GrabNet","Grafula","Grammarly","GrapeFX","GreatNews","Gregarius","GRequests","grokkit","grouphigh","grub-client","gSOAP\\\/","GT::WWW","GTmetrix","GuzzleHttp","gvfs\\\/","HAA(A)?RTLAND http client","Haansoft","hackney\\\/","Hadi Agent","HappyApps-WebCheck","Hatena","Havij","HeadlessChrome","HEADMasterSEO","HeartRails_Capture","help@dataminr\\.com","heritrix","historious","hkedcity","hledejLevne\\.cz","Hloader","HMView","Holmes","HonesoSearchEngine","HootSuite Image proxy","Hootsuite-WebFeed","hosterstats","HostTracker","ht:\\\/\\\/check","htdig","HTMLparser","htmlyse","HTTP Banner Detection","HTTP_Compression_Test","http_request2","http_requester","http-get","HTTP-Header-Abfrage","http-kit","http-request\\\/","HTTP-Tiny","HTTP::Lite","http\\.rb\\\/","http_get","HttpComponents","httphr","HTTPMon","httpRequest","httpscheck","httpssites_power","httpunit","HttpUrlConnection","httrack","huaweisymantec","HubSpot ","Humanlinks","i2kconnect\\\/","Iblog","ichiro","Id-search","IdeelaborPlagiaat","IDG Twitter Links Resolver","IDwhois\\\/","Iframely","igdeSpyder","IlTrovatore","Image Fetch","Image Sucker","ImageEngine\\\/","ImageVisu\\\/","Imagga","imagineeasy","imgsizer","InAGist","inbound\\.li parser","InDesign%20CC","Indy Library","InetURL","infegy","infohelfer","InfoTekies","InfoWizards Reciprocal Link","inpwrd\\.com","instabid","Instapaper","Integrity","integromedb","Intelliseek","InterGET","internet_archive","Internet Ninja","InternetSeer","internetVista monitor","intraVnews","IODC","IOI","iplabel","ips-agent","IPS\\\/[0-9]","IPWorks HTTP\\\/S Component","iqdb\\\/","Iria","Irokez","isitup\\.org","iskanie","isUp\\.li","iThemes Sync\\\/","iZSearch","JAHHO","janforman","Jaunt\\\/","Jbrofuzz","Jersey\\\/","JetCar","Jigsaw","Jobboerse","JobFeed discovery","Jobg8 URL Monitor","jobo","Jobrapido","Jobsearch1\\.5","JoinVision Generic","JolokiaPwn","Joomla","Jorgee","JS-Kit","JustView","Kaspersky Lab CFR link resolver","Kelny\\\/","Kerrigan\\\/","KeyCDN","Keyword Density","Keywords Research","KickFire","KimonoLabs\\\/","Kml-Google","knows\\.is","KOCMOHABT","kouio","kube-probe","kulturarw3","KumKie","L\\.webis","Larbin","Lavf\\\/","LeechFTP","LeechGet","letsencrypt","Lftp","LibVLC","LibWeb","Libwhisker","libwww","Licorne","Liferea\\\/","Lightspeedsystems","Lighthouse","Likse","Link Valet","link_thumbnailer","LinkAlarm\\\/","linkCheck","linkdex","LinkExaminer","linkfluence","linkpeek","LinkPreviewGenerator","LinkScan","LinksManager","LinkTiger","LinkWalker","Lipperhey","Litemage_walker","livedoor ScreenShot","LoadImpactRload","localsearch-web","LongURL API","looksystems\\.net","ltx71","lua-resty-http","lwp-request","lwp-trivial","LWP::Simple","lycos","LYT\\.SR","mabontland","Mag-Net","MagpieRSS","Mail\\.Ru","MailChimp","Majestic12","makecontact\\\/","Mandrill","MapperCmd","marketinggrader","MarkMonitor","MarkWatch","Mass Downloader","masscan\\\/","Mata Hari","Mediapartners-Google","mediawords","MegaIndex\\.ru","MeltwaterNews","Melvil Rawi","MemGator","Metaspinner","MetaURI","MFC_Tear_Sample","Microsearch","Microsoft Office ","Microsoft Outlook","Microsoft Windows Network Diagnostics","Microsoft-WebDAV-MiniRedir","Microsoft Data Access","MIDown tool","MIIxpc","Mindjet","Miniature\\.io","Miniflux","Mister PiX","mixdata dot com","mixed-content-scan","Mixmax-LinkPreview","mixnode","Mnogosearch","mogimogi","Mojeek","Mojolicious \\(Perl\\)","Monit\\\/","monitis","Monitority\\\/","montastic","MonTools","Moreover","Morfeus Fucking Scanner","Morning Paper","MovableType","mowser","Mrcgiguy","MS Web Services Client Protocol","MSFrontPage","mShots","MuckRack\\\/","muhstik-scan","MVAClient","MxToolbox\\\/","nagios","Najdi\\.si","Name Intelligence","Nameprotect","Navroad","NearSite","Needle","Nessus","Net Vampire","NetAnts","NETCRAFT","NetLyzer","NetMechanic","NetNewsWire","Netpursual","netresearch","NetShelter ContentScan","Netsparker","NetTrack","Netvibes","NetZIP","Neustar WPM","NeutrinoAPI","NewRelicPinger","NewsBlur .*Finder","NewsGator","newsme","newspaper\\\/","Nexgate Ruby Client","NG-Search","Nibbler","NICErsPRO","Nikto","nineconnections","NLNZ_IAHarvester","Nmap Scripting Engine","node-superagent","node-urllib","node\\.io","Nodemeter","NodePing","nominet\\.org\\.uk","nominet\\.uk","Norton-Safeweb","Notifixious","notifyninja","nuhk","nutch","Nuzzel","nWormFeedFinder","nyawc\\\/","Nymesis","NYU","Ocelli\\\/","Octopus","oegp","Offline Explorer","Offline Navigator","og-scraper","okhttp","omgili","OMSC","Online Domain Tools","OpenCalaisSemanticProxy","Openfind","OpenLinkProfiler","Openstat\\\/","OpenVAS","Optimizer","Orbiter","OrgProbe\\\/","orion-semantics","Outlook-Express","Outlook-iOS","ow\\.ly","Owler","ownCloud News","OxfordCloudService","Page Valet","page_verifier","page scorer","page2rss","PageGrabber","PagePeeker","PageScorer","Pagespeed\\\/","Panopta","panscient","Papa Foto","parsijoo","Pavuk","PayPal IPN","pcBrowser","Pcore-HTTP","Pearltrees","PECL::HTTP","peerindex","Peew","PeoplePal","Perlu -","PhantomJS Screenshoter","PhantomJS\\\/","Photon\\\/","phpservermon","Pi-Monster","Picscout","Picsearch","PictureFinder","Pimonster","ping\\.blo\\.gs","Pingability","PingAdmin\\.Ru","Pingdom","Pingoscope","PingSpot","pinterest\\.com","Pixray","Pizilla","Plagger\\\/","Ploetz \\+ Zeller","Plukkie","plumanalytics","PocketImageCache","PocketParser","Pockey","POE-Component-Client-HTTP","Polymail\\\/","Pompos","Porkbun","Port Monitor","postano","PostmanRuntime","PostPost","postrank","PowerPoint\\\/","Priceonomics Analysis Engine","PrintFriendly","PritTorrent","Prlog","probethenet","Project 25499","prospectb2b","Protopage","ProWebWalker","proximic","PRTG Network Monitor","pshtt, https scanning","PTST ","PTST\\\/[0-9]+","Pulsepoint XT3 web scraper","Pump","Python-httplib2","python-requests","Python-urllib","Qirina Hurdler","QQDownload","QrafterPro","Qseero","Qualidator","QueryN Metasearch","queuedriver","Quora Link Preview","Qwantify","Radian6","RankActive","RankFlex","RankSonicSiteAuditor","Re-re Studio","ReactorNetty","Readability","RealDownload","RealPlayer%20Downloader","RebelMouse","Recorder","RecurPost\\\/","redback\\\/","ReederForMac","ReGet","RepoMonkey","request\\.js","reqwest\\\/","ResponseCodeTest","RestSharp","Riddler","Rival IQ","Robosourcer","Robozilla","ROI Hunter","RPT-HTTPClient","RSSOwl","safe-agent-scanner","SalesIntelligent","Saleslift","Sendsay\\.Ru","SauceNAO","SBIder","scalaj-http","scan\\.lol","ScanAlert","Scoop","scooter","ScoutJet","ScoutURLMonitor","ScrapeBox Page Scanner","SimpleScraper","Scrapy","Screaming","ScreenShotService","Scrubby","Scrutiny\\\/","search\\.thunderstone","Search37","searchenginepromotionhelp","Searchestate","SearchExpress","SearchSight","Seeker","semanticdiscovery","semanticjuice","Semiocast HTTP client","Semrush","sentry\\\/","SEO Browser","Seo Servis","seo-nastroj\\.cz","seo4ajax","Seobility","SEOCentro","SeoCheck","SEOkicks","Seomoz","SEOprofiler","SEOsearch","seoscanners","seositecheckup","SEOstats","servernfo","sexsearcher","Seznam","Shelob","Shodan","Shoppimon","ShopWiki","ShortLinkTranslate","shrinktheweb","Sideqik","SimplePie","SimplyFast","Siphon","SISTRIX","Site-Shot\\\/","Site Sucker","Site24x7","SiteBar","Sitebeam","Sitebulb\\\/","SiteCondor","SiteExplorer","SiteGuardian","Siteimprove","SiteIndexed","Sitemap(s)? Generator","SitemapGenerator","SiteMonitor","Siteshooter B0t","SiteSnagger","SiteSucker","SiteTruth","Sitevigil","sitexy\\.com","SkypeUriPreview","Slack\\\/","slider\\.com","slurp","SlySearch","SmartDownload","SMRF URL Expander","SMUrlExpander","Snake","Snappy","SnapSearch","Snarfer\\\/","SniffRSS","sniptracker","Snoopy","SnowHaze Search","sogou web","SortSite","Sottopop","sovereign\\.ai","SpaceBison","SpamExperts","Spammen","Spanner","spaziodati","SPDYCheck","Specificfeeds","speedy","SPEng","Spinn3r","spray-can","Sprinklr ","spyonweb","sqlmap","Sqlworm","Sqworm","SSL Labs","ssl-tools","StackRambler","Statastico\\\/","StatusCake","Steeler","Stratagems Kumo","Stroke\\.cz","StudioFACA","StumbleUpon","suchen","Sucuri","summify","SuperHTTP","Surphace Scout","Suzuran","SwiteScraper","Symfony BrowserKit","Symfony2 BrowserKit","SynHttpClient-Built","Sysomos","sysscan","Szukacz","T0PHackTeam","tAkeOut","Tarantula\\\/","Taringa UGC","TarmotGezgin","Teleport","Telesoft","Telesphoreo","Telesphorep","Tenon\\.io","teoma","terrainformatica","Test Certificate Info","testuri","Tetrahedron","The Drop Reaper","The Expert HTML Source Viewer","The Knowledge AI","The Intraformant","theinternetrules","TheNomad","Thinklab","Thumbshots","ThumbSniper","timewe\\.net","TinEye","Tiny Tiny RSS","TLSProbe\\\/","Toata","topster","touche\\.com","Traackr\\.com","tracemyfile","Trackuity","TrapitAgent","Trendiction","Trendsmap","trendspottr","truwoGPS","TryJsoup","TulipChain","Turingos","Turnitin","tweetedtimes","Tweetminster","Tweezler\\\/","twibble","Twice","Twikle","Twingly","Twisted PageGetter","Typhoeus","ubermetrics-technologies","uclassify","UdmSearch","unchaos","unirest-java","UniversalFeedParser","Unshorten\\.It","Untiny","UnwindFetchor","updated","updown\\.io daemon","Upflow","Uptimia","Urlcheckr","URL Verifier","URLitor","urlresolver","Urlstat","URLTester","UrlTrends Ranking Updater","URLy Warning","URLy\\.Warning","Vacuum","Vagabondo","VB Project","vBSEO","VCI","via ggpht\\.com GoogleImageProxy","VidibleScraper","Virusdie","visionutils","vkShare","VoidEYE","Voil","voltron","voyager\\\/","VSAgent\\\/","VSB-TUO\\\/","Vulnbusters Meter","VYU2","w3af\\.org","W3C_Unicorn","W3C-checklink","W3C-mobileOK","WAC-OFU","Wallpapers\\\/[0-9]+","WallpapersHD","wangling","Wappalyzer","WatchMouse","WbSrch\\\/","WDT\\.io","web-capture\\.net","Web-sniffer","Web Auto","Web Collage","Web Enhancer","Web Fetch","Web Fuck","Web Pix","Web Sauger","Web Sucker","Webalta","Webauskunft","WebAuto","WebCapture","WebClient\\\/","webcollage","WebCookies","WebCopier","WebCorp","WebDataStats","WebDoc","WebEnhancer","WebFetch","WebFuck","WebGazer","WebGo IS","WebImageCollector","WebImages","WebIndex","webkit2png","WebLeacher","webmastercoffee","webmon ","WebPix","WebReaper","WebSauger","webscreenie","Webshag","Webshot","Website Quester","websitepulse agent","WebsiteQuester","Websnapr","WebSniffer","Webster","WebStripper","WebSucker","Webthumb\\\/","WebThumbnail","WebWhacker","WebZIP","WeLikeLinks","WEPA","WeSEE","wf84","Wfuzz\\\/","wget","WhatsApp","WhatsMyIP","WhatWeb","WhereGoes\\?","Whibse","WhoRunsCoinHive","Whynder Magnet","Windows-RSS-Platform","WinPodder","wkhtmlto","wmtips","Woko","woorankreview","Word\\\/","WordPress\\\/","WordupinfoSearch","wotbox","WP Engine Install Performance API","wpif","wprecon\\.com survey","WPScan","wscheck","Wtrace","WWW-Collector-E","WWW-Mechanize","WWW::Document","WWW::Mechanize","www\\.monitor\\.us","WWWOFFLE","x09Mozilla","x22Mozilla","XaxisSemanticsClassifier","Xenu Link Sleuth","XING-contenttabreceiver","xpymep([0-9]?)\\.exe","Y!J-(ASR|BSC)","Y\\!J-BRW","Yaanb","yacy","Yahoo Link Preview","YahooCacheSystem","YahooYSMcm","YandeG","Yandex(?!Search)","yanga","yeti","Yo-yo","Yoleo Consumer","yoogliFetchAgent","YottaaMonitor","Your-Website-Sucks","yourls\\.org","YoYs\\.net","YP\\.PL","Zabbix","Zade","Zao","Zauba","Zemanta Aggregator","Zend_Http_Client","Zend\\\\Http\\\\Client","Zermelo","Zeus ","zgrab","ZnajdzFoto","Zombie\\.js","Zoom\\.Mac","ZyBorg","[a-z0-9\\-_]*(bot|crawl|archiver|transcoder|spider|uptime|validator|fetcher|cron|checker|reader|extractor|monitoring|analyzer)"] \ No newline at end of file +[" YLT","^Aether","^Amazon Simple Notification Service Agent$","^Amazon-Route53-Health-Check-Service","^b0t$","^bluefish ","^Calypso v\\\/","^COMODO DCV","^Corax","^DangDang","^DavClnt","^DHSH","^docker\\\/[0-9]","^Expanse","^FDM ","^git\\\/","^Goose\\\/","^Grabber","^Gradle\\\/","^HTTPClient\\\/","^HTTPing","^Java\\\/","^Jeode\\\/","^Jetty\\\/","^Mail\\\/","^Mget","^Microsoft URL Control","^Mikrotik\\\/","^Netlab360","^NG\\\/[0-9\\.]","^NING\\\/","^npm\\\/","^Nuclei","^PHP-AYMAPI\\\/","^PHP\\\/","^pip\\\/","^pnpm\\\/","^RMA\\\/","^Ruby|Ruby\\\/[0-9]","^Swurl ","^TLS tester ","^twine\\\/","^ureq","^VSE\\\/[0-9]","^WordPress\\.com","^XRL\\\/[0-9]","^ZmEu","008\\\/","13TABS","192\\.comAgent","2GDPR\\\/","2ip\\.ru","404enemy","7Siters","80legs","a3logics\\.in","A6-Indexer","Abonti","Aboundex","aboutthedomain","Accoona-AI-Agent","acebookexternalhit\\\/","acoon","acrylicapps\\.com\\\/pulp","Acunetix","AdAuth\\\/","adbeat","AddThis","ADmantX","AdminLabs","adressendeutschland","adreview\\\/","adscanner","adstxt-worker","Adstxtaggregator","adstxt\\.com","Adyen HttpClient","AffiliateLabz\\\/","affilimate-puppeteer","agentslug","AHC","aihit","aiohttp\\\/","Airmail","akka-http\\\/","akula\\\/","alertra","alexa site audit","Alibaba\\.Security\\.Heimdall","Alligator","allloadin","AllSubmitter","alyze\\.info","amagit","Anarchie","AndroidDownloadManager","Anemone","AngleSharp","annotate_google","Anthill","Anturis Agent","Ant\\.com","AnyEvent-HTTP\\\/","Apache Ant\\\/","Apache Droid","Apache OpenOffice","Apache-HttpAsyncClient","Apache-HttpClient","ApacheBench","Apexoo","apimon\\.de","APIs-Google","AportWorm\\\/","AppBeat\\\/","AppEngine-Google","AppleSyndication","Aprc\\\/[0-9]","Arachmo","arachnode","Arachnophilia","aria2","Arukereso","asafaweb","Asana\\\/","Ask Jeeves","AskQuickly","ASPSeek","Asterias","Astute","asynchttp","Attach","attohttpc","autocite","AutomaticWPTester","Autonomy","awin\\.com","AWS Security Scanner","axios\\\/","a\\.pr-cy\\.ru","B-l-i-t-z-B-O-T","Backlink-Ceck","backlink-check","BacklinkHttpStatus","BackStreet","BackupLand","BackWeb","Bad-Neighborhood","Badass","baidu\\.com","Bandit","basicstate","BatchFTP","Battleztar Bazinga","baypup\\\/","BazQux","BBBike","BCKLINKS","BDFetch","BegunAdvertising","Bewica-security-scan","Bidtellect","BigBozz","Bigfoot","biglotron","BingLocalSearch","BingPreview","binlar","biNu image cacher","Bitacle","Bitrix link preview","biz_Directory","BKCTwitterUnshortener\\\/","Black Hole","Blackboard Safeassign","BlackWidow","BlockNote\\.Net","BlogBridge","Bloglines","Bloglovin","BlogPulseLive","BlogSearch","Blogtrottr","BlowFish","boitho\\.com-dc","Boost\\.Beast","BPImageWalker","Braintree-Webhooks","Branch Metrics API","Branch-Passthrough","Brandprotect","BrandVerity","Brandwatch","Brodie\\\/","Browsershots","BUbiNG","Buck\\\/","Buddy","BuiltWith","Bullseye","BunnySlippers","Burf Search","Butterfly\\\/","BuzzSumo","CAAM\\\/[0-9]","CakePHP","Calculon","Canary%20Mail","CaretNail","catexplorador","CC Metadata Scaper","Cegbfeieh","censys","centuryb.o.t9[at]gmail.com","Cerberian Drtrs","CERT\\.at-Statistics-Survey","cf-facebook","cg-eye","changedetection","ChangesMeter","Charlotte","chatterino-api-cache","CheckHost","checkprivacy","CherryPicker","ChinaClaw","Chirp\\\/","chkme\\.com","Chlooe","Chromaxa","CirrusExplorer","CISPA Vulnerability Notification","CISPA Web Analyser","Citoid","CJNetworkQuality","Clarsentia","clips\\.ua\\.ac\\.be","Cloud mapping","CloudEndure","CloudFlare-AlwaysOnline","Cloudflare-Healthchecks","Cloudinary","cmcm\\.com","coccoc","cognitiveseo","ColdFusion","colly -","CommaFeed","Commons-HttpClient","commonscan","contactbigdatafr","contentkingapp","Contextual Code Sites Explorer","convera","CookieReports","copyright sheriff","CopyRightCheck","Copyscape","cortex\\\/","Cosmos4j\\.feedback","Covario-IDS","Craw\\\/","Crescent","Criteo","Crowsnest","CSHttp","CSSCheck","Cula\\\/","curb","Curious George","curl","cuwhois\\\/","cybo\\.com","DAP\\\/NetHTTP","DareBoost","DatabaseDriverMysqli","DataCha0s","DatadogSynthetics","Datafeedwatch","Datanyze","DataparkSearch","dataprovider","DataXu","Daum(oa)?[ \\\/][0-9]","dBpoweramp","ddline","deeris","delve\\.ai","Demon","DeuSu","developers\\.google\\.com\\\/\\+\\\/web\\\/snippet\\\/","Devil","Digg","Digincore","DigitalPebble","Dirbuster","Discourse Forum Onebox","Dispatch\\\/","Disqus\\\/","DittoSpyder","dlvr","DMBrowser","DNSPod-reporting","docoloc","Dolphin http client","DomainAppender","DomainLabz","Domains Project\\\/","Donuts Content Explorer","dotMailer content retrieval","dotSemantic","downforeveryoneorjustme","Download Wonder","downnotifier","DowntimeDetector","Drip","drupact","Drupal \\(\\+http:\\\/\\\/drupal\\.org\\\/\\)","DTS Agent","dubaiindex","DuplexWeb-Google","DynatraceSynthetic","EARTHCOM","Easy-Thumb","EasyDL","Ebingbong","ec2linkfinder","eCairn-Grabber","eCatch","ECCP","eContext\\\/","Ecxi","EirGrabber","ElectricMonk","elefent","EMail Exractor","EMail Wolf","EmailWolf","Embarcadero","Embed PHP Library","Embedly","endo\\\/","europarchive\\.org","evc-batch","EventMachine HttpClient","Everwall Link Expander","Evidon","Evrinid","ExactSearch","ExaleadCloudview","Excel\\\/","exif","ExoRank","Exploratodo","Express WebPictures","Extreme Picture Finder","EyeNetIE","ezooms","facebookexternalhit","facebookexternalua","facebookplatform","fairshare","Faraday v","fasthttp","Faveeo","Favicon downloader","faviconarchive","faviconkit","FavOrg","Feed Wrangler","Feedable\\\/","Feedbin","FeedBooster","FeedBucket","FeedBunch\\\/","FeedBurner","feeder","Feedly","FeedshowOnline","Feedshow\\\/","Feedspot","FeedViewer\\\/","Feedwind\\\/","FeedZcollector","feeltiptop","Fetch API","Fetch\\\/[0-9]","Fever\\\/[0-9]","FHscan","Fiery%20Feeds","Filestack","Fimap","findlink","findthatfile","FlashGet","FlipboardBrowserProxy","FlipboardProxy","FlipboardRSS","Flock\\\/","Florienzh\\\/","fluffy","Flunky","flynxapp","forensiq","ForusP","FoundSeoTool","fragFINN\\.de","free thumbnails","Freeuploader","FreshRSS","frontman","Funnelback","Fuzz Faster U Fool","G-i-g-a-b-o-t","g00g1e\\.net","ganarvisitas","gdnplus\\.com","geek-tools","Genieo","GentleSource","GetCode","Getintent","GetLinkInfo","getprismatic","GetRight","getroot","GetURLInfo\\\/","GetWeb","Geziyor","Ghost Inspector","GigablastOpenSource","GIS-LABS","github-camo","GitHub-Hookshot","github\\.com","Go http package","Go [\\d\\.]* package http","Go!Zilla","Go-Ahead-Got-It","Go-http-client","go-mtasts\\\/","gobuster","gobyus","Gofeed","gofetch","Goldfire Server","GomezAgent","gooblog","Goodzer\\\/","Google AppsViewer","Google Desktop","Google favicon","Google Keyword Suggestion","Google Keyword Tool","Google Page Speed Insights","Google PP Default","Google Search Console","Google Web Preview","Google-Ads-Creatives-Assistant","Google-Ads-Overview","Google-Adwords","Google-Apps-Script","Google-Calendar-Importer","Google-HotelAdsVerifier","Google-HTTP-Java-Client","Google-InspectionTool","Google-Podcast","Google-Publisher-Plugin","Google-Read-Aloud","Google-SearchByImage","Google-Site-Verification","Google-SMTP-STS","Google-speakr","Google-Structured-Data-Testing-Tool","Google-Transparency-Report","google-xrawler","Google-Youtube-Links","GoogleDocs","GoogleHC\\\/","GoogleProber","GoogleProducer","GoogleSites","Gookey","GoSpotCheck","gosquared-thumbnailer","Gotit","GoZilla","grabify","GrabNet","Grafula","Grammarly","GrapeFX","GreatNews","Gregarius","GRequests","grokkit","grouphigh","grub-client","gSOAP\\\/","GT::WWW","GTmetrix","GuzzleHttp","gvfs\\\/","HAA(A)?RTLAND http client","Haansoft","hackney\\\/","Hadi Agent","HappyApps-WebCheck","Hardenize","Hatena","Havij","HaxerMen","HeadlessChrome","HEADMasterSEO","HeartRails_Capture","help@dataminr\\.com","heritrix","Hexometer","historious","hkedcity","hledejLevne\\.cz","Hloader","HMView","Holmes","HonesoSearchEngine","HootSuite Image proxy","Hootsuite-WebFeed","hosterstats","HostTracker","ht:\\\/\\\/check","htdig","HTMLparser","htmlyse","HTTP Banner Detection","http-get","HTTP-Header-Abfrage","http-kit","http-request\\\/","HTTP-Tiny","HTTP::Lite","http:\\\/\\\/www.neomo.de\\\/","HttpComponents","httphr","HTTPie","HTTPMon","httpRequest","httpscheck","httpssites_power","httpunit","HttpUrlConnection","http\\.rb\\\/","HTTP_Compression_Test","http_get","http_request2","http_requester","httrack","huaweisymantec","HubSpot ","HubSpot-Link-Resolver","Humanlinks","i2kconnect\\\/","Iblog","ichiro","Id-search","IdeelaborPlagiaat","IDG Twitter Links Resolver","IDwhois\\\/","Iframely","igdeSpyder","iGooglePortal","IlTrovatore","Image Fetch","Image Sucker","ImageEngine\\\/","ImageVisu\\\/","Imagga","imagineeasy","imgsizer","InAGist","inbound\\.li parser","InDesign%20CC","Indy Library","InetURL","infegy","infohelfer","InfoTekies","InfoWizards Reciprocal Link","inpwrd\\.com","instabid","Instapaper","Integrity","integromedb","Intelliseek","InterGET","Internet Ninja","InternetSeer","internetVista monitor","internetwache","internet_archive","intraVnews","IODC","IOI","Inboxb0t","iplabel","ips-agent","IPS\\\/[0-9]","IPWorks HTTP\\\/S Component","iqdb\\\/","Iria","Irokez","isitup\\.org","iskanie","isUp\\.li","iThemes Sync\\\/","IZaBEE","iZSearch","JAHHO","janforman","Jaunt\\\/","Java.*outbrain","javelin\\.io","Jbrofuzz","Jersey\\\/","JetCar","Jigsaw","Jobboerse","JobFeed discovery","Jobg8 URL Monitor","jobo","Jobrapido","Jobsearch1\\.5","JoinVision Generic","JolokiaPwn","Joomla","Jorgee","JS-Kit","JungleKeyThumbnail","JustView","Kaspersky Lab CFR link resolver","Kelny\\\/","Kerrigan\\\/","KeyCDN","Keyword Density","Keywords Research","khttp\\\/","KickFire","KimonoLabs\\\/","Kml-Google","knows\\.is","KOCMOHABT","kouio","kube-probe","kubectl","kulturarw3","KumKie","Larbin","Lavf\\\/","leakix\\.net","LeechFTP","LeechGet","letsencrypt","Lftp","LibVLC","LibWeb","Libwhisker","libwww","Licorne","Liferea\\\/","Lighthouse","Lightspeedsystems","Likse","limber\\.io","Link Valet","LinkAlarm\\\/","LinkAnalyser","linkCheck","linkdex","LinkExaminer","linkfluence","linkpeek","LinkPreview","LinkScan","LinksManager","LinkTiger","LinkWalker","link_thumbnailer","Lipperhey","Litemage_walker","livedoor ScreenShot","LoadImpactRload","localsearch-web","LongURL API","longurl-r-package","looid\\.com","looksystems\\.net","ltx71","lua-resty-http","Lucee \\(CFML Engine\\)","Lush Http Client","lwp-request","lwp-trivial","LWP::Simple","lycos","LYT\\.SR","L\\.webis","mabontland","MacOutlook\\\/","Mag-Net","MagpieRSS","Mail::STS","MailChimp","Mail\\.Ru","Majestic12","makecontact\\\/","Mandrill","MapperCmd","marketinggrader","MarkMonitor","MarkWatch","Mass Downloader","masscan\\\/","Mata Hari","mattermost","Mediametric","Mediapartners-Google","mediawords","MegaIndex\\.ru","MeltwaterNews","Melvil Rawi","MemGator","Metaspinner","MetaURI","MFC_Tear_Sample","Microsearch","Microsoft Data Access","Microsoft Office","Microsoft Outlook","Microsoft Windows Network Diagnostics","Microsoft-WebDAV-MiniRedir","Microsoft\\.Data\\.Mashup","MIDown tool","MIIxpc","Mindjet","Miniature\\.io","Miniflux","mio_httpc","Miro-HttpClient","Mister PiX","mixdata dot com","mixed-content-scan","mixnode","Mnogosearch","mogimogi","Mojeek","Mojolicious \\(Perl\\)","Mollie","monitis","Monitority\\\/","Monit\\\/","montastic","MonTools","Moreover","Morfeus Fucking Scanner","Morning Paper","MovableType","mowser","Mrcgiguy","Mr\\.4x3 Powered","MS Web Services Client Protocol","MSFrontPage","mShots","MuckRack\\\/","muhstik-scan","MVAClient","MxToolbox\\\/","myseosnapshot","nagios","Najdi\\.si","Name Intelligence","NameFo\\.com","Nameprotect","nationalarchives","Navroad","NearSite","Needle","Nessus","Net Vampire","NetAnts","NETCRAFT","NetLyzer","NetMechanic","NetNewsWire","Netpursual","netresearch","NetShelter ContentScan","Netsparker","NetSystemsResearch","nettle","NetTrack","Netvibes","NetZIP","Neustar WPM","NeutrinoAPI","NewRelicPinger","NewsBlur .*Finder","NewsGator","newsme","newspaper\\\/","Nexgate Ruby Client","NG-Search","nghttp2","Nibbler","NICErsPRO","NihilScio","Nikto","nineconnections","NLNZ_IAHarvester","Nmap Scripting Engine","node-fetch","node-superagent","node-urllib","Nodemeter","NodePing","node\\.io","nominet\\.org\\.uk","nominet\\.uk","Norton-Safeweb","Notifixious","notifyninja","NotionEmbedder","nuhk","nutch","Nuzzel","nWormFeedFinder","nyawc\\\/","Nymesis","NYU","Observatory\\\/","Ocelli\\\/","Octopus","oegp","Offline Explorer","Offline Navigator","OgScrper","okhttp","omgili","OMSC","Online Domain Tools","Open Source RSS","OpenCalaisSemanticProxy","Openfind","OpenLinkProfiler","Openstat\\\/","OpenVAS","OPPO A33","Optimizer","Orbiter","OrgProbe\\\/","orion-semantics","Outlook-Express","Outlook-iOS","Owler","Owlin","ownCloud News","ow\\.ly","OxfordCloudService","page scorer","Page Valet","page2rss","PageFreezer","PageGrabber","PagePeeker","PageScorer","Pagespeed\\\/","PageThing","page_verifier","Panopta","panscient","Papa Foto","parsijoo","Pavuk","PayPal IPN","pcBrowser","Pcore-HTTP","PDF24 URL To PDF","Pearltrees","PECL::HTTP","peerindex","Peew","PeoplePal","Perlu -","PhantomJS Screenshoter","PhantomJS\\\/","Photon\\\/","php-requests","phpservermon","Pi-Monster","Picscout","Picsearch","PictureFinder","Pimonster","Pingability","PingAdmin\\.Ru","Pingdom","Pingoscope","PingSpot","ping\\.blo\\.gs","pinterest\\.com","Pixray","Pizilla","Plagger\\\/","Pleroma ","Ploetz \\+ Zeller","Plukkie","plumanalytics","PocketImageCache","PocketParser","Pockey","PodcastAddict\\\/","POE-Component-Client-HTTP","Polymail\\\/","Pompos","Porkbun","Port Monitor","postano","postfix-mta-sts-resolver","PostmanRuntime","postplanner\\.com","PostPost","postrank","PowerPoint\\\/","Prebid","Prerender","Priceonomics Analysis Engine","PrintFriendly","PritTorrent","Prlog","probethenet","Project ?25499","Project-Resonance","prospectb2b","Protopage","ProWebWalker","proximic","PRTG Network Monitor","pshtt, https scanning","PTST ","PTST\\\/[0-9]+","Pump","Python-httplib2","python-httpx","python-requests","Python-urllib","Qirina Hurdler","QQDownload","QrafterPro","Qseero","Qualidator","QueryN Metasearch","queuedriver","quic-go-HTTP\\\/","QuiteRSS","Quora Link Preview","Qwantify","Radian6","RadioPublicImageResizer","Railgun\\\/","RankActive","RankFlex","RankSonicSiteAuditor","RapidLoad\\\/","Re-re Studio","ReactorNetty","Readability","RealDownload","RealPlayer%20Downloader","RebelMouse","Recorder","RecurPost\\\/","redback\\\/","ReederForMac","Reeder\\\/","ReGet","RepoMonkey","request\\.js","reqwest\\\/","ResponseCodeTest","RestSharp","Riddler","Rival IQ","Robosourcer","Robozilla","ROI Hunter","RPT-HTTPClient","RSSMix\\\/","RSSOwl","RyowlEngine","safe-agent-scanner","SalesIntelligent","Saleslift","SAP NetWeaver Application Server","SauceNAO","SBIder","sc-downloader","scalaj-http","Scamadviser-Frontend","ScanAlert","scan\\.lol","Scoop","scooter","ScopeContentAG-HTTP-Client","ScoutJet","ScoutURLMonitor","ScrapeBox Page Scanner","Scrapy","Screaming","ScreenShotService","Scrubby","Scrutiny\\\/","Search37","searchenginepromotionhelp","Searchestate","SearchExpress","SearchSight","SearchWP","search\\.thunderstone","Seeker","semanticdiscovery","semanticjuice","Semiocast HTTP client","Semrush","Sendsay\\.Ru","sentry\\\/","SEO Browser","Seo Servis","seo-nastroj\\.cz","seo4ajax","Seobility","SEOCentro","SeoCheck","seocompany","SEOkicks","SEOlizer","Seomoz","SEOprofiler","seoscanners","SEOsearch","seositecheckup","SEOstats","servernfo","sexsearcher","Seznam","Shelob","Shodan","Shoppimon","ShopWiki","ShortLinkTranslate","shortURL lengthener","shrinktheweb","Sideqik","Siege","SimplePie","SimplyFast","Siphon","SISTRIX","Site Sucker","Site-Shot\\\/","Site24x7","SiteBar","Sitebeam","Sitebulb\\\/","SiteCondor","SiteExplorer","SiteGuardian","Siteimprove","SiteIndexed","Sitemap(s)? Generator","SitemapGenerator","SiteMonitor","Siteshooter B0t","SiteSnagger","SiteSucker","SiteTruth","Sitevigil","sitexy\\.com","SkypeUriPreview","Slack\\\/","sli-systems\\.com","slider\\.com","slurp","SlySearch","SmartDownload","SMRF URL Expander","SMUrlExpander","Snake","Snappy","SnapSearch","Snarfer\\\/","SniffRSS","sniptracker","Snoopy","SnowHaze Search","sogou web","SortSite","Sottopop","sovereign\\.ai","SpaceBison","SpamExperts","Spammen","Spanner","Spawning-AI","spaziodati","SPDYCheck","Specificfeeds","SpeedKit","speedy","SPEng","Spinn3r","spray-can","Sprinklr ","spyonweb","sqlmap","Sqlworm","Sqworm","SSL Labs","ssl-tools","StackRambler","Statastico\\\/","Statically-","StatusCake","Steeler","Stratagems Kumo","Stripe\\\/","Stroke\\.cz","StudioFACA","StumbleUpon","suchen","Sucuri","summify","SuperHTTP","Surphace Scout","Suzuran","swcd ","Symfony BrowserKit","Symfony2 BrowserKit","Synapse\\\/","Syndirella\\\/","SynHttpClient-Built","Sysomos","sysscan","Szukacz","T0PHackTeam","tAkeOut","Tarantula\\\/","Taringa UGC","TarmotGezgin","tchelebi\\.io","techiaith\\.cymru","Teleport","Telesoft","Telesphoreo","Telesphorep","Tenon\\.io","teoma","terrainformatica","Test Certificate Info","testuri","Tetrahedron","TextRazor Downloader","The Drop Reaper","The Expert HTML Source Viewer","The Intraformant","The Knowledge AI","theinternetrules","TheNomad","Thinklab","Thumbor","Thumbshots","ThumbSniper","timewe\\.net","TinEye","Tiny Tiny RSS","TLSProbe\\\/","Toata","topster","touche\\.com","Traackr\\.com","tracemyfile","Trackuity","TrapitAgent","Trendiction","Trendsmap","trendspottr","truwoGPS","TryJsoup","TulipChain","Turingos","Turnitin","tweetedtimes","Tweetminster","Tweezler\\\/","twibble","Twice","Twikle","Twingly","Twisted PageGetter","Typhoeus","ubermetrics-technologies","uclassify","UdmSearch","ultimate_sitemap_parser","unchaos","unirest-java","UniversalFeedParser","unshortenit","Unshorten\\.It","Untiny","UnwindFetchor","updated","updown\\.io daemon","Upflow","Uptimia","URL Verifier","Urlcheckr","URLitor","urlresolver","Urlstat","URLTester","UrlTrends Ranking Updater","URLy Warning","URLy\\.Warning","URL\\\/Emacs","Vacuum","Vagabondo","VB Project","vBSEO","VCI","via ggpht\\.com GoogleImageProxy","Virusdie","visionutils","Visual Rights Group","vkShare","VoidEYE","Voil","voltron","voyager\\\/","VSAgent\\\/","VSB-TUO\\\/","Vulnbusters Meter","VYU2","w3af\\.org","W3C-checklink","W3C-mobileOK","W3C_Unicorn","WAC-OFU","WakeletLinkExpander","WallpapersHD","Wallpapers\\\/[0-9]+","wangling","Wappalyzer","WatchMouse","WbSrch\\\/","WDT\\.io","Web Auto","Web Collage","Web Enhancer","Web Fetch","Web Fuck","Web Pix","Web Sauger","Web spyder","Web Sucker","web-capture\\.net","Web-sniffer","Webalta","Webauskunft","WebAuto","WebCapture","WebClient\\\/","webcollage","WebCookies","WebCopier","WebCorp","WebDataStats","WebDoc","WebEnhancer","WebFetch","WebFuck","WebGazer","WebGo IS","WebImageCollector","WebImages","WebIndex","webkit2png","WebLeacher","webmastercoffee","webmon ","WebPix","WebReaper","WebSauger","webscreenie","Webshag","Webshot","Website Quester","websitepulse agent","WebsiteQuester","Websnapr","WebSniffer","Webster","WebStripper","WebSucker","webtech\\\/","WebThumbnail","Webthumb\\\/","WebWhacker","WebZIP","WeLikeLinks","WEPA","WeSEE","wf84","Wfuzz\\\/","wget","WhatCMS","WhatsApp","WhatsMyIP","WhatWeb","WhereGoes\\?","Whibse","WhoAPI\\\/","WhoRunsCoinHive","Whynder Magnet","Windows-RSS-Platform","WinHttp-Autoproxy-Service","WinHTTP\\\/","WinPodder","wkhtmlto","wmtips","Woko","Wolfram HTTPClient","woorankreview","WordPress\\\/","WordupinfoSearch","Word\\\/","worldping-api","wotbox","WP Engine Install Performance API","WP Rocket","wpif","wprecon\\.com survey","WPScan","wscheck","Wtrace","WWW-Collector-E","WWW-Mechanize","WWW::Document","WWW::Mechanize","WWWOFFLE","www\\.monitor\\.us","x09Mozilla","x22Mozilla","XaxisSemanticsClassifier","XenForo\\\/","Xenu Link Sleuth","XING-contenttabreceiver","xpymep([0-9]?)\\.exe","Y!J-[A-Z][A-Z][A-Z]","Yaanb","yacy","Yahoo Link Preview","YahooCacheSystem","YahooMailProxy","YahooYSMcm","YandeG","Yandex(?!Search)","yanga","yeti","Yo-yo","Yoleo Consumer","yomins\\.com","yoogliFetchAgent","YottaaMonitor","Your-Website-Sucks","yourls\\.org","YoYs\\.net","YP\\.PL","Zabbix","Zade","Zao","Zauba","Zemanta Aggregator","Zend\\\\Http\\\\Client","Zend_Http_Client","Zermelo","Zeus ","zgrab","ZnajdzFoto","ZnHTTP","Zombie\\.js","Zoom\\.Mac","ZoteroTranslationServer","ZyBorg","[a-z0-9\\-_]*(bot|crawl|archiver|transcoder|spider|uptime|validator|fetcher|cron|checker|reader|extractor|monitoring|analyzer|scraper)"] \ No newline at end of file diff --git a/blockbot/vendor/jaybizzle/crawler-detect/raw/Crawlers.txt b/blockbot/vendor/jaybizzle/crawler-detect/raw/Crawlers.txt index 1522796e..791d08bb 100644 --- a/blockbot/vendor/jaybizzle/crawler-detect/raw/Crawlers.txt +++ b/blockbot/vendor/jaybizzle/crawler-detect/raw/Crawlers.txt @@ -1,27 +1,46 @@ -.*Java.*outbrain YLT +^Aether +^Amazon Simple Notification Service Agent$ +^Amazon-Route53-Health-Check-Service ^b0t$ ^bluefish ^Calypso v\/ ^COMODO DCV +^Corax ^DangDang ^DavClnt +^DHSH +^docker\/[0-9] +^Expanse ^FDM ^git\/ ^Goose\/ ^Grabber +^Gradle\/ ^HTTPClient\/ +^HTTPing ^Java\/ ^Jeode\/ ^Jetty\/ ^Mail\/ ^Mget ^Microsoft URL Control +^Mikrotik\/ +^Netlab360 ^NG\/[0-9\.] ^NING\/ -^PHP\/[0-9] +^npm\/ +^Nuclei +^PHP-AYMAPI\/ +^PHP\/ +^pip\/ +^pnpm\/ ^RMA\/ ^Ruby|Ruby\/[0-9] +^Swurl +^TLS tester +^twine\/ +^ureq ^VSE\/[0-9] ^WordPress\.com ^XRL\/[0-9] @@ -29,17 +48,18 @@ 008\/ 13TABS 192\.comAgent +2GDPR\/ 2ip\.ru 404enemy 7Siters 80legs -a\.pr-cy\.ru a3logics\.in A6-Indexer Abonti Aboundex aboutthedomain Accoona-AI-Agent +acebookexternalhit\/ acoon acrylicapps\.com\/pulp Acunetix @@ -49,8 +69,14 @@ AddThis ADmantX AdminLabs adressendeutschland +adreview\/ adscanner +adstxt-worker Adstxtaggregator +adstxt\.com +Adyen HttpClient +AffiliateLabz\/ +affilimate-puppeteer agentslug AHC aihit @@ -71,20 +97,23 @@ AndroidDownloadManager Anemone AngleSharp annotate_google -Ant\.com +Anthill Anturis Agent +Ant\.com AnyEvent-HTTP\/ +Apache Ant\/ Apache Droid Apache OpenOffice Apache-HttpAsyncClient Apache-HttpClient ApacheBench Apexoo +apimon\.de APIs-Google AportWorm\/ AppBeat\/ AppEngine-Google -AppStoreScraperZ +AppleSyndication Aprc\/[0-9] Arachmo arachnode @@ -92,21 +121,28 @@ Arachnophilia aria2 Arukereso asafaweb -AskQuickly +Asana\/ Ask Jeeves +AskQuickly ASPSeek Asterias Astute asynchttp Attach +attohttpc autocite +AutomaticWPTester Autonomy +awin\.com +AWS Security Scanner axios\/ +a\.pr-cy\.ru B-l-i-t-z-B-O-T Backlink-Ceck backlink-check BacklinkHttpStatus BackStreet +BackupLand BackWeb Bad-Neighborhood Badass @@ -121,6 +157,7 @@ BBBike BCKLINKS BDFetch BegunAdvertising +Bewica-security-scan Bidtellect BigBozz Bigfoot @@ -130,11 +167,14 @@ BingPreview binlar biNu image cacher Bitacle +Bitrix link preview biz_Directory +BKCTwitterUnshortener\/ Black Hole Blackboard Safeassign BlackWidow BlockNote\.Net +BlogBridge Bloglines Bloglovin BlogPulseLive @@ -142,6 +182,7 @@ BlogSearch Blogtrottr BlowFish boitho\.com-dc +Boost\.Beast BPImageWalker Braintree-Webhooks Branch Metrics API @@ -169,12 +210,15 @@ catexplorador CC Metadata Scaper Cegbfeieh censys +centuryb.o.t9[at]gmail.com Cerberian Drtrs CERT\.at-Statistics-Survey +cf-facebook cg-eye changedetection ChangesMeter Charlotte +chatterino-api-cache CheckHost checkprivacy CherryPicker @@ -185,6 +229,7 @@ Chlooe Chromaxa CirrusExplorer CISPA Vulnerability Notification +CISPA Web Analyser Citoid CJNetworkQuality Clarsentia @@ -192,27 +237,34 @@ clips\.ua\.ac\.be Cloud mapping CloudEndure CloudFlare-AlwaysOnline +Cloudflare-Healthchecks Cloudinary cmcm\.com coccoc cognitiveseo +ColdFusion colly - CommaFeed Commons-HttpClient commonscan contactbigdatafr contentkingapp +Contextual Code Sites Explorer convera CookieReports copyright sheriff CopyRightCheck Copyscape +cortex\/ Cosmos4j\.feedback Covario-IDS +Craw\/ Crescent -Crowsnest Criteo +Crowsnest CSHttp +CSSCheck +Cula\/ curb Curious George curl @@ -222,12 +274,17 @@ DAP\/NetHTTP DareBoost DatabaseDriverMysqli DataCha0s +DatadogSynthetics Datafeedwatch Datanyze DataparkSearch dataprovider DataXu Daum(oa)?[ \/][0-9] +dBpoweramp +ddline +deeris +delve\.ai Demon DeuSu developers\.google\.com\/\+\/web\/snippet\/ @@ -237,8 +294,8 @@ Digincore DigitalPebble Dirbuster Discourse Forum Onebox -Disqus\/ Dispatch\/ +Disqus\/ DittoSpyder dlvr DMBrowser @@ -246,6 +303,8 @@ DNSPod-reporting docoloc Dolphin http client DomainAppender +DomainLabz +Domains Project\/ Donuts Content Explorer dotMailer content retrieval dotSemantic @@ -258,6 +317,8 @@ drupact Drupal \(\+http:\/\/drupal\.org\/\) DTS Agent dubaiindex +DuplexWeb-Google +DynatraceSynthetic EARTHCOM Easy-Thumb EasyDL @@ -288,20 +349,22 @@ ExactSearch ExaleadCloudview Excel\/ exif +ExoRank Exploratodo Express WebPictures Extreme Picture Finder EyeNetIE ezooms facebookexternalhit +facebookexternalua facebookplatform fairshare Faraday v fasthttp Faveeo Favicon downloader -faviconkit faviconarchive +faviconkit FavOrg Feed Wrangler Feedable\/ @@ -313,7 +376,9 @@ FeedBurner feeder Feedly FeedshowOnline +Feedshow\/ Feedspot +FeedViewer\/ Feedwind\/ FeedZcollector feeltiptop @@ -321,6 +386,8 @@ Fetch API Fetch\/[0-9] Fever\/[0-9] FHscan +Fiery%20Feeds +Filestack Fimap findlink findthatfile @@ -329,18 +396,24 @@ FlipboardBrowserProxy FlipboardProxy FlipboardRSS Flock\/ +Florienzh\/ fluffy Flunky flynxapp forensiq +ForusP FoundSeoTool -http:\/\/www.neomo.de\/ +fragFINN\.de free thumbnails Freeuploader +FreshRSS +frontman Funnelback +Fuzz Faster U Fool G-i-g-a-b-o-t g00g1e\.net ganarvisitas +gdnplus\.com geek-tools Genieo GentleSource @@ -352,18 +425,24 @@ GetRight getroot GetURLInfo\/ GetWeb +Geziyor Ghost Inspector GigablastOpenSource GIS-LABS github-camo +GitHub-Hookshot github\.com -Go [\d\.]* package http Go http package +Go [\d\.]* package http +Go!Zilla Go-Ahead-Got-It Go-http-client -Go!Zilla +go-mtasts\/ +gobuster gobyus +Gofeed gofetch +Goldfire Server GomezAgent gooblog Goodzer\/ @@ -376,24 +455,31 @@ Google Page Speed Insights Google PP Default Google Search Console Google Web Preview +Google-Ads-Creatives-Assistant +Google-Ads-Overview Google-Adwords Google-Apps-Script Google-Calendar-Importer Google-HotelAdsVerifier Google-HTTP-Java-Client +Google-InspectionTool +Google-Podcast Google-Publisher-Plugin +Google-Read-Aloud Google-SearchByImage Google-Site-Verification +Google-SMTP-STS +Google-speakr Google-Structured-Data-Testing-Tool -Google-Youtube-Links +Google-Transparency-Report google-xrawler +Google-Youtube-Links GoogleDocs GoogleHC\/ +GoogleProber GoogleProducer GoogleSites -Google-Transparency-Report Gookey -GoScraper GoSpotCheck gosquared-thumbnailer Gotit @@ -419,13 +505,16 @@ Haansoft hackney\/ Hadi Agent HappyApps-WebCheck +Hardenize Hatena Havij +HaxerMen HeadlessChrome HEADMasterSEO HeartRails_Capture help@dataminr\.com heritrix +Hexometer historious hkedcity hledejLevne\.cz @@ -442,28 +531,31 @@ htdig HTMLparser htmlyse HTTP Banner Detection -HTTP_Compression_Test -http_request2 -http_requester http-get HTTP-Header-Abfrage http-kit http-request\/ HTTP-Tiny HTTP::Lite -http\.rb\/ -http_get +http:\/\/www.neomo.de\/ HttpComponents httphr +HTTPie HTTPMon httpRequest httpscheck httpssites_power httpunit HttpUrlConnection +http\.rb\/ +HTTP_Compression_Test +http_get +http_request2 +http_requester httrack huaweisymantec HubSpot +HubSpot-Link-Resolver Humanlinks i2kconnect\/ Iblog @@ -474,6 +566,7 @@ IDG Twitter Links Resolver IDwhois\/ Iframely igdeSpyder +iGooglePortal IlTrovatore Image Fetch Image Sucker @@ -498,13 +591,15 @@ Integrity integromedb Intelliseek InterGET -internet_archive Internet Ninja InternetSeer internetVista monitor +internetwache +internet_archive intraVnews IODC IOI +Inboxb0t iplabel ips-agent IPS\/[0-9] @@ -516,10 +611,13 @@ isitup\.org iskanie isUp\.li iThemes Sync\/ +IZaBEE iZSearch JAHHO janforman Jaunt\/ +Java.*outbrain +javelin\.io Jbrofuzz Jersey\/ JetCar @@ -535,6 +633,7 @@ JolokiaPwn Joomla Jorgee JS-Kit +JungleKeyThumbnail JustView Kaspersky Lab CFR link resolver Kelny\/ @@ -542,6 +641,7 @@ Kerrigan\/ KeyCDN Keyword Density Keywords Research +khttp\/ KickFire KimonoLabs\/ Kml-Google @@ -549,11 +649,12 @@ knows\.is KOCMOHABT kouio kube-probe +kubectl kulturarw3 KumKie -L\.webis Larbin Lavf\/ +leakix\.net LeechFTP LeechGet letsencrypt @@ -564,41 +665,50 @@ Libwhisker libwww Licorne Liferea\/ -Lightspeedsystems Lighthouse +Lightspeedsystems Likse +limber\.io Link Valet -link_thumbnailer LinkAlarm\/ +LinkAnalyser linkCheck linkdex LinkExaminer linkfluence linkpeek -LinkPreviewGenerator +LinkPreview LinkScan LinksManager LinkTiger LinkWalker +link_thumbnailer Lipperhey Litemage_walker livedoor ScreenShot LoadImpactRload localsearch-web LongURL API +longurl-r-package +looid\.com looksystems\.net ltx71 lua-resty-http +Lucee \(CFML Engine\) +Lush Http Client lwp-request lwp-trivial LWP::Simple lycos LYT\.SR +L\.webis mabontland +MacOutlook\/ Mag-Net MagpieRSS -Mail\.Ru +Mail::STS MailChimp +Mail\.Ru Majestic12 makecontact\/ Mandrill @@ -609,6 +719,8 @@ MarkWatch Mass Downloader masscan\/ Mata Hari +mattermost +Mediametric Mediapartners-Google mediawords MegaIndex\.ru @@ -619,28 +731,31 @@ Metaspinner MetaURI MFC_Tear_Sample Microsearch -Microsoft Office +Microsoft Data Access +Microsoft Office Microsoft Outlook Microsoft Windows Network Diagnostics Microsoft-WebDAV-MiniRedir -Microsoft Data Access +Microsoft\.Data\.Mashup MIDown tool MIIxpc Mindjet Miniature\.io Miniflux +mio_httpc +Miro-HttpClient Mister PiX mixdata dot com mixed-content-scan -Mixmax-LinkPreview mixnode Mnogosearch mogimogi Mojeek Mojolicious \(Perl\) -Monit\/ +Mollie monitis Monitority\/ +Monit\/ montastic MonTools Moreover @@ -649,6 +764,7 @@ Morning Paper MovableType mowser Mrcgiguy +Mr\.4x3 Powered MS Web Services Client Protocol MSFrontPage mShots @@ -656,10 +772,13 @@ MuckRack\/ muhstik-scan MVAClient MxToolbox\/ +myseosnapshot nagios Najdi\.si Name Intelligence +NameFo\.com Nameprotect +nationalarchives Navroad NearSite Needle @@ -674,6 +793,8 @@ Netpursual netresearch NetShelter ContentScan Netsparker +NetSystemsResearch +nettle NetTrack Netvibes NetZIP @@ -686,22 +807,26 @@ newsme newspaper\/ Nexgate Ruby Client NG-Search +nghttp2 Nibbler NICErsPRO +NihilScio Nikto nineconnections NLNZ_IAHarvester Nmap Scripting Engine +node-fetch node-superagent node-urllib -node\.io Nodemeter NodePing +node\.io nominet\.org\.uk nominet\.uk Norton-Safeweb Notifixious notifyninja +NotionEmbedder nuhk nutch Nuzzel @@ -709,39 +834,45 @@ nWormFeedFinder nyawc\/ Nymesis NYU +Observatory\/ Ocelli\/ Octopus oegp Offline Explorer Offline Navigator -og-scraper +OgScrper okhttp omgili OMSC Online Domain Tools +Open Source RSS OpenCalaisSemanticProxy Openfind OpenLinkProfiler Openstat\/ OpenVAS +OPPO A33 Optimizer Orbiter OrgProbe\/ orion-semantics Outlook-Express Outlook-iOS -ow\.ly Owler +Owlin ownCloud News +ow\.ly OxfordCloudService -Page Valet -page_verifier page scorer +Page Valet page2rss +PageFreezer PageGrabber PagePeeker PageScorer Pagespeed\/ +PageThing +page_verifier Panopta panscient Papa Foto @@ -750,6 +881,7 @@ Pavuk PayPal IPN pcBrowser Pcore-HTTP +PDF24 URL To PDF Pearltrees PECL::HTTP peerindex @@ -759,44 +891,52 @@ Perlu - PhantomJS Screenshoter PhantomJS\/ Photon\/ +php-requests phpservermon Pi-Monster Picscout Picsearch PictureFinder Pimonster -ping\.blo\.gs Pingability PingAdmin\.Ru Pingdom Pingoscope PingSpot +ping\.blo\.gs pinterest\.com Pixray Pizilla Plagger\/ +Pleroma Ploetz \+ Zeller Plukkie plumanalytics PocketImageCache PocketParser Pockey +PodcastAddict\/ POE-Component-Client-HTTP Polymail\/ Pompos Porkbun Port Monitor postano +postfix-mta-sts-resolver PostmanRuntime +postplanner\.com PostPost postrank PowerPoint\/ +Prebid +Prerender Priceonomics Analysis Engine PrintFriendly PritTorrent Prlog probethenet -Project 25499 +Project ?25499 +Project-Resonance prospectb2b Protopage ProWebWalker @@ -805,9 +945,9 @@ PRTG Network Monitor pshtt, https scanning PTST PTST\/[0-9]+ -Pulsepoint XT3 web scraper Pump Python-httplib2 +python-httpx python-requests Python-urllib Qirina Hurdler @@ -817,12 +957,17 @@ Qseero Qualidator QueryN Metasearch queuedriver +quic-go-HTTP\/ +QuiteRSS Quora Link Preview Qwantify Radian6 +RadioPublicImageResizer +Railgun\/ RankActive RankFlex RankSonicSiteAuditor +RapidLoad\/ Re-re Studio ReactorNetty Readability @@ -833,6 +978,7 @@ Recorder RecurPost\/ redback\/ ReederForMac +Reeder\/ ReGet RepoMonkey request\.js @@ -845,38 +991,44 @@ Robosourcer Robozilla ROI Hunter RPT-HTTPClient +RSSMix\/ RSSOwl +RyowlEngine safe-agent-scanner SalesIntelligent Saleslift -Sendsay\.Ru +SAP NetWeaver Application Server SauceNAO SBIder +sc-downloader scalaj-http -scan\.lol +Scamadviser-Frontend ScanAlert +scan\.lol Scoop scooter +ScopeContentAG-HTTP-Client ScoutJet ScoutURLMonitor ScrapeBox Page Scanner -SimpleScraper Scrapy Screaming ScreenShotService Scrubby Scrutiny\/ -search\.thunderstone Search37 searchenginepromotionhelp Searchestate SearchExpress SearchSight +SearchWP +search\.thunderstone Seeker semanticdiscovery semanticjuice Semiocast HTTP client Semrush +Sendsay\.Ru sentry\/ SEO Browser Seo Servis @@ -885,11 +1037,13 @@ seo4ajax Seobility SEOCentro SeoCheck +seocompany SEOkicks +SEOlizer Seomoz SEOprofiler -SEOsearch seoscanners +SEOsearch seositecheckup SEOstats servernfo @@ -900,14 +1054,16 @@ Shodan Shoppimon ShopWiki ShortLinkTranslate +shortURL lengthener shrinktheweb Sideqik +Siege SimplePie SimplyFast Siphon SISTRIX -Site-Shot\/ Site Sucker +Site-Shot\/ Site24x7 SiteBar Sitebeam @@ -928,6 +1084,7 @@ Sitevigil sitexy\.com SkypeUriPreview Slack\/ +sli-systems\.com slider\.com slurp SlySearch @@ -950,9 +1107,11 @@ SpaceBison SpamExperts Spammen Spanner +Spawning-AI spaziodati SPDYCheck Specificfeeds +SpeedKit speedy SPEng Spinn3r @@ -966,9 +1125,11 @@ SSL Labs ssl-tools StackRambler Statastico\/ +Statically- StatusCake Steeler Stratagems Kumo +Stripe\/ Stroke\.cz StudioFACA StumbleUpon @@ -978,9 +1139,11 @@ summify SuperHTTP Surphace Scout Suzuran -SwiteScraper +swcd Symfony BrowserKit Symfony2 BrowserKit +Synapse\/ +Syndirella\/ SynHttpClient-Built Sysomos sysscan @@ -990,6 +1153,8 @@ tAkeOut Tarantula\/ Taringa UGC TarmotGezgin +tchelebi\.io +techiaith\.cymru Teleport Telesoft Telesphoreo @@ -1000,13 +1165,15 @@ terrainformatica Test Certificate Info testuri Tetrahedron +TextRazor Downloader The Drop Reaper The Expert HTML Source Viewer -The Knowledge AI The Intraformant +The Knowledge AI theinternetrules TheNomad Thinklab +Thumbor Thumbshots ThumbSniper timewe\.net @@ -1040,9 +1207,11 @@ Typhoeus ubermetrics-technologies uclassify UdmSearch +ultimate_sitemap_parser unchaos unirest-java UniversalFeedParser +unshortenit Unshorten\.It Untiny UnwindFetchor @@ -1050,8 +1219,8 @@ updated updown\.io daemon Upflow Uptimia -Urlcheckr URL Verifier +Urlcheckr URLitor urlresolver Urlstat @@ -1059,15 +1228,16 @@ URLTester UrlTrends Ranking Updater URLy Warning URLy\.Warning +URL\/Emacs Vacuum Vagabondo VB Project vBSEO VCI via ggpht\.com GoogleImageProxy -VidibleScraper Virusdie visionutils +Visual Rights Group vkShare VoidEYE Voil @@ -1078,19 +1248,18 @@ VSB-TUO\/ Vulnbusters Meter VYU2 w3af\.org -W3C_Unicorn W3C-checklink W3C-mobileOK +W3C_Unicorn WAC-OFU -Wallpapers\/[0-9]+ +WakeletLinkExpander WallpapersHD +Wallpapers\/[0-9]+ wangling Wappalyzer WatchMouse WbSrch\/ WDT\.io -web-capture\.net -Web-sniffer Web Auto Web Collage Web Enhancer @@ -1098,7 +1267,10 @@ Web Fetch Web Fuck Web Pix Web Sauger +Web spyder Web Sucker +web-capture\.net +Web-sniffer Webalta Webauskunft WebAuto @@ -1136,8 +1308,9 @@ WebSniffer Webster WebStripper WebSucker -Webthumb\/ +webtech\/ WebThumbnail +Webthumb\/ WebWhacker WebZIP WeLikeLinks @@ -1146,24 +1319,31 @@ WeSEE wf84 Wfuzz\/ wget +WhatCMS WhatsApp WhatsMyIP WhatWeb WhereGoes\? Whibse +WhoAPI\/ WhoRunsCoinHive Whynder Magnet Windows-RSS-Platform +WinHttp-Autoproxy-Service +WinHTTP\/ WinPodder wkhtmlto wmtips Woko +Wolfram HTTPClient woorankreview -Word\/ WordPress\/ WordupinfoSearch +Word\/ +worldping-api wotbox WP Engine Install Performance API +WP Rocket wpif wprecon\.com survey WPScan @@ -1173,20 +1353,21 @@ WWW-Collector-E WWW-Mechanize WWW::Document WWW::Mechanize -www\.monitor\.us WWWOFFLE +www\.monitor\.us x09Mozilla x22Mozilla XaxisSemanticsClassifier +XenForo\/ Xenu Link Sleuth XING-contenttabreceiver xpymep([0-9]?)\.exe -Y!J-(ASR|BSC) -Y\!J-BRW +Y!J-[A-Z][A-Z][A-Z] Yaanb yacy Yahoo Link Preview YahooCacheSystem +YahooMailProxy YahooYSMcm YandeG Yandex(?!Search) @@ -1194,6 +1375,7 @@ yanga yeti Yo-yo Yoleo Consumer +yomins\.com yoogliFetchAgent YottaaMonitor Your-Website-Sucks @@ -1205,13 +1387,15 @@ Zade Zao Zauba Zemanta Aggregator -Zend_Http_Client Zend\\Http\\Client +Zend_Http_Client Zermelo Zeus zgrab ZnajdzFoto +ZnHTTP Zombie\.js Zoom\.Mac +ZoteroTranslationServer ZyBorg -[a-z0-9\-_]*(bot|crawl|archiver|transcoder|spider|uptime|validator|fetcher|cron|checker|reader|extractor|monitoring|analyzer) \ No newline at end of file +[a-z0-9\-_]*(bot|crawl|archiver|transcoder|spider|uptime|validator|fetcher|cron|checker|reader|extractor|monitoring|analyzer|scraper) \ No newline at end of file diff --git a/blockbot/vendor/jaybizzle/crawler-detect/raw/Exclusions.json b/blockbot/vendor/jaybizzle/crawler-detect/raw/Exclusions.json index a18eb985..e7e01416 100644 --- a/blockbot/vendor/jaybizzle/crawler-detect/raw/Exclusions.json +++ b/blockbot/vendor/jaybizzle/crawler-detect/raw/Exclusions.json @@ -1 +1 @@ -["Safari.[\\d\\.]*","Firefox.[\\d\\.]*"," Chrome.[\\d\\.]*","Chromium.[\\d\\.]*","MSIE.[\\d\\.]","Opera\\\/[\\d\\.]*","Mozilla.[\\d\\.]*","AppleWebKit.[\\d\\.]*","Trident.[\\d\\.]*","Windows NT.[\\d\\.]*","Android [\\d\\.]*","Macintosh.","Ubuntu","Linux","[ ]Intel","Mac OS X [\\d_]*","(like )?Gecko(.[\\d\\.]*)?","KHTML,","CriOS.[\\d\\.]*","CPU iPhone OS ([0-9_])* like Mac OS X","CPU OS ([0-9_])* like Mac OS X","iPod","compatible","x86_..","i686","x64","X11","rv:[\\d\\.]*","Version.[\\d\\.]*","WOW64","Win64","Dalvik.[\\d\\.]*"," \\.NET CLR [\\d\\.]*","Presto.[\\d\\.]*","Media Center PC","BlackBerry","Build","Opera Mini\\\/\\d{1,2}\\.\\d{1,2}\\.[\\d\\.]*\\\/\\d{1,2}\\.","Opera"," \\.NET[\\d\\.]*","cubot","; M bot","; CRONO","; B bot","; IDbot","; ID bot","; POWER BOT",";"] \ No newline at end of file +["Safari.[\\d\\.]*","Firefox.[\\d\\.]*"," Chrome.[\\d\\.]*","Chromium.[\\d\\.]*","MSIE.[\\d\\.]","Opera\\\/[\\d\\.]*","Mozilla.[\\d\\.]*","AppleWebKit.[\\d\\.]*","Trident.[\\d\\.]*","Windows NT.[\\d\\.]*","Android [\\d\\.]*","Macintosh.","Ubuntu","Linux","[ ]Intel","Mac OS X [\\d_]*","(like )?Gecko(.[\\d\\.]*)?","KHTML,","CriOS.[\\d\\.]*","CPU iPhone OS ([0-9_])* like Mac OS X","CPU OS ([0-9_])* like Mac OS X","iPod","compatible","x86_..","i686","x64","X11","rv:[\\d\\.]*","Version.[\\d\\.]*","WOW64","Win64","Dalvik.[\\d\\.]*"," \\.NET CLR [\\d\\.]*","Presto.[\\d\\.]*","Media Center PC","BlackBerry","Build","Opera Mini\\\/\\d{1,2}\\.\\d{1,2}\\.[\\d\\.]*\\\/\\d{1,2}\\.","Opera"," \\.NET[\\d\\.]*","cubot","; M bot","; CRONO","; B bot","; IDbot","; ID bot","; POWER BOT","OCTOPUS-CORE","htc_botdugls","super\\\/\\d+\\\/Android\\\/\\d+"] \ No newline at end of file diff --git a/blockbot/vendor/jaybizzle/crawler-detect/raw/Exclusions.txt b/blockbot/vendor/jaybizzle/crawler-detect/raw/Exclusions.txt index da56db9b..a44a99cb 100644 --- a/blockbot/vendor/jaybizzle/crawler-detect/raw/Exclusions.txt +++ b/blockbot/vendor/jaybizzle/crawler-detect/raw/Exclusions.txt @@ -45,4 +45,6 @@ cubot ; IDbot ; ID bot ; POWER BOT -; \ No newline at end of file +OCTOPUS-CORE +htc_botdugls +super\/\d+\/Android\/\d+ \ No newline at end of file diff --git a/blockbot/vendor/jaybizzle/crawler-detect/src/CrawlerDetect.php b/blockbot/vendor/jaybizzle/crawler-detect/src/CrawlerDetect.php index 1067976b..3ea284a7 100644 --- a/blockbot/vendor/jaybizzle/crawler-detect/src/CrawlerDetect.php +++ b/blockbot/vendor/jaybizzle/crawler-detect/src/CrawlerDetect.php @@ -20,9 +20,9 @@ class CrawlerDetect /** * The user agent. * - * @var null + * @var string|null */ - protected $userAgent = null; + protected $userAgent; /** * Headers that contain a user agent. @@ -93,7 +93,7 @@ class CrawlerDetect * Compile the regex patterns into one regex string. * * @param array - * + * * @return string */ public function compileRegex($patterns) @@ -138,7 +138,7 @@ class CrawlerDetect /** * Set the user agent. * - * @param string $userAgent + * @param string|null $userAgent */ public function setUserAgent($userAgent) { @@ -165,20 +165,14 @@ class CrawlerDetect $agent = trim(preg_replace( "/{$this->compiledExclusions}/i", '', - $userAgent ?: $this->userAgent + $userAgent ?: $this->userAgent ?: '' )); - if ($agent == '') { + if ($agent === '') { return false; } - $result = preg_match("/{$this->compiledRegex}/i", $agent, $matches); - - if ($matches) { - $this->matches = $matches; - } - - return (bool) $result; + return (bool) preg_match("/{$this->compiledRegex}/i", $agent, $this->matches); } /** @@ -190,4 +184,13 @@ class CrawlerDetect { return isset($this->matches[0]) ? $this->matches[0] : null; } + + + /** + * @return string|null + */ + public function getUserAgent() + { + return $this->userAgent; + } } diff --git a/blockbot/vendor/jaybizzle/crawler-detect/src/Fixtures/AbstractProvider.php b/blockbot/vendor/jaybizzle/crawler-detect/src/Fixtures/AbstractProvider.php index 26ea8e5f..ffe10f51 100644 --- a/blockbot/vendor/jaybizzle/crawler-detect/src/Fixtures/AbstractProvider.php +++ b/blockbot/vendor/jaybizzle/crawler-detect/src/Fixtures/AbstractProvider.php @@ -15,14 +15,14 @@ abstract class AbstractProvider { /** * The data set. - * + * * @var array */ protected $data; /** * Return the data set. - * + * * @return array */ public function getAll() diff --git a/blockbot/vendor/jaybizzle/crawler-detect/src/Fixtures/Crawlers.php b/blockbot/vendor/jaybizzle/crawler-detect/src/Fixtures/Crawlers.php index a9070565..a44edd23 100644 --- a/blockbot/vendor/jaybizzle/crawler-detect/src/Fixtures/Crawlers.php +++ b/blockbot/vendor/jaybizzle/crawler-detect/src/Fixtures/Crawlers.php @@ -19,30 +19,49 @@ class Crawlers extends AbstractProvider * @var array */ protected $data = array( - '.*Java.*outbrain', ' YLT', + '^Aether', + '^Amazon Simple Notification Service Agent$', + '^Amazon-Route53-Health-Check-Service', '^b0t$', '^bluefish ', '^Calypso v\/', '^COMODO DCV', + '^Corax', '^DangDang', '^DavClnt', + '^DHSH', + '^docker\/[0-9]', + '^Expanse', '^FDM ', '^git\/', '^Goose\/', '^Grabber', + '^Gradle\/', '^HTTPClient\/', + '^HTTPing', '^Java\/', '^Jeode\/', '^Jetty\/', '^Mail\/', '^Mget', '^Microsoft URL Control', + '^Mikrotik\/', + '^Netlab360', '^NG\/[0-9\.]', '^NING\/', - '^PHP\/[0-9]', + '^npm\/', + '^Nuclei', + '^PHP-AYMAPI\/', + '^PHP\/', + '^pip\/', + '^pnpm\/', '^RMA\/', '^Ruby|Ruby\/[0-9]', + '^Swurl ', + '^TLS tester ', + '^twine\/', + '^ureq', '^VSE\/[0-9]', '^WordPress\.com', '^XRL\/[0-9]', @@ -50,17 +69,18 @@ class Crawlers extends AbstractProvider '008\/', '13TABS', '192\.comAgent', + '2GDPR\/', '2ip\.ru', '404enemy', '7Siters', '80legs', - 'a\.pr-cy\.ru', 'a3logics\.in', 'A6-Indexer', 'Abonti', 'Aboundex', 'aboutthedomain', 'Accoona-AI-Agent', + 'acebookexternalhit\/', 'acoon', 'acrylicapps\.com\/pulp', 'Acunetix', @@ -70,8 +90,14 @@ class Crawlers extends AbstractProvider 'ADmantX', 'AdminLabs', 'adressendeutschland', + 'adreview\/', 'adscanner', + 'adstxt-worker', 'Adstxtaggregator', + 'adstxt\.com', + 'Adyen HttpClient', + 'AffiliateLabz\/', + 'affilimate-puppeteer', 'agentslug', 'AHC', 'aihit', @@ -92,20 +118,23 @@ class Crawlers extends AbstractProvider 'Anemone', 'AngleSharp', 'annotate_google', - 'Ant\.com', + 'Anthill', 'Anturis Agent', + 'Ant\.com', 'AnyEvent-HTTP\/', + 'Apache Ant\/', 'Apache Droid', 'Apache OpenOffice', 'Apache-HttpAsyncClient', 'Apache-HttpClient', 'ApacheBench', 'Apexoo', + 'apimon\.de', 'APIs-Google', 'AportWorm\/', 'AppBeat\/', 'AppEngine-Google', - 'AppStoreScraperZ', + 'AppleSyndication', 'Aprc\/[0-9]', 'Arachmo', 'arachnode', @@ -113,21 +142,28 @@ class Crawlers extends AbstractProvider 'aria2', 'Arukereso', 'asafaweb', - 'AskQuickly', + 'Asana\/', 'Ask Jeeves', + 'AskQuickly', 'ASPSeek', 'Asterias', 'Astute', 'asynchttp', 'Attach', + 'attohttpc', 'autocite', + 'AutomaticWPTester', 'Autonomy', + 'awin\.com', + 'AWS Security Scanner', 'axios\/', + 'a\.pr-cy\.ru', 'B-l-i-t-z-B-O-T', 'Backlink-Ceck', 'backlink-check', 'BacklinkHttpStatus', 'BackStreet', + 'BackupLand', 'BackWeb', 'Bad-Neighborhood', 'Badass', @@ -142,6 +178,7 @@ class Crawlers extends AbstractProvider 'BCKLINKS', 'BDFetch', 'BegunAdvertising', + 'Bewica-security-scan', 'Bidtellect', 'BigBozz', 'Bigfoot', @@ -151,11 +188,14 @@ class Crawlers extends AbstractProvider 'binlar', 'biNu image cacher', 'Bitacle', + 'Bitrix link preview', 'biz_Directory', + 'BKCTwitterUnshortener\/', 'Black Hole', 'Blackboard Safeassign', 'BlackWidow', 'BlockNote\.Net', + 'BlogBridge', 'Bloglines', 'Bloglovin', 'BlogPulseLive', @@ -163,6 +203,7 @@ class Crawlers extends AbstractProvider 'Blogtrottr', 'BlowFish', 'boitho\.com-dc', + 'Boost\.Beast', 'BPImageWalker', 'Braintree-Webhooks', 'Branch Metrics API', @@ -190,12 +231,15 @@ class Crawlers extends AbstractProvider 'CC Metadata Scaper', 'Cegbfeieh', 'censys', + 'centuryb.o.t9[at]gmail.com', 'Cerberian Drtrs', 'CERT\.at-Statistics-Survey', + 'cf-facebook', 'cg-eye', 'changedetection', 'ChangesMeter', 'Charlotte', + 'chatterino-api-cache', 'CheckHost', 'checkprivacy', 'CherryPicker', @@ -206,6 +250,7 @@ class Crawlers extends AbstractProvider 'Chromaxa', 'CirrusExplorer', 'CISPA Vulnerability Notification', + 'CISPA Web Analyser', 'Citoid', 'CJNetworkQuality', 'Clarsentia', @@ -213,27 +258,34 @@ class Crawlers extends AbstractProvider 'Cloud mapping', 'CloudEndure', 'CloudFlare-AlwaysOnline', + 'Cloudflare-Healthchecks', 'Cloudinary', 'cmcm\.com', 'coccoc', 'cognitiveseo', + 'ColdFusion', 'colly -', 'CommaFeed', 'Commons-HttpClient', 'commonscan', 'contactbigdatafr', 'contentkingapp', + 'Contextual Code Sites Explorer', 'convera', 'CookieReports', 'copyright sheriff', 'CopyRightCheck', 'Copyscape', + 'cortex\/', 'Cosmos4j\.feedback', 'Covario-IDS', + 'Craw\/', 'Crescent', - 'Crowsnest', 'Criteo', + 'Crowsnest', 'CSHttp', + 'CSSCheck', + 'Cula\/', 'curb', 'Curious George', 'curl', @@ -243,12 +295,17 @@ class Crawlers extends AbstractProvider 'DareBoost', 'DatabaseDriverMysqli', 'DataCha0s', + 'DatadogSynthetics', 'Datafeedwatch', 'Datanyze', 'DataparkSearch', 'dataprovider', 'DataXu', 'Daum(oa)?[ \/][0-9]', + 'dBpoweramp', + 'ddline', + 'deeris', + 'delve\.ai', 'Demon', 'DeuSu', 'developers\.google\.com\/\+\/web\/snippet\/', @@ -258,8 +315,8 @@ class Crawlers extends AbstractProvider 'DigitalPebble', 'Dirbuster', 'Discourse Forum Onebox', - 'Disqus\/', 'Dispatch\/', + 'Disqus\/', 'DittoSpyder', 'dlvr', 'DMBrowser', @@ -267,6 +324,8 @@ class Crawlers extends AbstractProvider 'docoloc', 'Dolphin http client', 'DomainAppender', + 'DomainLabz', + 'Domains Project\/', 'Donuts Content Explorer', 'dotMailer content retrieval', 'dotSemantic', @@ -279,6 +338,8 @@ class Crawlers extends AbstractProvider 'Drupal \(\+http:\/\/drupal\.org\/\)', 'DTS Agent', 'dubaiindex', + 'DuplexWeb-Google', + 'DynatraceSynthetic', 'EARTHCOM', 'Easy-Thumb', 'EasyDL', @@ -309,20 +370,22 @@ class Crawlers extends AbstractProvider 'ExaleadCloudview', 'Excel\/', 'exif', + 'ExoRank', 'Exploratodo', 'Express WebPictures', 'Extreme Picture Finder', 'EyeNetIE', 'ezooms', 'facebookexternalhit', + 'facebookexternalua', 'facebookplatform', 'fairshare', 'Faraday v', 'fasthttp', 'Faveeo', 'Favicon downloader', - 'faviconkit', 'faviconarchive', + 'faviconkit', 'FavOrg', 'Feed Wrangler', 'Feedable\/', @@ -334,7 +397,9 @@ class Crawlers extends AbstractProvider 'feeder', 'Feedly', 'FeedshowOnline', + 'Feedshow\/', 'Feedspot', + 'FeedViewer\/', 'Feedwind\/', 'FeedZcollector', 'feeltiptop', @@ -342,6 +407,8 @@ class Crawlers extends AbstractProvider 'Fetch\/[0-9]', 'Fever\/[0-9]', 'FHscan', + 'Fiery%20Feeds', + 'Filestack', 'Fimap', 'findlink', 'findthatfile', @@ -350,18 +417,24 @@ class Crawlers extends AbstractProvider 'FlipboardProxy', 'FlipboardRSS', 'Flock\/', + 'Florienzh\/', 'fluffy', 'Flunky', 'flynxapp', 'forensiq', + 'ForusP', 'FoundSeoTool', - 'http:\/\/www.neomo.de\/', //'Francis [Bot]' + 'fragFINN\.de', 'free thumbnails', 'Freeuploader', + 'FreshRSS', + 'frontman', 'Funnelback', + 'Fuzz Faster U Fool', 'G-i-g-a-b-o-t', 'g00g1e\.net', 'ganarvisitas', + 'gdnplus\.com', 'geek-tools', 'Genieo', 'GentleSource', @@ -373,18 +446,24 @@ class Crawlers extends AbstractProvider 'getroot', 'GetURLInfo\/', 'GetWeb', + 'Geziyor', 'Ghost Inspector', 'GigablastOpenSource', 'GIS-LABS', 'github-camo', + 'GitHub-Hookshot', 'github\.com', - 'Go [\d\.]* package http', 'Go http package', + 'Go [\d\.]* package http', + 'Go!Zilla', 'Go-Ahead-Got-It', 'Go-http-client', - 'Go!Zilla', + 'go-mtasts\/', + 'gobuster', 'gobyus', + 'Gofeed', 'gofetch', + 'Goldfire Server', 'GomezAgent', 'gooblog', 'Goodzer\/', @@ -397,24 +476,31 @@ class Crawlers extends AbstractProvider 'Google PP Default', 'Google Search Console', 'Google Web Preview', + 'Google-Ads-Creatives-Assistant', + 'Google-Ads-Overview', 'Google-Adwords', 'Google-Apps-Script', 'Google-Calendar-Importer', 'Google-HotelAdsVerifier', 'Google-HTTP-Java-Client', + 'Google-InspectionTool', + 'Google-Podcast', 'Google-Publisher-Plugin', + 'Google-Read-Aloud', 'Google-SearchByImage', 'Google-Site-Verification', + 'Google-SMTP-STS', + 'Google-speakr', 'Google-Structured-Data-Testing-Tool', - 'Google-Youtube-Links', + 'Google-Transparency-Report', 'google-xrawler', + 'Google-Youtube-Links', 'GoogleDocs', 'GoogleHC\/', + 'GoogleProber', 'GoogleProducer', 'GoogleSites', - 'Google-Transparency-Report', 'Gookey', - 'GoScraper', 'GoSpotCheck', 'gosquared-thumbnailer', 'Gotit', @@ -440,13 +526,16 @@ class Crawlers extends AbstractProvider 'hackney\/', 'Hadi Agent', 'HappyApps-WebCheck', + 'Hardenize', 'Hatena', 'Havij', + 'HaxerMen', 'HeadlessChrome', 'HEADMasterSEO', 'HeartRails_Capture', 'help@dataminr\.com', 'heritrix', + 'Hexometer', 'historious', 'hkedcity', 'hledejLevne\.cz', @@ -463,28 +552,31 @@ class Crawlers extends AbstractProvider 'HTMLparser', 'htmlyse', 'HTTP Banner Detection', - 'HTTP_Compression_Test', - 'http_request2', - 'http_requester', 'http-get', 'HTTP-Header-Abfrage', 'http-kit', 'http-request\/', 'HTTP-Tiny', 'HTTP::Lite', - 'http\.rb\/', - 'http_get', + 'http:\/\/www.neomo.de\/', //'Francis [Bot]' 'HttpComponents', 'httphr', + 'HTTPie', 'HTTPMon', 'httpRequest', 'httpscheck', 'httpssites_power', 'httpunit', 'HttpUrlConnection', + 'http\.rb\/', + 'HTTP_Compression_Test', + 'http_get', + 'http_request2', + 'http_requester', 'httrack', 'huaweisymantec', 'HubSpot ', + 'HubSpot-Link-Resolver', 'Humanlinks', 'i2kconnect\/', 'Iblog', @@ -495,6 +587,7 @@ class Crawlers extends AbstractProvider 'IDwhois\/', 'Iframely', 'igdeSpyder', + 'iGooglePortal', 'IlTrovatore', 'Image Fetch', 'Image Sucker', @@ -519,13 +612,15 @@ class Crawlers extends AbstractProvider 'integromedb', 'Intelliseek', 'InterGET', - 'internet_archive', 'Internet Ninja', 'InternetSeer', 'internetVista monitor', + 'internetwache', + 'internet_archive', 'intraVnews', 'IODC', 'IOI', + 'Inboxb0t', 'iplabel', 'ips-agent', 'IPS\/[0-9]', @@ -537,10 +632,13 @@ class Crawlers extends AbstractProvider 'iskanie', 'isUp\.li', 'iThemes Sync\/', + 'IZaBEE', 'iZSearch', 'JAHHO', 'janforman', 'Jaunt\/', + 'Java.*outbrain', + 'javelin\.io', 'Jbrofuzz', 'Jersey\/', 'JetCar', @@ -556,6 +654,7 @@ class Crawlers extends AbstractProvider 'Joomla', 'Jorgee', 'JS-Kit', + 'JungleKeyThumbnail', 'JustView', 'Kaspersky Lab CFR link resolver', 'Kelny\/', @@ -563,6 +662,7 @@ class Crawlers extends AbstractProvider 'KeyCDN', 'Keyword Density', 'Keywords Research', + 'khttp\/', 'KickFire', 'KimonoLabs\/', 'Kml-Google', @@ -570,11 +670,12 @@ class Crawlers extends AbstractProvider 'KOCMOHABT', 'kouio', 'kube-probe', + 'kubectl', 'kulturarw3', 'KumKie', - 'L\.webis', 'Larbin', 'Lavf\/', + 'leakix\.net', 'LeechFTP', 'LeechGet', 'letsencrypt', @@ -585,41 +686,50 @@ class Crawlers extends AbstractProvider 'libwww', 'Licorne', 'Liferea\/', - 'Lightspeedsystems', 'Lighthouse', + 'Lightspeedsystems', 'Likse', + 'limber\.io', 'Link Valet', - 'link_thumbnailer', 'LinkAlarm\/', + 'LinkAnalyser', 'linkCheck', 'linkdex', 'LinkExaminer', 'linkfluence', 'linkpeek', - 'LinkPreviewGenerator', + 'LinkPreview', 'LinkScan', 'LinksManager', 'LinkTiger', 'LinkWalker', + 'link_thumbnailer', 'Lipperhey', 'Litemage_walker', 'livedoor ScreenShot', 'LoadImpactRload', 'localsearch-web', 'LongURL API', + 'longurl-r-package', + 'looid\.com', 'looksystems\.net', 'ltx71', 'lua-resty-http', + 'Lucee \(CFML Engine\)', + 'Lush Http Client', 'lwp-request', 'lwp-trivial', 'LWP::Simple', 'lycos', 'LYT\.SR', + 'L\.webis', 'mabontland', + 'MacOutlook\/', 'Mag-Net', 'MagpieRSS', - 'Mail\.Ru', + 'Mail::STS', 'MailChimp', + 'Mail\.Ru', 'Majestic12', 'makecontact\/', 'Mandrill', @@ -630,6 +740,8 @@ class Crawlers extends AbstractProvider 'Mass Downloader', 'masscan\/', 'Mata Hari', + 'mattermost', + 'Mediametric', 'Mediapartners-Google', 'mediawords', 'MegaIndex\.ru', @@ -640,28 +752,31 @@ class Crawlers extends AbstractProvider 'MetaURI', 'MFC_Tear_Sample', 'Microsearch', - 'Microsoft Office ', + 'Microsoft Data Access', + 'Microsoft Office', 'Microsoft Outlook', 'Microsoft Windows Network Diagnostics', 'Microsoft-WebDAV-MiniRedir', - 'Microsoft Data Access', + 'Microsoft\.Data\.Mashup', 'MIDown tool', 'MIIxpc', 'Mindjet', 'Miniature\.io', 'Miniflux', + 'mio_httpc', + 'Miro-HttpClient', 'Mister PiX', 'mixdata dot com', 'mixed-content-scan', - 'Mixmax-LinkPreview', 'mixnode', 'Mnogosearch', 'mogimogi', 'Mojeek', 'Mojolicious \(Perl\)', - 'Monit\/', + 'Mollie', 'monitis', 'Monitority\/', + 'Monit\/', 'montastic', 'MonTools', 'Moreover', @@ -670,6 +785,7 @@ class Crawlers extends AbstractProvider 'MovableType', 'mowser', 'Mrcgiguy', + 'Mr\.4x3 Powered', 'MS Web Services Client Protocol', 'MSFrontPage', 'mShots', @@ -677,10 +793,13 @@ class Crawlers extends AbstractProvider 'muhstik-scan', 'MVAClient', 'MxToolbox\/', + 'myseosnapshot', 'nagios', 'Najdi\.si', 'Name Intelligence', + 'NameFo\.com', 'Nameprotect', + 'nationalarchives', 'Navroad', 'NearSite', 'Needle', @@ -695,6 +814,8 @@ class Crawlers extends AbstractProvider 'netresearch', 'NetShelter ContentScan', 'Netsparker', + 'NetSystemsResearch', + 'nettle', 'NetTrack', 'Netvibes', 'NetZIP', @@ -707,22 +828,26 @@ class Crawlers extends AbstractProvider 'newspaper\/', 'Nexgate Ruby Client', 'NG-Search', + 'nghttp2', 'Nibbler', 'NICErsPRO', + 'NihilScio', 'Nikto', 'nineconnections', 'NLNZ_IAHarvester', 'Nmap Scripting Engine', + 'node-fetch', 'node-superagent', 'node-urllib', - 'node\.io', 'Nodemeter', 'NodePing', + 'node\.io', 'nominet\.org\.uk', 'nominet\.uk', 'Norton-Safeweb', 'Notifixious', 'notifyninja', + 'NotionEmbedder', 'nuhk', 'nutch', 'Nuzzel', @@ -730,39 +855,45 @@ class Crawlers extends AbstractProvider 'nyawc\/', 'Nymesis', 'NYU', + 'Observatory\/', 'Ocelli\/', 'Octopus', 'oegp', 'Offline Explorer', 'Offline Navigator', - 'og-scraper', + 'OgScrper', 'okhttp', 'omgili', 'OMSC', 'Online Domain Tools', + 'Open Source RSS', 'OpenCalaisSemanticProxy', 'Openfind', 'OpenLinkProfiler', 'Openstat\/', 'OpenVAS', + 'OPPO A33', 'Optimizer', 'Orbiter', 'OrgProbe\/', 'orion-semantics', 'Outlook-Express', 'Outlook-iOS', - 'ow\.ly', 'Owler', + 'Owlin', 'ownCloud News', + 'ow\.ly', 'OxfordCloudService', - 'Page Valet', - 'page_verifier', 'page scorer', + 'Page Valet', 'page2rss', + 'PageFreezer', 'PageGrabber', 'PagePeeker', 'PageScorer', 'Pagespeed\/', + 'PageThing', + 'page_verifier', 'Panopta', 'panscient', 'Papa Foto', @@ -771,6 +902,7 @@ class Crawlers extends AbstractProvider 'PayPal IPN', 'pcBrowser', 'Pcore-HTTP', + 'PDF24 URL To PDF', 'Pearltrees', 'PECL::HTTP', 'peerindex', @@ -780,44 +912,52 @@ class Crawlers extends AbstractProvider 'PhantomJS Screenshoter', 'PhantomJS\/', 'Photon\/', + 'php-requests', 'phpservermon', 'Pi-Monster', 'Picscout', 'Picsearch', 'PictureFinder', 'Pimonster', - 'ping\.blo\.gs', 'Pingability', 'PingAdmin\.Ru', 'Pingdom', 'Pingoscope', 'PingSpot', + 'ping\.blo\.gs', 'pinterest\.com', 'Pixray', 'Pizilla', 'Plagger\/', + 'Pleroma ', 'Ploetz \+ Zeller', 'Plukkie', 'plumanalytics', 'PocketImageCache', 'PocketParser', 'Pockey', + 'PodcastAddict\/', 'POE-Component-Client-HTTP', 'Polymail\/', 'Pompos', 'Porkbun', 'Port Monitor', 'postano', + 'postfix-mta-sts-resolver', 'PostmanRuntime', + 'postplanner\.com', 'PostPost', 'postrank', 'PowerPoint\/', + 'Prebid', + 'Prerender', 'Priceonomics Analysis Engine', 'PrintFriendly', 'PritTorrent', 'Prlog', 'probethenet', - 'Project 25499', + 'Project ?25499', + 'Project-Resonance', 'prospectb2b', 'Protopage', 'ProWebWalker', @@ -826,9 +966,9 @@ class Crawlers extends AbstractProvider 'pshtt, https scanning', 'PTST ', 'PTST\/[0-9]+', - 'Pulsepoint XT3 web scraper', 'Pump', 'Python-httplib2', + 'python-httpx', 'python-requests', 'Python-urllib', 'Qirina Hurdler', @@ -838,12 +978,17 @@ class Crawlers extends AbstractProvider 'Qualidator', 'QueryN Metasearch', 'queuedriver', + 'quic-go-HTTP\/', + 'QuiteRSS', 'Quora Link Preview', 'Qwantify', 'Radian6', + 'RadioPublicImageResizer', + 'Railgun\/', 'RankActive', 'RankFlex', 'RankSonicSiteAuditor', + 'RapidLoad\/', 'Re-re Studio', 'ReactorNetty', 'Readability', @@ -854,6 +999,7 @@ class Crawlers extends AbstractProvider 'RecurPost\/', 'redback\/', 'ReederForMac', + 'Reeder\/', 'ReGet', 'RepoMonkey', 'request\.js', @@ -866,38 +1012,44 @@ class Crawlers extends AbstractProvider 'Robozilla', 'ROI Hunter', 'RPT-HTTPClient', + 'RSSMix\/', 'RSSOwl', + 'RyowlEngine', 'safe-agent-scanner', 'SalesIntelligent', 'Saleslift', - 'Sendsay\.Ru', + 'SAP NetWeaver Application Server', 'SauceNAO', 'SBIder', + 'sc-downloader', 'scalaj-http', - 'scan\.lol', + 'Scamadviser-Frontend', 'ScanAlert', + 'scan\.lol', 'Scoop', 'scooter', + 'ScopeContentAG-HTTP-Client', 'ScoutJet', 'ScoutURLMonitor', 'ScrapeBox Page Scanner', - 'SimpleScraper', 'Scrapy', 'Screaming', 'ScreenShotService', 'Scrubby', 'Scrutiny\/', - 'search\.thunderstone', 'Search37', 'searchenginepromotionhelp', 'Searchestate', 'SearchExpress', 'SearchSight', + 'SearchWP', + 'search\.thunderstone', 'Seeker', 'semanticdiscovery', 'semanticjuice', 'Semiocast HTTP client', 'Semrush', + 'Sendsay\.Ru', 'sentry\/', 'SEO Browser', 'Seo Servis', @@ -906,11 +1058,13 @@ class Crawlers extends AbstractProvider 'Seobility', 'SEOCentro', 'SeoCheck', + 'seocompany', 'SEOkicks', + 'SEOlizer', 'Seomoz', 'SEOprofiler', - 'SEOsearch', 'seoscanners', + 'SEOsearch', 'seositecheckup', 'SEOstats', 'servernfo', @@ -921,14 +1075,16 @@ class Crawlers extends AbstractProvider 'Shoppimon', 'ShopWiki', 'ShortLinkTranslate', + 'shortURL lengthener', 'shrinktheweb', 'Sideqik', + 'Siege', 'SimplePie', 'SimplyFast', 'Siphon', 'SISTRIX', - 'Site-Shot\/', 'Site Sucker', + 'Site-Shot\/', 'Site24x7', 'SiteBar', 'Sitebeam', @@ -949,6 +1105,7 @@ class Crawlers extends AbstractProvider 'sitexy\.com', 'SkypeUriPreview', 'Slack\/', + 'sli-systems\.com', 'slider\.com', 'slurp', 'SlySearch', @@ -971,9 +1128,11 @@ class Crawlers extends AbstractProvider 'SpamExperts', 'Spammen', 'Spanner', + 'Spawning-AI', 'spaziodati', 'SPDYCheck', 'Specificfeeds', + 'SpeedKit', 'speedy', 'SPEng', 'Spinn3r', @@ -987,9 +1146,11 @@ class Crawlers extends AbstractProvider 'ssl-tools', 'StackRambler', 'Statastico\/', + 'Statically-', 'StatusCake', 'Steeler', 'Stratagems Kumo', + 'Stripe\/', 'Stroke\.cz', 'StudioFACA', 'StumbleUpon', @@ -999,9 +1160,11 @@ class Crawlers extends AbstractProvider 'SuperHTTP', 'Surphace Scout', 'Suzuran', - 'SwiteScraper', + 'swcd ', 'Symfony BrowserKit', 'Symfony2 BrowserKit', + 'Synapse\/', + 'Syndirella\/', 'SynHttpClient-Built', 'Sysomos', 'sysscan', @@ -1011,6 +1174,8 @@ class Crawlers extends AbstractProvider 'Tarantula\/', 'Taringa UGC', 'TarmotGezgin', + 'tchelebi\.io', + 'techiaith\.cymru', 'Teleport', 'Telesoft', 'Telesphoreo', @@ -1021,13 +1186,15 @@ class Crawlers extends AbstractProvider 'Test Certificate Info', 'testuri', 'Tetrahedron', + 'TextRazor Downloader', 'The Drop Reaper', 'The Expert HTML Source Viewer', - 'The Knowledge AI', 'The Intraformant', + 'The Knowledge AI', 'theinternetrules', 'TheNomad', 'Thinklab', + 'Thumbor', 'Thumbshots', 'ThumbSniper', 'timewe\.net', @@ -1061,9 +1228,11 @@ class Crawlers extends AbstractProvider 'ubermetrics-technologies', 'uclassify', 'UdmSearch', + 'ultimate_sitemap_parser', 'unchaos', 'unirest-java', 'UniversalFeedParser', + 'unshortenit', 'Unshorten\.It', 'Untiny', 'UnwindFetchor', @@ -1071,8 +1240,8 @@ class Crawlers extends AbstractProvider 'updown\.io daemon', 'Upflow', 'Uptimia', - 'Urlcheckr', 'URL Verifier', + 'Urlcheckr', 'URLitor', 'urlresolver', 'Urlstat', @@ -1080,15 +1249,16 @@ class Crawlers extends AbstractProvider 'UrlTrends Ranking Updater', 'URLy Warning', 'URLy\.Warning', + 'URL\/Emacs', 'Vacuum', 'Vagabondo', 'VB Project', 'vBSEO', 'VCI', 'via ggpht\.com GoogleImageProxy', - 'VidibleScraper', 'Virusdie', 'visionutils', + 'Visual Rights Group', 'vkShare', 'VoidEYE', 'Voil', @@ -1099,19 +1269,18 @@ class Crawlers extends AbstractProvider 'Vulnbusters Meter', 'VYU2', 'w3af\.org', - 'W3C_Unicorn', 'W3C-checklink', 'W3C-mobileOK', + 'W3C_Unicorn', 'WAC-OFU', - 'Wallpapers\/[0-9]+', + 'WakeletLinkExpander', 'WallpapersHD', + 'Wallpapers\/[0-9]+', 'wangling', 'Wappalyzer', 'WatchMouse', 'WbSrch\/', 'WDT\.io', - 'web-capture\.net', - 'Web-sniffer', 'Web Auto', 'Web Collage', 'Web Enhancer', @@ -1119,7 +1288,10 @@ class Crawlers extends AbstractProvider 'Web Fuck', 'Web Pix', 'Web Sauger', + 'Web spyder', 'Web Sucker', + 'web-capture\.net', + 'Web-sniffer', 'Webalta', 'Webauskunft', 'WebAuto', @@ -1157,8 +1329,9 @@ class Crawlers extends AbstractProvider 'Webster', 'WebStripper', 'WebSucker', - 'Webthumb\/', + 'webtech\/', 'WebThumbnail', + 'Webthumb\/', 'WebWhacker', 'WebZIP', 'WeLikeLinks', @@ -1167,24 +1340,31 @@ class Crawlers extends AbstractProvider 'wf84', 'Wfuzz\/', 'wget', + 'WhatCMS', 'WhatsApp', 'WhatsMyIP', 'WhatWeb', 'WhereGoes\?', 'Whibse', + 'WhoAPI\/', 'WhoRunsCoinHive', 'Whynder Magnet', 'Windows-RSS-Platform', + 'WinHttp-Autoproxy-Service', + 'WinHTTP\/', 'WinPodder', 'wkhtmlto', 'wmtips', 'Woko', + 'Wolfram HTTPClient', 'woorankreview', - 'Word\/', 'WordPress\/', 'WordupinfoSearch', + 'Word\/', + 'worldping-api', 'wotbox', 'WP Engine Install Performance API', + 'WP Rocket', 'wpif', 'wprecon\.com survey', 'WPScan', @@ -1194,20 +1374,21 @@ class Crawlers extends AbstractProvider 'WWW-Mechanize', 'WWW::Document', 'WWW::Mechanize', - 'www\.monitor\.us', 'WWWOFFLE', + 'www\.monitor\.us', 'x09Mozilla', 'x22Mozilla', 'XaxisSemanticsClassifier', + 'XenForo\/', 'Xenu Link Sleuth', 'XING-contenttabreceiver', 'xpymep([0-9]?)\.exe', - 'Y!J-(ASR|BSC)', - 'Y\!J-BRW', + 'Y!J-[A-Z][A-Z][A-Z]', 'Yaanb', 'yacy', 'Yahoo Link Preview', 'YahooCacheSystem', + 'YahooMailProxy', 'YahooYSMcm', 'YandeG', 'Yandex(?!Search)', @@ -1215,6 +1396,7 @@ class Crawlers extends AbstractProvider 'yeti', 'Yo-yo', 'Yoleo Consumer', + 'yomins\.com', 'yoogliFetchAgent', 'YottaaMonitor', 'Your-Website-Sucks', @@ -1226,15 +1408,17 @@ class Crawlers extends AbstractProvider 'Zao', 'Zauba', 'Zemanta Aggregator', - 'Zend_Http_Client', 'Zend\\\\Http\\\\Client', + 'Zend_Http_Client', 'Zermelo', 'Zeus ', 'zgrab', 'ZnajdzFoto', + 'ZnHTTP', 'Zombie\.js', 'Zoom\.Mac', + 'ZoteroTranslationServer', 'ZyBorg', - '[a-z0-9\-_]*(bot|crawl|archiver|transcoder|spider|uptime|validator|fetcher|cron|checker|reader|extractor|monitoring|analyzer)', + '[a-z0-9\-_]*(bot|crawl|archiver|transcoder|spider|uptime|validator|fetcher|cron|checker|reader|extractor|monitoring|analyzer|scraper)', ); } diff --git a/blockbot/vendor/jaybizzle/crawler-detect/src/Fixtures/Exclusions.php b/blockbot/vendor/jaybizzle/crawler-detect/src/Fixtures/Exclusions.php index e6b3ca89..62745572 100644 --- a/blockbot/vendor/jaybizzle/crawler-detect/src/Fixtures/Exclusions.php +++ b/blockbot/vendor/jaybizzle/crawler-detect/src/Fixtures/Exclusions.php @@ -67,6 +67,8 @@ class Exclusions extends AbstractProvider '; IDbot', '; ID bot', '; POWER BOT', - ';', // Remove the following characters ; + 'OCTOPUS-CORE', + 'htc_botdugls', + 'super\/\d+\/Android\/\d+', ); } diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index fe66d9a4..aef7156c 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -1,7 +1,7 @@ * @@ -10,6 +10,8 @@ * - Outgoing mentions * * At some point in time: + * - post videos + * - direct messages * - Sending Quote shares https://atproto.com/lexicons/app-bsky-embed#appbskyembedrecord and https://atproto.com/lexicons/app-bsky-embed#appbskyembedrecordwithmedia * * Possibly not possible: @@ -24,29 +26,24 @@ */ use Friendica\Content\Text\BBCode; -use Friendica\Content\Text\HTML; use Friendica\Content\Text\Plaintext; use Friendica\Core\Cache\Enum\Duration; use Friendica\Core\Config\Util\ConfigFileManager; use Friendica\Core\Hook; -use Friendica\Core\Logger; use Friendica\Core\Protocol; use Friendica\Core\Renderer; use Friendica\Core\Worker; use Friendica\Database\DBA; use Friendica\DI; use Friendica\Model\Contact; -use Friendica\Model\GServer; +use Friendica\Model\Conversation; use Friendica\Model\Item; -use Friendica\Model\ItemURI; use Friendica\Model\Photo; use Friendica\Model\Post; -use Friendica\Model\Tag; use Friendica\Model\User; -use Friendica\Network\HTTPClient\Client\HttpClientAccept; -use Friendica\Network\HTTPClient\Client\HttpClientOptions; use Friendica\Object\Image; use Friendica\Protocol\Activity; +use Friendica\Protocol\ATProtocol; use Friendica\Protocol\Relay; use Friendica\Util\DateTimeFormat; use Friendica\Util\Strings; @@ -54,21 +51,6 @@ use Friendica\Util\Strings; const BLUESKY_DEFAULT_POLL_INTERVAL = 10; // given in minutes const BLUESKY_IMAGE_SIZE = [1000000, 500000, 100000, 50000]; -const BLUEKSY_STATUS_UNKNOWN = 0; -const BLUEKSY_STATUS_TOKEN_OK = 1; -const BLUEKSY_STATUS_SUCCESS = 2; -const BLUEKSY_STATUS_API_FAIL = 10; -const BLUEKSY_STATUS_DID_FAIL = 11; -const BLUEKSY_STATUS_PDS_FAIL = 12; -const BLUEKSY_STATUS_TOKEN_FAIL = 13; - -/* - * (Currently) hard wired paths for Bluesky services - */ -const BLUESKY_DIRECTORY = 'https://plc.directory'; // Path to the directory server service to fetch the PDS of a given DID -const BLUESKY_PDS = 'https://bsky.social'; // Path to the personal data server service (PDS) to fetch the DID for a given handle -const BLUESKY_WEB = 'https://bsky.app'; // Path to the web interface with the user profile and posts - function bluesky_install() { Hook::register('load_config', __FILE__, 'bluesky_load_config'); @@ -80,83 +62,31 @@ function bluesky_install() Hook::register('connector_settings_post', __FILE__, 'bluesky_settings_post'); Hook::register('cron', __FILE__, 'bluesky_cron'); Hook::register('support_follow', __FILE__, 'bluesky_support_follow'); - Hook::register('support_probe', __FILE__, 'bluesky_support_probe'); Hook::register('follow', __FILE__, 'bluesky_follow'); Hook::register('unfollow', __FILE__, 'bluesky_unfollow'); Hook::register('block', __FILE__, 'bluesky_block'); Hook::register('unblock', __FILE__, 'bluesky_unblock'); Hook::register('check_item_notification', __FILE__, 'bluesky_check_item_notification'); - Hook::register('probe_detect', __FILE__, 'bluesky_probe_detect'); Hook::register('item_by_link', __FILE__, 'bluesky_item_by_link'); } function bluesky_load_config(ConfigFileManager $loader) { - DI::app()->getConfigCache()->load($loader->loadAddonConfig('bluesky'), \Friendica\Core\Config\ValueObject\Cache::SOURCE_STATIC); + DI::appHelper()->getConfigCache()->load($loader->loadAddonConfig('bluesky'), \Friendica\Core\Config\ValueObject\Cache::SOURCE_STATIC); } function bluesky_check_item_notification(array &$notification_data) { - $did = DI::pConfig()->get($notification_data['uid'], 'bluesky', 'did'); - - if (!empty($did)) { - $notification_data['profiles'][] = $did; - } -} - -function bluesky_probe_detect(array &$hookData) -{ - // Don't overwrite an existing result - if (isset($hookData['result'])) { + if (empty($notification_data['uid'])) { return; } - // Avoid a lookup for the wrong network - if (!in_array($hookData['network'], ['', Protocol::BLUESKY])) { + $did = DI::atProtocol()->getUserDid($notification_data['uid']); + if (empty($did)) { return; } - $pconfig = DBA::selectFirst('pconfig', ['uid'], ["`cat` = ? AND `k` = ? AND `v` != ?", 'bluesky', 'access_token', '']); - if (empty($pconfig['uid'])) { - return; - } - - if (parse_url($hookData['uri'], PHP_URL_SCHEME) == 'did') { - $did = $hookData['uri']; - } elseif (preg_match('#^' . BLUESKY_WEB . '/profile/(.+)#', $hookData['uri'], $matches)) { - $did = bluesky_get_did($matches[1]); - if (empty($did)) { - return; - } - } else { - return; - } - - $token = bluesky_get_token($pconfig['uid']); - if (empty($token)) { - return; - } - - $data = bluesky_xrpc_get($pconfig['uid'], 'app.bsky.actor.getProfile', ['actor' => $did]); - if (empty($data)) { - return; - } - - $hookData['result'] = bluesky_get_contact_fields($data, 0, $pconfig['uid'], false); - - $hookData['result']['baseurl'] = bluesky_get_pds($did); - - // Preparing probe data. This differs slightly from the contact array - $hookData['result']['about'] = HTML::toBBCode($data->description ?? ''); - $hookData['result']['photo'] = $data->avatar ?? ''; - $hookData['result']['header'] = $data->banner ?? ''; - $hookData['result']['batch'] = ''; - $hookData['result']['notify'] = ''; - $hookData['result']['poll'] = ''; - $hookData['result']['poco'] = ''; - $hookData['result']['pubkey'] = ''; - $hookData['result']['priority'] = 0; - $hookData['result']['guid'] = ''; + $notification_data['profiles'][] = $did; } function bluesky_item_by_link(array &$hookData) @@ -166,26 +96,25 @@ function bluesky_item_by_link(array &$hookData) return; } - $token = bluesky_get_token($hookData['uid']); - if (empty($token)) { - return; + if (substr($hookData['uri'], 0, 5) != 'at://') { + if (!preg_match('#^' . ATProtocol::WEB . '/profile/(.+)/post/(.+)#', $hookData['uri'], $matches)) { + return; + } + + $did = DI::atProtocol()->getDid($matches[1]); + if (empty($did)) { + return; + } + + DI::logger()->debug('Found bluesky post', ['uri' => $hookData['uri'], 'did' => $did, 'cid' => $matches[2]]); + + $uri = 'at://' . $did . '/app.bsky.feed.post/' . $matches[2]; + } else { + $uri = $hookData['uri']; } - if (!preg_match('#^' . BLUESKY_WEB . '/profile/(.+)/post/(.+)#', $hookData['uri'], $matches)) { - return; - } - - $did = bluesky_get_did($matches[1]); - if (empty($did)) { - return; - } - - Logger::debug('Found bluesky post', ['url' => $hookData['uri'], 'handle' => $matches[1], 'did' => $did, 'cid' => $matches[2]]); - - $uri = 'at://' . $did . '/app.bsky.feed.post/' . $matches[2]; - - $uri = bluesky_fetch_missing_post($uri, $hookData['uid'], $hookData['uid'], Item::PR_FETCHED, 0, 0, 0); - Logger::debug('Got post', ['profile' => $matches[1], 'cid' => $matches[2], 'result' => $uri]); + $uri = DI::atpProcessor()->fetchMissingPost($uri, $hookData['uid'], Item::PR_FETCHED, 0, 0); + DI::logger()->debug('Got post', ['uri' => $uri]); if (!empty($uri)) { $item = Post::selectFirst(['id'], ['uri' => $uri, 'uid' => $hookData['uid']]); if (!empty($item['id'])) { @@ -201,21 +130,14 @@ function bluesky_support_follow(array &$data) } } -function bluesky_support_probe(array &$data) -{ - if ($data['protocol'] == Protocol::BLUESKY) { - $data['result'] = true; - } -} - function bluesky_follow(array &$hook_data) { - $token = bluesky_get_token($hook_data['uid']); + $token = DI::atProtocol()->getUserToken($hook_data['uid']); if (empty($token)) { return; } - Logger::debug('Check if contact is bluesky', ['data' => $hook_data]); + DI::logger()->debug('Check if contact is bluesky', ['data' => $hook_data]); $contact = DBA::selectFirst('contact', [], ['network' => Protocol::BLUESKY, 'url' => $hook_data['url'], 'uid' => [0, $hook_data['uid']]]); if (empty($contact)) { return; @@ -229,20 +151,20 @@ function bluesky_follow(array &$hook_data) $post = [ 'collection' => 'app.bsky.graph.follow', - 'repo' => DI::pConfig()->get($hook_data['uid'], 'bluesky', 'did'), + 'repo' => DI::atProtocol()->getUserDid($hook_data['uid']), 'record' => $record ]; - $activity = bluesky_xrpc_post($hook_data['uid'], 'com.atproto.repo.createRecord', $post); + $activity = DI::atProtocol()->XRPCPost($hook_data['uid'], 'com.atproto.repo.createRecord', $post); if (!empty($activity->uri)) { $hook_data['contact'] = $contact; - Logger::debug('Successfully start following', ['url' => $contact['url'], 'uri' => $activity->uri]); + DI::logger()->debug('Successfully start following', ['url' => $contact['url'], 'uri' => $activity->uri]); } } function bluesky_unfollow(array &$hook_data) { - $token = bluesky_get_token($hook_data['uid']); + $token = DI::atProtocol()->getUserToken($hook_data['uid']); if (empty($token)) { return; } @@ -251,7 +173,7 @@ function bluesky_unfollow(array &$hook_data) return; } - $data = bluesky_xrpc_get($hook_data['uid'], 'app.bsky.actor.getProfile', ['actor' => $hook_data['contact']['url']]); + $data = DI::atProtocol()->XRPCGet('app.bsky.actor.getProfile', ['actor' => $hook_data['contact']['url']], $hook_data['uid']); if (empty($data->viewer) || empty($data->viewer->following)) { return; } @@ -263,42 +185,7 @@ function bluesky_unfollow(array &$hook_data) function bluesky_block(array &$hook_data) { - $token = bluesky_get_token($hook_data['uid']); - if (empty($token)) { - return; - } - - Logger::debug('Check if contact is bluesky', ['data' => $hook_data]); - $contact = DBA::selectFirst('contact', [], ['network' => Protocol::BLUESKY, 'url' => $hook_data['url'], 'uid' => [0, $hook_data['uid']]]); - if (empty($contact)) { - return; - } - - $record = [ - 'subject' => $contact['url'], - 'createdAt' => DateTimeFormat::utcNow(DateTimeFormat::ATOM), - '$type' => 'app.bsky.graph.block' - ]; - - $post = [ - 'collection' => 'app.bsky.graph.block', - 'repo' => DI::pConfig()->get($hook_data['uid'], 'bluesky', 'did'), - 'record' => $record - ]; - - $activity = bluesky_xrpc_post($hook_data['uid'], 'com.atproto.repo.createRecord', $post); - if (!empty($activity->uri)) { - $cdata = Contact::getPublicAndUserContactID($hook_data['contact']['id'], $hook_data['uid']); - if (!empty($cdata['user'])) { - Contact::remove($cdata['user']); - } - Logger::debug('Successfully blocked contact', ['url' => $hook_data['contact']['url'], 'uri' => $activity->uri]); - } -} - -function bluesky_unblock(array &$hook_data) -{ - $token = bluesky_get_token($hook_data['uid']); + $token = DI::atProtocol()->getUserToken($hook_data['uid']); if (empty($token)) { return; } @@ -307,7 +194,40 @@ function bluesky_unblock(array &$hook_data) return; } - $data = bluesky_xrpc_get($hook_data['uid'], 'app.bsky.actor.getProfile', ['actor' => $hook_data['contact']['url']]); + $record = [ + 'subject' => $hook_data['contact']['url'], + 'createdAt' => DateTimeFormat::utcNow(DateTimeFormat::ATOM), + '$type' => 'app.bsky.graph.block' + ]; + + $post = [ + 'collection' => 'app.bsky.graph.block', + 'repo' => DI::atProtocol()->getUserDid($hook_data['uid']), + 'record' => $record + ]; + + $activity = DI::atProtocol()->XRPCPost($hook_data['uid'], 'com.atproto.repo.createRecord', $post); + if (!empty($activity->uri)) { + $ucid = Contact::getUserContactId($hook_data['contact']['id'], $hook_data['uid']); + if ($ucid) { + Contact::remove($ucid); + } + DI::logger()->debug('Successfully blocked contact', ['url' => $hook_data['contact']['url'], 'uri' => $activity->uri]); + } +} + +function bluesky_unblock(array &$hook_data) +{ + $token = DI::atProtocol()->getUserToken($hook_data['uid']); + if (empty($token)) { + return; + } + + if ($hook_data['contact']['network'] != Protocol::BLUESKY) { + return; + } + + $data = DI::atProtocol()->XRPCGet('app.bsky.actor.getProfile', ['actor' => $hook_data['contact']['url']], $hook_data['uid']); if (empty($data->viewer) || empty($data->viewer->blocking)) { return; } @@ -323,7 +243,7 @@ function bluesky_addon_admin(string &$o) $o = Renderer::replaceMacros($t, [ '$submit' => DI::l10n()->t('Save Settings'), - '$friendica_handles' => ['friendica_handles', DI::l10n()->t('Allow your users to use your hostname for their Bluesky handles'), DI::config()->get('bluesky', 'friendica_handles'), DI::l10n()->t('Before enabling this option, you have to download and configure the bluesky-handles repository on your system. See https://git.friendi.ca/heluecht/bluesky-handles')], + '$friendica_handles' => ['friendica_handles', DI::l10n()->t('Allow your users to use your hostname for their Bluesky handles'), DI::config()->get('bluesky', 'friendica_handles'), DI::l10n()->t('Before enabling this option, you have to setup a wildcard domain configuration and you have to enable wildcard requests in your webserver configuration. On Apache this is done by adding "ServerAlias *.%s" to your HTTP configuration. You don\'t need to change the HTTPS configuration.', DI::baseUrl()->getHost())], ]); } @@ -338,36 +258,41 @@ function bluesky_settings(array &$data) return; } - $enabled = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'post') ?? false; - $def_enabled = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'post_by_default') ?? false; - $pds = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'pds'); - $handle = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'handle'); - $did = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'did'); - $token = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'access_token'); - $import = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'import') ?? false; - $import_feeds = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'import_feeds') ?? false; - $custom_handle = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'friendica_handle') ?? false; + $enabled = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'post') ?? false; + $def_enabled = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'post_by_default') ?? false; + $pds = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'pds'); + $handle = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'handle'); + $did = DI::atProtocol()->getUserDid(DI::userSession()->getLocalUserId()); + $token = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'access_token'); + $import = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'import') ?? false; + $import_feeds = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'import_feeds') ?? false; + $complete_threads = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'complete_threads') ?? false; + $custom_handle = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'friendica_handle') ?? false; if (DI::config()->get('bluesky', 'friendica_handles')) { $self = User::getById(DI::userSession()->getLocalUserId(), ['nickname']); - $handle = $self['nickname'] . '.' . DI::baseUrl()->getHost(); - $friendica_handle = ['bluesky_friendica_handle', DI::l10n()->t('Allow to use %s as your Bluesky handle.', $handle), $custom_handle, DI::l10n()->t('When enabled, you can use %s as your Bluesky handle. After you enabled this option, please go to https://bsky.app/settings and select to change your handle. Select that you have got your own domain. Then enter %s and select "No DNS Panel". Then select "Verify Text File".', $handle, $handle)]; + $host_handle = $self['nickname'] . '.' . DI::baseUrl()->getHost(); + $friendica_handle = ['bluesky_friendica_handle', DI::l10n()->t('Allow to use %s as your Bluesky handle.', $host_handle), $custom_handle, DI::l10n()->t('When enabled, you can use %s as your Bluesky handle. After you enabled this option, please go to https://bsky.app/settings and select to change your handle. Select that you have got your own domain. Then enter %s and select "No DNS Panel". Then select "Verify Text File".', $host_handle, $host_handle)]; + if ($custom_handle) { + $handle = $host_handle; + } } else { $friendica_handle = []; } $t = Renderer::getMarkupTemplate('connector_settings.tpl', 'addon/bluesky/'); $html = Renderer::replaceMacros($t, [ - '$enable' => ['bluesky', DI::l10n()->t('Enable Bluesky Post Addon'), $enabled], - '$bydefault' => ['bluesky_bydefault', DI::l10n()->t('Post to Bluesky by default'), $def_enabled], - '$import' => ['bluesky_import', DI::l10n()->t('Import the remote timeline'), $import], - '$import_feeds' => ['bluesky_import_feeds', DI::l10n()->t('Import the pinned feeds'), $import_feeds, DI::l10n()->t('When activated, Posts will be imported from all the feeds that you pinned in Bluesky.')], - '$custom_handle' => $friendica_handle, - '$pds' => ['bluesky_pds', DI::l10n()->t('Personal Data Server'), $pds, DI::l10n()->t('The personal data server (PDS) is the system that hosts your profile.'), '', 'readonly'], - '$handle' => ['bluesky_handle', DI::l10n()->t('Bluesky handle'), $handle], - '$did' => ['bluesky_did', DI::l10n()->t('Bluesky DID'), $did, DI::l10n()->t('This is the unique identifier. It will be fetched automatically, when the handle is entered.'), '', 'readonly'], - '$password' => ['bluesky_password', DI::l10n()->t('Bluesky app password'), '', DI::l10n()->t("Please don't add your real password here, but instead create a specific app password in the Bluesky settings.")], - '$status' => bluesky_get_status($handle, $did, $pds, $token), + '$enable' => ['bluesky', DI::l10n()->t('Enable Bluesky Post Addon'), $enabled], + '$bydefault' => ['bluesky_bydefault', DI::l10n()->t('Post to Bluesky by default'), $def_enabled], + '$import' => ['bluesky_import', DI::l10n()->t('Import the remote timeline'), $import], + '$import_feeds' => ['bluesky_import_feeds', DI::l10n()->t('Import the pinned feeds'), $import_feeds, DI::l10n()->t('When activated, Posts will be imported from all the feeds that you pinned in Bluesky.')], + '$complete_threads' => ['bluesky_complete_threads', DI::l10n()->t('Complete the threads'), $complete_threads, DI::l10n()->t('When activated, the system fetches additional replies for the posts in the timeline. This leads to more complete threads.')], + '$custom_handle' => $friendica_handle, + '$pds' => ['bluesky_pds', DI::l10n()->t('Personal Data Server'), $pds, DI::l10n()->t('The personal data server (PDS) is the system that hosts your profile.'), '', 'readonly'], + '$handle' => ['bluesky_handle', DI::l10n()->t('Bluesky handle'), $handle, '', '', $custom_handle ? 'readonly' : ''], + '$did' => ['bluesky_did', DI::l10n()->t('Bluesky DID'), $did, DI::l10n()->t('This is the unique identifier. It will be fetched automatically, when the handle is entered.'), '', 'readonly'], + '$password' => ['bluesky_password', DI::l10n()->t('Bluesky app password'), '', DI::l10n()->t("Please don't add your real password here, but instead create a specific app password in the Bluesky settings.")], + '$status' => bluesky_get_status($handle, $did, $pds, $token), ]); $data = [ @@ -385,33 +310,34 @@ function bluesky_get_status(string $handle = null, string $did = null, string $p return DI::l10n()->t('You are not authenticated. Please enter your handle and the app password.'); } - $status = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'status') ?? BLUEKSY_STATUS_UNKNOWN; + $status = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'status') ?? ATProtocol::STATUS_UNKNOWN; + $message = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'status-message') ?? ''; // Fallback mechanism for connection that had been established before the introduction of the status - if ($status == BLUEKSY_STATUS_UNKNOWN) { + if ($status == ATProtocol::STATUS_UNKNOWN) { if (empty($did)) { - $status = BLUEKSY_STATUS_DID_FAIL; + $status = ATProtocol::STATUS_DID_FAIL; } elseif (empty($pds)) { - $status = BLUEKSY_STATUS_PDS_FAIL; + $status = ATProtocol::STATUS_PDS_FAIL; } elseif (!empty($token)) { - $status = BLUEKSY_STATUS_TOKEN_OK; + $status = ATProtocol::STATUS_TOKEN_OK; } else { - $status = BLUEKSY_STATUS_TOKEN_FAIL; + $status = ATProtocol::STATUS_TOKEN_FAIL; } } switch ($status) { - case BLUEKSY_STATUS_TOKEN_OK: + case ATProtocol::STATUS_TOKEN_OK: return DI::l10n()->t("You are authenticated to Bluesky. For security reasons the password isn't stored."); - case BLUEKSY_STATUS_SUCCESS: + case ATProtocol::STATUS_SUCCESS: return DI::l10n()->t('The communication with the personal data server service (PDS) is established.'); - case BLUEKSY_STATUS_API_FAIL; - return DI::l10n()->t('Communication issues with the personal data server service (PDS).'); - case BLUEKSY_STATUS_DID_FAIL: + case ATProtocol::STATUS_API_FAIL; + return DI::l10n()->t('Communication issues with the personal data server service (PDS): %s', $message); + case ATProtocol::STATUS_DID_FAIL: return DI::l10n()->t('The DID for the provided handle could not be detected. Please check if you entered the correct handle.'); - case BLUEKSY_STATUS_PDS_FAIL: + case ATProtocol::STATUS_PDS_FAIL: return DI::l10n()->t('The personal data server service (PDS) could not be detected.'); - case BLUEKSY_STATUS_TOKEN_FAIL: + case ATProtocol::STATUS_TOKEN_FAIL: return DI::l10n()->t('The authentication with the provided handle and password failed. Please check if you entered the correct password.'); default: return ''; @@ -435,22 +361,15 @@ function bluesky_settings_post(array &$b) DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'handle', $handle); DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'import', intval($_POST['bluesky_import'])); DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'import_feeds', intval($_POST['bluesky_import_feeds'])); - DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'friendica_handle', intval($_POST['bluesky_friendica_handle'])); + DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'complete_threads', intval($_POST['bluesky_complete_threads'])); + DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'friendica_handle', intval($_POST['bluesky_friendica_handle'] ?? false)); if (!empty($handle)) { - if (empty($old_did) || $old_handle != $handle) { - $did = bluesky_get_did(DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'handle')); - if (empty($did)) { - DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'status', BLUEKSY_STATUS_DID_FAIL); - } - DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'did', $did); - } else { - $did = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'did'); - } + $did = DI::atProtocol()->getUserDid(DI::userSession()->getLocalUserId(), empty($old_did) || $old_handle != $handle); if (!empty($did) && (empty($old_pds) || $old_handle != $handle)) { - $pds = bluesky_get_pds($did); + $pds = DI::atProtocol()->getPdsOfDid($did); if (empty($pds)) { - DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'status', BLUEKSY_STATUS_PDS_FAIL); + DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'status', ATProtocol::STATUS_PDS_FAIL); } DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'pds', $pds); } else { @@ -459,6 +378,7 @@ function bluesky_settings_post(array &$b) } else { DI::pConfig()->delete(DI::userSession()->getLocalUserId(), 'bluesky', 'did'); DI::pConfig()->delete(DI::userSession()->getLocalUserId(), 'bluesky', 'pds'); + DI::pConfig()->delete(DI::userSession()->getLocalUserId(), 'bluesky', 'password'); DI::pConfig()->delete(DI::userSession()->getLocalUserId(), 'bluesky', 'access_token'); DI::pConfig()->delete(DI::userSession()->getLocalUserId(), 'bluesky', 'refresh_token'); DI::pConfig()->delete(DI::userSession()->getLocalUserId(), 'bluesky', 'token_created'); @@ -466,7 +386,7 @@ function bluesky_settings_post(array &$b) } if (!empty($did) && !empty($pds) && !empty($_POST['bluesky_password'])) { - bluesky_create_token(DI::userSession()->getLocalUserId(), $_POST['bluesky_password']); + DI::atProtocol()->createUserToken(DI::userSession()->getLocalUserId(), $_POST['bluesky_password']); } } @@ -500,11 +420,11 @@ function bluesky_cron() if ($last) { $next = $last + ($poll_interval * 60); if ($next > time()) { - Logger::notice('poll interval not reached'); + DI::logger()->notice('poll interval not reached'); return; } } - Logger::notice('cron_start'); + DI::logger()->notice('cron_start'); $abandon_days = intval(DI::config()->get('system', 'account_abandon_days')); if ($abandon_days < 1) { @@ -513,44 +433,61 @@ function bluesky_cron() $abandon_limit = date(DateTimeFormat::MYSQL, time() - $abandon_days * 86400); - $pconfigs = DBA::selectToArray('pconfig', [], ['cat' => 'bluesky', 'k' => 'import', 'v' => true]); + $pconfigs = DBA::selectToArray('pconfig', [], ["`cat` = ? AND `k` IN (?, ?) AND `v`", 'bluesky', 'import', 'import_feeds']); foreach ($pconfigs as $pconfig) { + if (empty(DI::atProtocol()->getUserDid($pconfig['uid']))) { + DI::logger()->debug('User has got no valid DID', ['uid' => $pconfig['uid']]); + continue; + } + if ($abandon_days != 0) { if (!DBA::exists('user', ["`uid` = ? AND `login_date` >= ?", $pconfig['uid'], $abandon_limit])) { - Logger::notice('abandoned account: timeline from user will not be imported', ['user' => $pconfig['uid']]); + DI::logger()->notice('abandoned account: timeline from user will not be imported', ['user' => $pconfig['uid']]); continue; } } // Refresh the token now, so that it doesn't need to be refreshed in parallel by the following workers - bluesky_get_token($pconfig['uid']); + DI::logger()->debug('Refresh the token', ['uid' => $pconfig['uid']]); + DI::atProtocol()->getUserToken($pconfig['uid']); - Worker::add(['priority' => Worker::PRIORITY_MEDIUM, 'force_priority' => true], 'addon/bluesky/bluesky_timeline.php', $pconfig['uid'], $last); - Worker::add(['priority' => Worker::PRIORITY_MEDIUM, 'force_priority' => true], 'addon/bluesky/bluesky_notifications.php', $pconfig['uid'], $last); + $last_sync = DI::pConfig()->get($pconfig['uid'], 'bluesky', 'last_contact_sync'); + if ($last_sync < (time() - 86400)) { + DI::atpActor()->syncContacts($pconfig['uid']); + DI::pConfig()->set($pconfig['uid'], 'bluesky', 'last_contact_sync', time()); + } + Worker::add(['priority' => Worker::PRIORITY_MEDIUM, 'force_priority' => true], 'addon/bluesky/bluesky_notifications.php', $pconfig['uid']); + if (DI::pConfig()->get($pconfig['uid'], 'bluesky', 'import')) { + Worker::add(['priority' => Worker::PRIORITY_MEDIUM, 'force_priority' => true], 'addon/bluesky/bluesky_timeline.php', $pconfig['uid']); + } if (DI::pConfig()->get($pconfig['uid'], 'bluesky', 'import_feeds')) { + DI::logger()->debug('Fetch feeds for user', ['uid' => $pconfig['uid']]); $feeds = bluesky_get_feeds($pconfig['uid']); foreach ($feeds as $feed) { - Worker::add(['priority' => Worker::PRIORITY_MEDIUM, 'force_priority' => true], 'addon/bluesky/bluesky_feed.php', $pconfig['uid'], $feed, $last); + Worker::add(['priority' => Worker::PRIORITY_MEDIUM, 'force_priority' => true], 'addon/bluesky/bluesky_feed.php', $pconfig['uid'], $feed); } } + DI::logger()->debug('Polling done for user', ['uid' => $pconfig['uid']]); } + DI::logger()->notice('Polling done for all users'); + + DI::keyValue()->set('bluesky_last_poll', time()); + $last_clean = DI::keyValue()->get('bluesky_last_clean'); if (empty($last_clean) || ($last_clean + 86400 < time())) { - Logger::notice('Start contact cleanup'); + DI::logger()->notice('Start contact cleanup'); $contacts = DBA::select('account-user-view', ['id', 'pid'], ["`network` = ? AND `uid` != ? AND `rel` = ?", Protocol::BLUESKY, 0, Contact::NOTHING]); while ($contact = DBA::fetch($contacts)) { Worker::add(Worker::PRIORITY_LOW, 'MergeContact', $contact['pid'], $contact['id'], 0); } DBA::close($contacts); DI::keyValue()->set('bluesky_last_clean', time()); - Logger::notice('Contact cleanup done'); + DI::logger()->notice('Contact cleanup done'); } - Logger::notice('cron_end'); - - DI::keyValue()->set('bluesky_last_poll', time()); + DI::logger()->notice('cron_end'); } function bluesky_hook_fork(array &$b) @@ -569,13 +506,13 @@ function bluesky_hook_fork(array &$b) if (DI::pConfig()->get($post['uid'], 'bluesky', 'import')) { // Don't post if it isn't a reply to a bluesky post - if (($post['parent'] != $post['id']) && !Post::exists(['id' => $post['parent'], 'network' => Protocol::BLUESKY])) { - Logger::notice('No bluesky parent found', ['item' => $post['id']]); + if (($post['gravity'] != Item::GRAVITY_PARENT) && !Post::exists(['id' => $post['parent'], 'network' => Protocol::BLUESKY])) { + DI::logger()->notice('No bluesky parent found', ['item' => $post['id']]); $b['execute'] = false; return; } - } elseif (!strstr($post['postopts'] ?? '', 'bluesky') || ($post['parent'] != $post['id']) || $post['private']) { - DI::logger()->info('Activities are never exported when we don\'t import the bluesky timeline', ['uid' => $post['uid']]); + } elseif (!strstr($post['postopts'] ?? '', 'bluesky') || ($post['gravity'] != Item::GRAVITY_PARENT) || ($post['private'] == Item::PRIVATE)) { + DI::logger()->info('Post will not be exported', ['uid' => $post['uid'], 'postopts' => $post['postopts'], 'gravity' => $post['gravity'], 'private' => $post['private']]); $b['execute'] = false; return; } @@ -583,15 +520,11 @@ function bluesky_hook_fork(array &$b) function bluesky_post_local(array &$b) { - if ($b['edit']) { - return; - } - if (!DI::userSession()->getLocalUserId() || (DI::userSession()->getLocalUserId() != $b['uid'])) { return; } - if ($b['private'] || $b['parent']) { + if ($b['edit'] || ($b['private'] == Item::PRIVATE) || ($b['gravity'] != Item::GRAVITY_PARENT)) { return; } @@ -621,35 +554,35 @@ function bluesky_send(array &$b) } if ($b['gravity'] != Item::GRAVITY_PARENT) { - Logger::debug('Got comment', ['item' => $b]); + DI::logger()->debug('Got comment', ['item' => $b]); if ($b['deleted']) { - $uri = bluesky_get_uri_class($b['uri']); + $uri = DI::atpProcessor()->getUriClass($b['uri']); if (empty($uri)) { - Logger::debug('Not a bluesky post', ['uri' => $b['uri']]); + DI::logger()->debug('Not a bluesky post', ['uri' => $b['uri']]); return; } bluesky_delete_post($b['uri'], $b['uid']); return; } - $root = bluesky_get_uri_class($b['parent-uri']); - $parent = bluesky_get_uri_class($b['thr-parent']); + $root = DI::atpProcessor()->getUriClass($b['parent-uri']); + $parent = DI::atpProcessor()->getUriClass($b['thr-parent']); if (empty($root) || empty($parent)) { - Logger::debug('No bluesky post', ['parent' => $b['parent'], 'thr-parent' => $b['thr-parent']]); + DI::logger()->debug('No bluesky post', ['parent' => $b['parent'], 'thr-parent' => $b['thr-parent']]); return; } if ($b['gravity'] == Item::GRAVITY_COMMENT) { - Logger::debug('Posting comment', ['root' => $root, 'parent' => $parent]); + DI::logger()->debug('Posting comment', ['root' => $root, 'parent' => $parent]); bluesky_create_post($b, $root, $parent); return; } elseif (in_array($b['verb'], [Activity::LIKE, Activity::ANNOUNCE])) { bluesky_create_activity($b, $parent); } return; - } elseif ($b['private'] || !strstr($b['postopts'], 'bluesky')) { + } elseif (($b['private'] == Item::PRIVATE) || !strstr($b['postopts'], 'bluesky')) { return; } @@ -659,12 +592,17 @@ function bluesky_send(array &$b) function bluesky_create_activity(array $item, stdClass $parent = null) { $uid = $item['uid']; - $token = bluesky_get_token($uid); + $token = DI::atProtocol()->getUserToken($uid); if (empty($token)) { return; } - $did = DI::pConfig()->get($uid, 'bluesky', 'did'); + $did = DI::atProtocol()->getUserDid($uid); + if (empty($did)) { + return; + } + + $post = []; if ($item['verb'] == Activity::LIKE) { $record = [ @@ -692,20 +630,20 @@ function bluesky_create_activity(array $item, stdClass $parent = null) ]; } - $activity = bluesky_xrpc_post($uid, 'com.atproto.repo.createRecord', $post); - if (empty($activity)) { + $activity = DI::atProtocol()->XRPCPost($uid, 'com.atproto.repo.createRecord', $post); + if (empty($activity->uri)) { return; } - Logger::debug('Activity done', ['return' => $activity]); - $uri = bluesky_get_uri($activity); - Item::update(['extid' => $uri], ['id' => $item['id']]); - Logger::debug('Set extid', ['id' => $item['id'], 'extid' => $activity]); + DI::logger()->debug('Activity done', ['return' => $activity]); + $uri = DI::atpProcessor()->getUri($activity); + Item::update(['extid' => $uri], ['guid' => $item['guid']]); + DI::logger()->debug('Set extid', ['id' => $item['id'], 'extid' => $activity]); } function bluesky_create_post(array $item, stdClass $root = null, stdClass $parent = null) { $uid = $item['uid']; - $token = bluesky_get_token($uid); + $token = DI::atProtocol()->getUserToken($uid); if (empty($token)) { return; } @@ -724,7 +662,7 @@ function bluesky_create_post(array $item, stdClass $root = null, stdClass $paren $item['body'] .= "\n[url]" . $media['url'] . "[/url]\n"; } } - + if (!empty($item['quote-uri-id'])) { $quote = Post::selectFirstPost(['uri', 'plink'], ['uri-id' => $item['quote-uri-id']]); if (!empty($quote)) { @@ -733,7 +671,9 @@ function bluesky_create_post(array $item, stdClass $root = null, stdClass $paren } } } - + + $item['body'] = bluesky_set_mentions($item['body']); + $urls = bluesky_get_urls($item['body']); $item['body'] = $urls['body']; @@ -772,37 +712,64 @@ function bluesky_create_post(array $item, stdClass $root = null, stdClass $paren $post = [ 'collection' => 'app.bsky.feed.post', - 'repo' => DI::pConfig()->get($uid, 'bluesky', 'did'), + 'repo' => DI::atProtocol()->getUserDid($uid), 'record' => $record ]; - $parent = bluesky_xrpc_post($uid, 'com.atproto.repo.createRecord', $post); - if (empty($parent)) { + $parent = DI::atProtocol()->XRPCPost($uid, 'com.atproto.repo.createRecord', $post); + if (empty($parent->uri)) { if ($part == 0) { Worker::defer(); } return; } - Logger::debug('Posting done', ['return' => $parent]); + DI::logger()->debug('Posting done', ['return' => $parent]); if (empty($root)) { $root = $parent; } if (($key == 0) && ($item['gravity'] != Item::GRAVITY_PARENT)) { - $uri = bluesky_get_uri($parent); - Item::update(['extid' => $uri], ['id' => $item['id']]); - Logger::debug('Set extid', ['id' => $item['id'], 'extid' => $uri]); + $uri = DI::atpProcessor()->getUri($parent); + Item::update(['extid' => $uri], ['guid' => $item['guid']]); + DI::logger()->debug('Set extid', ['id' => $item['id'], 'extid' => $uri]); } } } -function bluesky_get_urls(string $body): array +function bluesky_set_mentions(string $body): string { - // Remove all hashtag and mention links + // Remove all url based mention links $body = preg_replace("/([@!])\[url\=(.*?)\](.*?)\[\/url\]/ism", '$1$3', $body); + if (!preg_match_all("/[@!]\[url\=(did:.*?)\](.*?)\[\/url\]/ism", $body, $matches, PREG_SET_ORDER)) { + return $body; + } + + foreach ($matches as $match) { + $contact = Contact::selectFirst(['addr'], ['nurl' => $match[1]]); + if (!empty($contact['addr'])) { + $body = str_replace($match[0], '@[url=' . $match[1] . ']' . $contact['addr'] . '[/url]', $body); + } else { + $body = str_replace($match[0], '@' . $match[2], $body); + } + } + + return $body; +} + +function bluesky_get_urls(string $body): array +{ $body = BBCode::expandVideoLinks($body); $urls = []; + // Search for Mentions + if (preg_match_all("/[@!]\[url\=(did:.*?)\](.*?)\[\/url\]/ism", $body, $matches, PREG_SET_ORDER)) { + foreach ($matches as $match) { + $text = '@' . $match[2]; + $urls[strpos($body, $match[0])] = ['mention' => $match[1], 'text' => $text, 'hash' => $text]; + $body = str_replace($match[0], $text, $body); + } + } + // Search for hash tags if (preg_match_all("/#\[url\=(https?:.*?)\](.*?)\[\/url\]/ism", $body, $matches, PREG_SET_ORDER)) { foreach ($matches as $match) { @@ -887,6 +854,9 @@ function bluesky_get_facets(string $body, array $urls): array } elseif (!empty($url['url'])) { $feature->uri = $url['url']; $feature->$type = 'app.bsky.richtext.facet#link'; + } elseif (!empty($url['mention'])) { + $feature->did = $url['mention']; + $feature->$type = 'app.bsky.richtext.facet#mention'; } else { continue; } @@ -911,7 +881,14 @@ function bluesky_add_embed(int $uid, array $msg, array $record): array if (empty($blob)) { return []; } - $images[] = ['alt' => $image['description'] ?? '', 'image' => $blob]; + $images[] = [ + 'alt' => $image['description'] ?? '', + 'image' => $blob, + 'aspectRatio' => [ + 'width' => $photo['width'], + 'height' => $photo['height'], + ] + ]; } if (!empty($images)) { $record['embed'] = ['$type' => 'app.bsky.embed.images', 'images' => $images]; @@ -949,35 +926,41 @@ function bluesky_upload_blob(int $uid, array $photo): ?stdClass $picture = Photo::resizeToFileSize($picture, BLUESKY_IMAGE_SIZE[$retrial]); $new_height = $picture->getHeight(); $new_width = $picture->getWidth(); - $content = $picture->asString(); + $content = (string)$picture->asString(); $new_size = strlen($content); - Logger::info('Uploading', ['uid' => $uid, 'retrial' => $retrial, 'height' => $new_height, 'width' => $new_width, 'size' => $new_size, 'orig-height' => $height, 'orig-width' => $width, 'orig-size' => $size]); + if (($size != 0) && ($new_size == 0) && ($retrial == 0)) { + DI::logger()->warning('Size is empty after resize, uploading original file', ['uid' => $uid, 'retrial' => $retrial, 'height' => $new_height, 'width' => $new_width, 'size' => $new_size, 'orig-height' => $height, 'orig-width' => $width, 'orig-size' => $size]); + $content = Photo::getImageForPhoto($photo); + } else { + DI::logger()->info('Uploading', ['uid' => $uid, 'retrial' => $retrial, 'height' => $new_height, 'width' => $new_width, 'size' => $new_size, 'orig-height' => $height, 'orig-width' => $width, 'orig-size' => $size]); + } - $data = bluesky_post($uid, '/xrpc/com.atproto.repo.uploadBlob', $content, ['Content-type' => $photo['type'], 'Authorization' => ['Bearer ' . bluesky_get_token($uid)]]); - if (empty($data)) { - Logger::info('Uploading failed', ['uid' => $uid, 'retrial' => $retrial, 'height' => $new_height, 'width' => $new_width, 'size' => $new_size, 'orig-height' => $height, 'orig-width' => $width, 'orig-size' => $size]); + $data = DI::atProtocol()->post($uid, '/xrpc/com.atproto.repo.uploadBlob', $content, ['Content-type' => $photo['type'], 'Authorization' => ['Bearer ' . DI::atProtocol()->getUserToken($uid)]]); + if (empty($data) || empty($data->blob)) { + DI::logger()->info('Uploading failed', ['uid' => $uid, 'retrial' => $retrial, 'height' => $new_height, 'width' => $new_width, 'size' => $new_size, 'orig-height' => $height, 'orig-width' => $width, 'orig-size' => $size]); return null; } - Logger::debug('Uploaded blob', ['return' => $data, 'uid' => $uid, 'retrial' => $retrial, 'height' => $new_height, 'width' => $new_width, 'size' => $new_size, 'orig-height' => $height, 'orig-width' => $width, 'orig-size' => $size]); + Item::incrementOutbound(Protocol::BLUESKY); + DI::logger()->debug('Uploaded blob', ['return' => $data, 'uid' => $uid, 'retrial' => $retrial, 'height' => $new_height, 'width' => $new_width, 'size' => $new_size, 'orig-height' => $height, 'orig-width' => $width, 'orig-size' => $size]); return $data->blob; } function bluesky_delete_post(string $uri, int $uid) { - $parts = bluesky_get_uri_parts($uri); + $parts = DI::atpProcessor()->getUriParts($uri); if (empty($parts)) { - Logger::debug('No uri delected', ['uri' => $uri]); + DI::logger()->debug('No uri delected', ['uri' => $uri]); return; } - bluesky_xrpc_post($uid, 'com.atproto.repo.deleteRecord', $parts); - Logger::debug('Deleted', ['parts' => $parts]); + DI::atProtocol()->XRPCPost($uid, 'com.atproto.repo.deleteRecord', $parts); + DI::logger()->debug('Deleted', ['parts' => $parts]); } -function bluesky_fetch_timeline(int $uid, int $last_poll) +function bluesky_fetch_timeline(int $uid) { - $data = bluesky_xrpc_get($uid, 'app.bsky.feed.getTimeline'); + $data = DI::atProtocol()->XRPCGet('app.bsky.feed.getTimeline', [], $uid); if (empty($data)) { return; } @@ -987,14 +970,40 @@ function bluesky_fetch_timeline(int $uid, int $last_poll) } foreach (array_reverse($data->feed) as $entry) { - bluesky_process_post($entry->post, $uid, $uid, Item::PR_NONE, 0, 0, $last_poll); + $causer = DI::atpActor()->getContactByDID($entry->post->author->did, $uid, 0, true); + if (!empty($entry->reply)) { + if (!empty($entry->reply->root)) { + bluesky_complete_post($entry->reply->root, $uid, Item::PR_COMMENT, $causer['id'], Conversation::PARCEL_CONNECTOR); + } + if (!empty($entry->reply->parent)) { + bluesky_complete_post($entry->reply->parent, $uid, Item::PR_COMMENT, $causer['id'], Conversation::PARCEL_CONNECTOR); + } + } + DI::atpProcessor()->processPost($entry->post, $uid, Item::PR_NONE, 0, 0, Conversation::PARCEL_CONNECTOR); if (!empty($entry->reason)) { - bluesky_process_reason($entry->reason, bluesky_get_uri($entry->post), $uid); + bluesky_process_reason($entry->reason, DI::atpProcessor()->getUri($entry->post), $uid); + } + } +} + +function bluesky_complete_post(stdClass $post, int $uid, int $post_reason, int $causer, int $protocol): int +{ + $complete = DI::pConfig()->get($uid, 'bluesky', 'complete_threads'); + $existing_uri = DI::atpProcessor()->getPostUri(DI::atpProcessor()->getUri($post), $uid); + if (!empty($existing_uri)) { + $comments = Post::countPosts(['thr-parent' => $existing_uri, 'gravity' => Item::GRAVITY_COMMENT]); + if (($post->replyCount <= $comments) || !$complete) { + return DI::atpProcessor()->fetchUriId($existing_uri, $uid); } } - // @todo Support paging - // [cursor] => 1684670516000::bafyreidq3ilwslmlx72jf5vrk367xcc63s6lrhzlyup2bi3zwcvso6w2vi + if ($complete) { + $uri = DI::atpProcessor()->fetchMissingPost(DI::atpProcessor()->getUri($post), $uid, $post_reason, $causer, 0, '', true, $protocol); + $uri_id = DI::atpProcessor()->fetchUriId($uri, $uid); + } else { + $uri_id = DI::atpProcessor()->processPost($post, $uid, $post_reason, $causer, 0, $protocol); + } + return $uri_id; } function bluesky_process_reason(stdClass $reason, string $uri, int $uid) @@ -1004,15 +1013,15 @@ function bluesky_process_reason(stdClass $reason, string $uri, int $uid) return; } - $contact = bluesky_get_contact($reason->by, $uid, $uid); + $contact = DI::atpActor()->getContactByDID($reason->by->did, $uid, 0); $item = [ 'network' => Protocol::BLUESKY, + 'protocol' => Conversation::PARCEL_CONNECTOR, 'uid' => $uid, 'wall' => false, 'uri' => $reason->by->did . '/app.bsky.feed.repost/' . $reason->indexedAt, 'private' => Item::UNLISTED, - 'verb' => Activity::POST, 'contact-id' => $contact['id'], 'author-name' => $contact['name'], 'author-link' => $contact['url'], @@ -1028,91 +1037,96 @@ function bluesky_process_reason(stdClass $reason, string $uri, int $uid) return; } + if (Post::exists(['uid' => $item['uid'], 'thr-parent' => $item['thr-parent'], 'verb' => $item['verb'], 'contact-id' => $item['contact-id']])) { + return; + } + $item['guid'] = Item::guidFromUri($item['uri'], $contact['alias']); $item['owner-name'] = $item['author-name']; $item['owner-link'] = $item['author-link']; $item['owner-avatar'] = $item['author-avatar']; if (Item::insert($item)) { - $cdata = Contact::getPublicAndUserContactID($contact['id'], $uid); - Item::update(['post-reason' => Item::PR_ANNOUNCEMENT, 'causer-id' => $cdata['public']], ['uri' => $uri, 'uid' => $uid]); + $pcid = Contact::getPublicContactId($contact['id'], $uid); + Item::update(['post-reason' => Item::PR_ANNOUNCEMENT, 'causer-id' => $pcid], ['uri' => $uri, 'uid' => $uid]); } } -function bluesky_fetch_notifications(int $uid, int $last_poll) +function bluesky_fetch_notifications(int $uid) { - $data = bluesky_xrpc_get($uid, 'app.bsky.notification.listNotifications'); + $data = DI::atProtocol()->XRPCGet('app.bsky.notification.listNotifications', [], $uid); if (empty($data->notifications)) { return; } + foreach ($data->notifications as $notification) { - $uri = bluesky_get_uri($notification); + $uri = DI::atpProcessor()->getUri($notification); if (Post::exists(['uri' => $uri, 'uid' => $uid]) || Post::exists(['extid' => $uri, 'uid' => $uid])) { - Logger::debug('Notification already processed', ['uid' => $uid, 'reason' => $notification->reason, 'uri' => $uri, 'indexedAt' => $notification->indexedAt]); + DI::logger()->debug('Notification already processed', ['uid' => $uid, 'reason' => $notification->reason, 'uri' => $uri, 'indexedAt' => $notification->indexedAt]); continue; } - Logger::debug('Process notification', ['uid' => $uid, 'reason' => $notification->reason, 'uri' => $uri, 'indexedAt' => $notification->indexedAt]); + DI::logger()->debug('Process notification', ['uid' => $uid, 'reason' => $notification->reason, 'uri' => $uri, 'indexedAt' => $notification->indexedAt]); switch ($notification->reason) { case 'like': - $item = bluesky_get_header($notification, $uri, $uid, $uid); + $item = DI::atpProcessor()->getHeaderFromPost($notification, $uri, $uid, Conversation::PARCEL_CONNECTOR); $item['gravity'] = Item::GRAVITY_ACTIVITY; $item['body'] = $item['verb'] = Activity::LIKE; - $item['thr-parent'] = bluesky_get_uri($notification->record->subject); - $item['thr-parent'] = bluesky_fetch_missing_post($item['thr-parent'], $uid, $uid, Item::PR_FETCHED, $item['contact-id'], 0, $last_poll); + $item['thr-parent'] = DI::atpProcessor()->getUri($notification->record->subject); + $item['thr-parent'] = DI::atpProcessor()->fetchMissingPost($item['thr-parent'], $uid, Item::PR_FETCHED, $item['contact-id'], 0); if (!empty($item['thr-parent'])) { $data = Item::insert($item); - Logger::debug('Got like', ['uid' => $uid, 'result' => $data, 'uri' => $uri]); + DI::logger()->debug('Got like', ['uid' => $uid, 'result' => $data, 'uri' => $uri]); } else { - Logger::info('Thread parent not found', ['uid' => $uid, 'parent' => $item['thr-parent'], 'uri' => $uri]); + DI::logger()->info('Thread parent not found', ['uid' => $uid, 'parent' => $item['thr-parent'], 'uri' => $uri]); } break; case 'repost': - $item = bluesky_get_header($notification, $uri, $uid, $uid); + $item = DI::atpProcessor()->getHeaderFromPost($notification, $uri, $uid, Conversation::PARCEL_CONNECTOR); $item['gravity'] = Item::GRAVITY_ACTIVITY; $item['body'] = $item['verb'] = Activity::ANNOUNCE; - $item['thr-parent'] = bluesky_get_uri($notification->record->subject); - $item['thr-parent'] = bluesky_fetch_missing_post($item['thr-parent'], $uid, $uid, Item::PR_FETCHED, $item['contact-id'], 0, $last_poll); + $item['thr-parent'] = DI::atpProcessor()->getUri($notification->record->subject); + $item['thr-parent'] = DI::atpProcessor()->fetchMissingPost($item['thr-parent'], $uid, Item::PR_FETCHED, $item['contact-id'], 0); if (!empty($item['thr-parent'])) { $data = Item::insert($item); - Logger::debug('Got repost', ['uid' => $uid, 'result' => $data, 'uri' => $uri]); + DI::logger()->debug('Got repost', ['uid' => $uid, 'result' => $data, 'uri' => $uri]); } else { - Logger::info('Thread parent not found', ['uid' => $uid, 'parent' => $item['thr-parent'], 'uri' => $uri]); + DI::logger()->info('Thread parent not found', ['uid' => $uid, 'parent' => $item['thr-parent'], 'uri' => $uri]); } break; case 'follow': - $contact = bluesky_get_contact($notification->author, $uid, $uid); - Logger::debug('New follower', ['uid' => $uid, 'nick' => $contact['nick'], 'uri' => $uri]); + $contact = DI::atpActor()->getContactByDID($notification->author->did, $uid, $uid); + DI::logger()->debug('New follower', ['uid' => $uid, 'nick' => $contact['nick'], 'uri' => $uri]); break; case 'mention': - $contact = bluesky_get_contact($notification->author, 0, $uid); - $result = bluesky_fetch_missing_post($uri, $uid, $uid, Item::PR_TO, $contact['id'], 0, $last_poll); - Logger::debug('Got mention', ['uid' => $uid, 'nick' => $contact['nick'], 'result' => $result, 'uri' => $uri]); + $contact = DI::atpActor()->getContactByDID($notification->author->did, $uid, 0); + $result = DI::atpProcessor()->fetchMissingPost($uri, $uid, Item::PR_TO, $contact['id'], 0); + DI::logger()->debug('Got mention', ['uid' => $uid, 'nick' => $contact['nick'], 'result' => $result, 'uri' => $uri]); break; case 'reply': - $contact = bluesky_get_contact($notification->author, 0, $uid); - $result = bluesky_fetch_missing_post($uri, $uid, $uid, Item::PR_COMMENT, $contact['id'], 0, $last_poll); - Logger::debug('Got reply', ['uid' => $uid, 'nick' => $contact['nick'], 'result' => $result, 'uri' => $uri]); + $contact = DI::atpActor()->getContactByDID($notification->author->did, $uid, 0); + $result = DI::atpProcessor()->fetchMissingPost($uri, $uid, Item::PR_COMMENT, $contact['id'], 0); + DI::logger()->debug('Got reply', ['uid' => $uid, 'nick' => $contact['nick'], 'result' => $result, 'uri' => $uri]); break; case 'quote': - $contact = bluesky_get_contact($notification->author, 0, $uid); - $result = bluesky_fetch_missing_post($uri, $uid, $uid, Item::PR_PUSHED, $contact['id'], 0, $last_poll); - Logger::debug('Got quote', ['uid' => $uid, 'nick' => $contact['nick'], 'result' => $result, 'uri' => $uri]); + $contact = DI::atpActor()->getContactByDID($notification->author->did, $uid, 0); + $result = DI::atpProcessor()->fetchMissingPost($uri, $uid, Item::PR_PUSHED, $contact['id'], 0); + DI::logger()->debug('Got quote', ['uid' => $uid, 'nick' => $contact['nick'], 'result' => $result, 'uri' => $uri]); break; default: - Logger::notice('Unhandled reason', ['reason' => $notification->reason, 'uri' => $uri]); + DI::logger()->notice('Unhandled reason', ['reason' => $notification->reason, 'uri' => $uri]); break; } } } -function bluesky_fetch_feed(int $uid, string $feed, int $last_poll) +function bluesky_fetch_feed(int $uid, string $feed) { - $data = bluesky_xrpc_get($uid, 'app.bsky.feed.getFeed', ['feed' => $feed]); + $data = DI::atProtocol()->XRPCGet('app.bsky.feed.getFeed', ['feed' => $feed], $uid); if (empty($data)) { return; } @@ -1121,8 +1135,8 @@ function bluesky_fetch_feed(int $uid, string $feed, int $last_poll) return; } - $feeddata = bluesky_xrpc_get($uid, 'app.bsky.feed.getFeedGenerator', ['feed' => $feed]); - if (!empty($feeddata)) { + $feeddata = DI::atProtocol()->XRPCGet('app.bsky.feed.getFeedGenerator', ['feed' => $feed], $uid); + if (!empty($feeddata) && !empty($feeddata->view)) { $feedurl = $feeddata->view->uri; $feedname = $feeddata->view->displayName; } else { @@ -1131,525 +1145,49 @@ function bluesky_fetch_feed(int $uid, string $feed, int $last_poll) } foreach (array_reverse($data->feed) as $entry) { - $contact = bluesky_get_contact($entry->post->author, 0, $uid); + $contact = DI::atpActor()->getContactByDID($entry->post->author->did, $uid, 0); $languages = $entry->post->record->langs ?? []; if (!Relay::isWantedLanguage($entry->post->record->text, 0, $contact['id'] ?? 0, $languages)) { - Logger::debug('Unwanted language detected', ['text' => $entry->post->record->text]); + DI::logger()->debug('Unwanted language detected', ['languages' => $languages, 'text' => $entry->post->record->text]); continue; } - $uri_id = bluesky_process_post($entry->post, $uid, $uid, Item::PR_TAG, 0, 0, $last_poll); + $causer = DI::atpActor()->getContactByDID($entry->post->author->did, $uid, 0); + $uri_id = bluesky_complete_post($entry->post, $uid, Item::PR_TAG, $causer['id'], Conversation::PARCEL_CONNECTOR); if (!empty($uri_id)) { $stored = Post\Category::storeFileByURIId($uri_id, $uid, Post\Category::SUBCRIPTION, $feedname, $feedurl); - Logger::debug('Stored tag subscription for user', ['uri-id' => $uri_id, 'uid' => $uid, 'name' => $feedname, 'url' => $feedurl, 'stored' => $stored]); + DI::logger()->debug('Stored tag subscription for user', ['uri-id' => $uri_id, 'uid' => $uid, 'name' => $feedname, 'url' => $feedurl, 'stored' => $stored]); } else { - Logger::notice('Post not found', ['entry' => $entry]); + DI::logger()->notice('Post not found', ['entry' => $entry]); } if (!empty($entry->reason)) { - bluesky_process_reason($entry->reason, bluesky_get_uri($entry->post), $uid); + bluesky_process_reason($entry->reason, DI::atpProcessor()->getUri($entry->post), $uid); } } } -function bluesky_process_post(stdClass $post, int $uid, int $fetch_uid, int $post_reason, int $causer, int $level, int $last_poll): int -{ - $uri = bluesky_get_uri($post); - - if ($uri_id = bluesky_fetch_uri_id($uri, $uid)) { - return $uri_id; - } - - if (empty($post->record)) { - Logger::debug('Invalid post', ['uri' => $uri]); - return 0; - } - - Logger::debug('Importing post', ['uid' => $uid, 'indexedAt' => $post->indexedAt, 'uri' => $post->uri, 'cid' => $post->cid, 'root' => $post->record->reply->root ?? '']); - - $item = bluesky_get_header($post, $uri, $uid, $fetch_uid); - $item = bluesky_get_content($item, $post->record, $uri, $uid, $fetch_uid, $level, $last_poll); - if (empty($item)) { - return 0; - } - - if (!empty($post->embed)) { - $item = bluesky_add_media($post->embed, $item, $uid, $level, $last_poll); - } - - if (empty($item['post-reason'])) { - $item['post-reason'] = $post_reason; - } - - if ($causer != 0) { - $item['causer-id'] = $causer; - } - - Item::insert($item); - return bluesky_fetch_uri_id($uri, $uid); -} - -function bluesky_get_header(stdClass $post, string $uri, int $uid, int $fetch_uid): array -{ - $parts = bluesky_get_uri_parts($uri); - if (empty($post->author) || empty($post->cid) || empty($parts->rkey)) { - return []; - } - $contact = bluesky_get_contact($post->author, $uid, $fetch_uid); - $item = [ - 'network' => Protocol::BLUESKY, - 'uid' => $uid, - 'wall' => false, - 'uri' => $uri, - 'guid' => $post->cid, - 'private' => Item::UNLISTED, - 'verb' => Activity::POST, - 'contact-id' => $contact['id'], - 'author-name' => $contact['name'], - 'author-link' => $contact['url'], - 'author-avatar' => $contact['avatar'], - 'plink' => $contact['alias'] . '/post/' . $parts->rkey, - 'source' => json_encode($post), - ]; - - $item['uri-id'] = ItemURI::getIdByURI($uri); - $item['owner-name'] = $item['author-name']; - $item['owner-link'] = $item['author-link']; - $item['owner-avatar'] = $item['author-avatar']; - - if (in_array($contact['rel'], [Contact::SHARING, Contact::FRIEND])) { - $item['post-reason'] = Item::PR_FOLLOWER; - } - - return $item; -} - -function bluesky_get_content(array $item, stdClass $record, string $uri, int $uid, int $fetch_uid, int $level, int $last_poll): array -{ - if (empty($item)) { - return []; - } - - if (!empty($record->reply)) { - $item['parent-uri'] = bluesky_get_uri($record->reply->root); - if ($item['parent-uri'] != $uri) { - $item['parent-uri'] = bluesky_fetch_missing_post($item['parent-uri'], $uid, $fetch_uid, Item::PR_FETCHED, $item['contact-id'], $level, $last_poll); - if (empty($item['parent-uri'])) { - return []; - } - } - - $item['thr-parent'] = bluesky_get_uri($record->reply->parent); - if (!in_array($item['thr-parent'], [$uri, $item['parent-uri']])) { - $item['thr-parent'] = bluesky_fetch_missing_post($item['thr-parent'], $uid, $fetch_uid, Item::PR_FETCHED, $item['contact-id'], $level, $last_poll, $item['parent-uri']); - if (empty($item['thr-parent'])) { - return []; - } - } - } - - $item['body'] = bluesky_get_text($record, $item['uri-id']); - $item['created'] = DateTimeFormat::utc($record->createdAt, DateTimeFormat::MYSQL); - $item['transmitted-languages'] = $record->langs ?? []; - - if (($last_poll != 0) && strtotime($item['created']) > $last_poll) { - $item['received'] = $item['created']; - } - - return $item; -} - -function bluesky_get_text(stdClass $record, int $uri_id): string -{ - $text = $record->text ?? ''; - - if (empty($record->facets)) { - return $text; - } - - $facets = []; - foreach ($record->facets as $facet) { - $facets[$facet->index->byteStart] = $facet; - } - krsort($facets); - - foreach ($facets as $facet) { - $prefix = substr($text, 0, $facet->index->byteStart); - $linktext = substr($text, $facet->index->byteStart, $facet->index->byteEnd - $facet->index->byteStart); - $suffix = substr($text, $facet->index->byteEnd); - - $url = ''; - $type = '$type'; - foreach ($facet->features as $feature) { - - switch ($feature->$type) { - case 'app.bsky.richtext.facet#link': - $url = $feature->uri; - break; - - case 'app.bsky.richtext.facet#mention': - $contact = Contact::getByURL($feature->did, null, ['id']); - if (!empty($contact['id'])) { - $url = DI::baseUrl() . '/contact/' . $contact['id']; - if (substr($linktext, 0, 1) == '@') { - $prefix .= '@'; - $linktext = substr($linktext, 1); - } - } - break; - - case 'app.bsky.richtext.facet#tag'; - Tag::store($uri_id, Tag::HASHTAG, $feature->tag); - $url = DI::baseUrl() . '/search?tag=' . urlencode($feature->tag); - $linktext = '#' . $feature->tag; - break; - - default: - Logger::notice('Unhandled feature type', ['type' => $feature->$type, 'feature' => $feature, 'record' => $record]); - break; - } - } - if (!empty($url)) { - $text = $prefix . '[url=' . $url . ']' . $linktext . '[/url]' . $suffix; - } - } - return $text; -} - -function bluesky_add_media(stdClass $embed, array $item, int $fetch_uid, int $level, int $last_poll): array -{ - $type = '$type'; - switch ($embed->$type) { - case 'app.bsky.embed.images#view': - foreach ($embed->images as $image) { - $media = [ - 'uri-id' => $item['uri-id'], - 'type' => Post\Media::IMAGE, - 'url' => $image->fullsize, - 'preview' => $image->thumb, - 'description' => $image->alt, - ]; - Post\Media::insert($media); - } - break; - - case 'app.bsky.embed.external#view': - $media = [ - 'uri-id' => $item['uri-id'], - 'type' => Post\Media::HTML, - 'url' => $embed->external->uri, - 'name' => $embed->external->title, - 'description' => $embed->external->description, - ]; - Post\Media::insert($media); - break; - - case 'app.bsky.embed.record#view': - $original_uri = $uri = bluesky_get_uri($embed->record); - $uri = bluesky_fetch_missing_post($uri, $item['uid'], $fetch_uid, Item::PR_FETCHED, $item['contact-id'], $level, $last_poll); - if ($uri) { - $shared = Post::selectFirst(['uri-id'], ['uri' => $uri, 'uid' => [$item['uid'], 0]]); - $uri_id = $shared['uri-id'] ?? 0; - } - if (!empty($uri_id)) { - $item['quote-uri-id'] = $uri_id; - } else { - Logger::debug('Quoted post could not be fetched', ['original-uri' => $original_uri, 'uri' => $uri]); - } - break; - - case 'app.bsky.embed.recordWithMedia#view': - bluesky_add_media($embed->media, $item, $fetch_uid, $level, $last_poll); - $original_uri = $uri = bluesky_get_uri($embed->record->record); - $uri = bluesky_fetch_missing_post($uri, $item['uid'], $fetch_uid, Item::PR_FETCHED, $item['contact-id'], $level, $last_poll); - if ($uri) { - $shared = Post::selectFirst(['uri-id'], ['uri' => $uri, 'uid' => [$item['uid'], 0]]); - $uri_id = $shared['uri-id'] ?? 0; - } - if (!empty($uri_id)) { - $item['quote-uri-id'] = $uri_id; - } else { - Logger::debug('Quoted post could not be fetched', ['original-uri' => $original_uri, 'uri' => $uri]); - } - break; - - default: - Logger::notice('Unhandled embed type', ['uri-id' => $item['uri-id'], 'type' => $embed->$type, 'embed' => $embed]); - break; - } - return $item; -} - -function bluesky_get_uri(stdClass $post): string -{ - if (empty($post->cid)) { - Logger::info('Invalid URI', ['post' => $post]); - return ''; - } - return $post->uri . ':' . $post->cid; -} - -function bluesky_get_uri_class(string $uri): ?stdClass -{ - if (empty($uri)) { - return null; - } - - $elements = explode(':', $uri); - if (empty($elements) || ($elements[0] != 'at')) { - $post = Post::selectFirstPost(['extid'], ['uri' => $uri]); - return bluesky_get_uri_class($post['extid'] ?? ''); - } - - $class = new stdClass; - - $class->cid = array_pop($elements); - $class->uri = implode(':', $elements); - - if ((substr_count($class->uri, '/') == 2) && (substr_count($class->cid, '/') == 2)) { - $class->uri .= ':' . $class->cid; - $class->cid = ''; - } - - return $class; -} - -function bluesky_get_uri_parts(string $uri): ?stdClass -{ - $class = bluesky_get_uri_class($uri); - if (empty($class)) { - return null; - } - - $parts = explode('/', substr($class->uri, 5)); - - $class = new stdClass; - - $class->repo = $parts[0]; - $class->collection = $parts[1]; - $class->rkey = $parts[2]; - - return $class; -} - -function bluesky_fetch_missing_post(string $uri, int $uid, int $fetch_uid, int $post_reason, int $causer, int $level, int $last_poll, string $fallback = ''): string -{ - $fetched_uri = bluesky_fetch_post($uri, $uid); - if (!empty($fetched_uri)) { - return $fetched_uri; - } - - if (++$level > 100) { - Logger::info('Recursion level too deep', ['level' => $level, 'uid' => $uid, 'uri' => $uri, 'fallback' => $fallback]); - // When the level is too deep we will fallback to the parent uri. - // Allthough the threading won't be correct, we at least had stored all posts and won't try again - return $fallback; - } - - $class = bluesky_get_uri_class($uri); - $fetch_uri = $class->uri; - - Logger::debug('Fetch missing post', ['level' => $level, 'uid' => $uid, 'uri' => $uri]); - $data = bluesky_xrpc_get($fetch_uid, 'app.bsky.feed.getPostThread', ['uri' => $fetch_uri]); - if (empty($data)) { - Logger::info('Thread was not fetched', ['level' => $level, 'uid' => $uid, 'uri' => $uri, 'fallback' => $fallback]); - return $fallback; - } - - Logger::debug('Reply count', ['level' => $level, 'uid' => $uid, 'uri' => $uri]); - - if ($causer != 0) { - $cdata = Contact::getPublicAndUserContactID($causer, $uid); - $causer = $cdata['public'] ?? 0; - } - - return bluesky_process_thread($data->thread, $uid, $fetch_uid, $post_reason, $causer, $level, $last_poll); -} - -function bluesky_fetch_post(string $uri, int $uid): string -{ - if (Post::exists(['uri' => $uri, 'uid' => [$uid, 0]])) { - Logger::debug('Post exists', ['uri' => $uri]); - return $uri; - } - - $reply = Post::selectFirst(['uri'], ['extid' => $uri, 'uid' => [$uid, 0]]); - if (!empty($reply['uri'])) { - Logger::debug('Post with extid exists', ['uri' => $uri]); - return $reply['uri']; - } - return ''; -} - -function bluesky_fetch_uri_id(string $uri, int $uid): string -{ - $reply = Post::selectFirst(['uri-id'], ['uri' => $uri, 'uid' => [$uid, 0]]); - if (!empty($reply['uri-id'])) { - Logger::debug('Post with extid exists', ['uri' => $uri]); - return $reply['uri-id']; - } - $reply = Post::selectFirst(['uri-id'], ['extid' => $uri, 'uid' => [$uid, 0]]); - if (!empty($reply['uri-id'])) { - Logger::debug('Post with extid exists', ['uri' => $uri]); - return $reply['uri-id']; - } - return 0; -} - -function bluesky_process_thread(stdClass $thread, int $uid, int $fetch_uid, int $post_reason, int $causer, int $level, int $last_poll): string -{ - if (empty($thread->post)) { - Logger::info('Invalid post', ['post' => $thread]); - return ''; - } - $uri = bluesky_get_uri($thread->post); - - $fetched_uri = bluesky_fetch_post($uri, $uid); - if (empty($fetched_uri)) { - $uri_id = bluesky_process_post($thread->post, $uid, $fetch_uid, $post_reason, $causer, $level, $last_poll); - if ($uri_id) { - Logger::debug('Post has been processed and stored', ['uri-id' => $uri_id, 'uri' => $uri]); - return $uri; - } else { - Logger::info('Post has not not been stored', ['uri' => $uri]); - return ''; - } - } else { - Logger::debug('Post exists', ['uri' => $uri]); - $uri = $fetched_uri; - } - - foreach ($thread->replies ?? [] as $reply) { - $reply_uri = bluesky_process_thread($reply, $uid, $fetch_uid, Item::PR_FETCHED, $causer, $level, $last_poll); - Logger::debug('Reply has been processed', ['uri' => $uri, 'reply' => $reply_uri]); - } - - return $uri; -} - -function bluesky_get_contact(stdClass $author, int $uid, int $fetch_uid): array -{ - $condition = ['network' => Protocol::BLUESKY, 'uid' => 0, 'url' => $author->did]; - $contact = Contact::selectFirst(['id', 'updated'], $condition); - - $update = empty($contact) || $contact['updated'] < DateTimeFormat::utc('now -24 hours'); - - $public_fields = $fields = bluesky_get_contact_fields($author, $uid, $fetch_uid, $update); - - $public_fields['uid'] = 0; - $public_fields['rel'] = Contact::NOTHING; - - if (empty($contact)) { - $cid = Contact::insert($public_fields); - } else { - $cid = $contact['id']; - Contact::update($public_fields, ['id' => $cid], true); - } - - if ($uid != 0) { - $condition = ['network' => Protocol::BLUESKY, 'uid' => $uid, 'url' => $author->did]; - - $contact = Contact::selectFirst(['id', 'rel', 'uid'], $condition); - if (!isset($fields['rel']) && isset($contact['rel'])) { - $fields['rel'] = $contact['rel']; - } elseif (!isset($fields['rel'])) { - $fields['rel'] = Contact::NOTHING; - } - } - - if (($uid != 0) && ($fields['rel'] != Contact::NOTHING)) { - if (empty($contact)) { - $cid = Contact::insert($fields); - } else { - $cid = $contact['id']; - Contact::update($fields, ['id' => $cid], true); - } - Logger::debug('Get user contact', ['id' => $cid, 'uid' => $uid, 'update' => $update]); - } else { - Logger::debug('Get public contact', ['id' => $cid, 'uid' => $uid, 'update' => $update]); - } - if (!empty($author->avatar)) { - Contact::updateAvatar($cid, $author->avatar); - } - - return Contact::getById($cid); -} - -function bluesky_get_contact_fields(stdClass $author, int $uid, int $fetch_uid, bool $update): array -{ - $nick = $author->handle ?? $author->did; - $name = $author->displayName ?? $nick; - $fields = [ - 'uid' => $uid, - 'network' => Protocol::BLUESKY, - 'priority' => 1, - 'writable' => true, - 'blocked' => false, - 'readonly' => false, - 'pending' => false, - 'url' => $author->did, - 'nurl' => $author->did, - 'alias' => BLUESKY_WEB . '/profile/' . $nick, - 'name' => $name ?: $nick, - 'nick' => $nick, - 'addr' => $nick, - ]; - - if (!$update) { - Logger::debug('Got contact fields', ['uid' => $uid, 'url' => $fields['url']]); - return $fields; - } - - $fields['baseurl'] = bluesky_get_pds($author->did); - if (!empty($fields['baseurl'])) { - GServer::check($fields['baseurl'], Protocol::BLUESKY); - $fields['gsid'] = GServer::getID($fields['baseurl'], true); - } - - $data = bluesky_xrpc_get($fetch_uid, 'app.bsky.actor.getProfile', ['actor' => $author->did]); - if (empty($data)) { - Logger::debug('Error fetching contact fields', ['uid' => $uid, 'url' => $fields['url']]); - return $fields; - } - - $fields['updated'] = DateTimeFormat::utcNow(DateTimeFormat::MYSQL); - - if (!empty($data->description)) { - $fields['about'] = HTML::toBBCode($data->description); - } - - if (!empty($data->banner)) { - $fields['header'] = $data->banner; - } - - if (!empty($data->viewer)) { - if (!empty($data->viewer->following) && !empty($data->viewer->followedBy)) { - $fields['rel'] = Contact::FRIEND; - } elseif (!empty($data->viewer->following) && empty($data->viewer->followedBy)) { - $fields['rel'] = Contact::SHARING; - } elseif (empty($data->viewer->following) && !empty($data->viewer->followedBy)) { - $fields['rel'] = Contact::FOLLOWER; - } else { - $fields['rel'] = Contact::NOTHING; - } - } - - Logger::debug('Got updated contact fields', ['uid' => $uid, 'url' => $fields['url']]); - return $fields; -} - function bluesky_get_feeds(int $uid): array { $type = '$type'; $preferences = bluesky_get_preferences($uid); + if (empty($preferences) || empty($preferences->preferences)) { + return []; + } foreach ($preferences->preferences as $preference) { - if ($preference->$type == 'app.bsky.actor.defs#savedFeedsPref') { - return $preference->pinned ?? []; + if ($preference->$type == 'app.bsky.actor.defs#savedFeedsPrefV2') { + $pinned = []; + foreach ($preference->items as $item) { + if (($item->type == 'feed') && $item->pinned) { + $pinned[] = $item->value; + } + } + return $pinned; } } return []; } -function bluesky_get_preferences(int $uid): stdClass +function bluesky_get_preferences(int $uid): ?stdClass { $cachekey = 'bluesky:preferences:' . $uid; $data = DI::cache()->get($cachekey); @@ -1657,207 +1195,11 @@ function bluesky_get_preferences(int $uid): stdClass return $data; } - $data = bluesky_xrpc_get($uid, 'app.bsky.actor.getPreferences'); + $data = DI::atProtocol()->XRPCGet('app.bsky.actor.getPreferences', [], $uid); + if (empty($data)) { + return null; + } DI::cache()->set($cachekey, $data, Duration::HOUR); return $data; } - -function bluesky_get_did_by_wellknown(string $handle): string -{ - $curlResult = DI::httpClient()->get('http://' . $handle . '/.well-known/atproto-did'); - if ($curlResult->isSuccess() && substr($curlResult->getBodyString(), 0, 4) == 'did:') { - $did = $curlResult->getBodyString(); - if (!bluesky_valid_did($did, $handle)) { - Logger::notice('Invalid DID', ['handle' => $handle, 'did' => $did]); - return ''; - } - Logger::debug('Got DID by wellknown', ['handle' => $handle, 'did' => $did]); - return $did; - } - return ''; -} - -function bluesky_get_did_by_dns(string $handle): string -{ - $records = @dns_get_record('_atproto.' . $handle . '.', DNS_TXT); - if (empty($records)) { - return ''; - } - foreach ($records as $record) { - if (!empty($record['txt']) && substr($record['txt'], 0, 4) == 'did=') { - $did = substr($record['txt'], 4); - if (!bluesky_valid_did($did, $handle)) { - Logger::notice('Invalid DID', ['handle' => $handle, 'did' => $did]); - return ''; - } - Logger::debug('Got DID by DNS', ['handle' => $handle, 'did' => $did]); - return $did; - } - } - return ''; -} - -function bluesky_get_did(string $handle): string -{ - // Deactivated at the moment, since it isn't reliable by now - //$did = bluesky_get_did_by_dns($handle); - //if ($did != '') { - // return $did; - //} - - //$did = bluesky_get_did_by_wellknown($handle); - //if ($did != '') { - // return $did; - //} - - $data = bluesky_get(BLUESKY_PDS . '/xrpc/com.atproto.identity.resolveHandle?handle=' . urlencode($handle)); - if (empty($data) || empty($data->did)) { - return ''; - } - Logger::debug('Got DID by PDS call', ['handle' => $handle, 'did' => $data->did]); - return $data->did; -} - -function bluesky_get_user_pds(int $uid): string -{ - $pds = DI::pConfig()->get($uid, 'bluesky', 'pds'); - if (!empty($pds)) { - return $pds; - } - $did = DI::pConfig()->get($uid, 'bluesky', 'did'); - if (empty($did)) { - Logger::notice('Empty did for user', ['uid' => $uid]); - return ''; - } - $pds = bluesky_get_pds($did); - DI::pConfig()->set($uid, 'bluesky', 'pds', $pds); - return $pds; -} - -function bluesky_get_pds(string $did): ?string -{ - $data = bluesky_get(BLUESKY_DIRECTORY . '/' . $did); - if (empty($data) || empty($data->service)) { - return null; - } - - foreach ($data->service as $service) { - if (($service->id == '#atproto_pds') && ($service->type == 'AtprotoPersonalDataServer') && !empty($service->serviceEndpoint)) { - return $service->serviceEndpoint; - } - } - - return null; -} - -function bluesky_valid_did(string $did, string $handle): bool -{ - $data = bluesky_get(BLUESKY_DIRECTORY . '/' . $did); - if (empty($data) || empty($data->alsoKnownAs)) { - return false; - } - - return in_array('at://' . $handle, $data->alsoKnownAs); -} - -function bluesky_get_token(int $uid): string -{ - $token = DI::pConfig()->get($uid, 'bluesky', 'access_token'); - $created = DI::pConfig()->get($uid, 'bluesky', 'token_created'); - if (empty($token)) { - return ''; - } - - if ($created + 300 < time()) { - return bluesky_refresh_token($uid); - } - return $token; -} - -function bluesky_refresh_token(int $uid): string -{ - $token = DI::pConfig()->get($uid, 'bluesky', 'refresh_token'); - - $data = bluesky_post($uid, '/xrpc/com.atproto.server.refreshSession', '', ['Authorization' => ['Bearer ' . $token]]); - if (empty($data)) { - return ''; - } - - Logger::debug('Refreshed token', ['return' => $data]); - DI::pConfig()->set($uid, 'bluesky', 'access_token', $data->accessJwt); - DI::pConfig()->set($uid, 'bluesky', 'refresh_token', $data->refreshJwt); - DI::pConfig()->set($uid, 'bluesky', 'token_created', time()); - return $data->accessJwt; -} - -function bluesky_create_token(int $uid, string $password): string -{ - $did = DI::pConfig()->get($uid, 'bluesky', 'did'); - - $data = bluesky_post($uid, '/xrpc/com.atproto.server.createSession', json_encode(['identifier' => $did, 'password' => $password]), ['Content-type' => 'application/json']); - if (empty($data)) { - DI::pConfig()->set($uid, 'bluesky', 'status', BLUEKSY_STATUS_TOKEN_FAIL); - return ''; - } - - Logger::debug('Created token', ['return' => $data]); - DI::pConfig()->set($uid, 'bluesky', 'access_token', $data->accessJwt); - DI::pConfig()->set($uid, 'bluesky', 'refresh_token', $data->refreshJwt); - DI::pConfig()->set($uid, 'bluesky', 'token_created', time()); - DI::pConfig()->set($uid, 'bluesky', 'status', BLUEKSY_STATUS_TOKEN_OK); - return $data->accessJwt; -} - -function bluesky_xrpc_post(int $uid, string $url, $parameters): ?stdClass -{ - return bluesky_post($uid, '/xrpc/' . $url, json_encode($parameters), ['Content-type' => 'application/json', 'Authorization' => ['Bearer ' . bluesky_get_token($uid)]]); -} - -function bluesky_post(int $uid, string $url, string $params, array $headers): ?stdClass -{ - try { - $curlResult = DI::httpClient()->post(bluesky_get_user_pds($uid) . $url, $params, $headers); - } catch (\Exception $e) { - Logger::notice('Exception on post', ['exception' => $e]); - DI::pConfig()->set($uid, 'bluesky', 'status', BLUEKSY_STATUS_API_FAIL); - return null; - } - - if (!$curlResult->isSuccess()) { - Logger::notice('API Error', ['error' => json_decode($curlResult->getBodyString()) ?: $curlResult->getBodyString()]); - DI::pConfig()->set($uid, 'bluesky', 'status', BLUEKSY_STATUS_API_FAIL); - return null; - } - - DI::pConfig()->set($uid, 'bluesky', 'status', BLUEKSY_STATUS_SUCCESS); - return json_decode($curlResult->getBodyString()); -} - -function bluesky_xrpc_get(int $uid, string $url, array $parameters = []): ?stdClass -{ - if (!empty($parameters)) { - $url .= '?' . http_build_query($parameters); - } - - $data = bluesky_get(bluesky_get_user_pds($uid) . '/xrpc/' . $url, HttpClientAccept::JSON, [HttpClientOptions::HEADERS => ['Authorization' => ['Bearer ' . bluesky_get_token($uid)]]]); - DI::pConfig()->set($uid, 'bluesky', 'status', is_null($data) ? BLUEKSY_STATUS_API_FAIL : BLUEKSY_STATUS_SUCCESS); - return $data; -} - -function bluesky_get(string $url, string $accept_content = HttpClientAccept::DEFAULT, array $opts = []): ?stdClass -{ - try { - $curlResult = DI::httpClient()->get($url, $accept_content, $opts); - } catch (\Exception $e) { - Logger::notice('Exception on get', ['exception' => $e]); - return null; - } - - if (!$curlResult->isSuccess()) { - Logger::notice('API Error', ['error' => json_decode($curlResult->getBodyString()) ?: $curlResult->getBodyString()]); - return null; - } - - return json_decode($curlResult->getBodyString()); -} diff --git a/bluesky/bluesky_feed.php b/bluesky/bluesky_feed.php index c9a54223..e4aa3fdc 100644 --- a/bluesky/bluesky_feed.php +++ b/bluesky/bluesky_feed.php @@ -1,16 +1,16 @@ $argv[1], 'feed' => $argv[2], 'last_poll' => $argv[3]]); - bluesky_fetch_feed($argv[1], $argv[2], $argv[3]); - Logger::debug('Importing feed - done', ['user' => $argv[1], 'feed' => $argv[2], 'last_poll' => $argv[3]]); + DI::logger()->debug('Importing feed - start', ['user' => $argv[1], 'feed' => $argv[2]]); + bluesky_fetch_feed($argv[1], $argv[2]); + DI::logger()->debug('Importing feed - done', ['user' => $argv[1], 'feed' => $argv[2]]); } diff --git a/bluesky/bluesky_notifications.php b/bluesky/bluesky_notifications.php index ad35dfe0..e1bf2047 100644 --- a/bluesky/bluesky_notifications.php +++ b/bluesky/bluesky_notifications.php @@ -1,16 +1,16 @@ $argv[1], 'last_poll' => $argv[2]]); - bluesky_fetch_notifications($argv[1], $argv[2]); - Logger::notice('importing notifications - done', ['user' => $argv[1], 'last_poll' => $argv[2]]); + DI::logger()->notice('importing notifications - start', ['user' => $argv[1]]); + bluesky_fetch_notifications($argv[1]); + DI::logger()->notice('importing notifications - done', ['user' => $argv[1]]); } diff --git a/bluesky/bluesky_timeline.php b/bluesky/bluesky_timeline.php index 22ef2224..37b22d99 100644 --- a/bluesky/bluesky_timeline.php +++ b/bluesky/bluesky_timeline.php @@ -1,16 +1,16 @@ $argv[1], 'last_poll' => $argv[2]]); - bluesky_fetch_timeline($argv[1], $argv[2]); - Logger::notice('importing timeline - done', ['user' => $argv[1], 'last_poll' => $argv[2]]); + DI::logger()->notice('importing timeline - start', ['user' => $argv[1]]); + bluesky_fetch_timeline($argv[1]); + DI::logger()->notice('importing timeline - done', ['user' => $argv[1]]); } diff --git a/bluesky/lang/C/messages.po b/bluesky/lang/C/messages.po index 0d69cc10..d573972c 100644 --- a/bluesky/lang/C/messages.po +++ b/bluesky/lang/C/messages.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-02-28 03:05+0000\n" +"POT-Creation-Date: 2024-09-29 18:16+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,129 +17,117 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: bluesky.php:325 +#: bluesky.php:335 msgid "Save Settings" msgstr "" -#: bluesky.php:326 +#: bluesky.php:336 msgid "Allow your users to use your hostname for their Bluesky handles" msgstr "" -#: bluesky.php:326 -msgid "" -"Before enabling this option, you have to download and configure the bluesky-" -"handles repository on your system. See https://git.friendi.ca/heluecht/" -"bluesky-handles" +#: bluesky.php:336 +#, php-format +msgid "Before enabling this option, you have to setup a wildcard domain configuration and you have to enable wildcard requests in your webserver configuration. On Apache this is done by adding \"ServerAlias *.%s\" to your HTTP configuration. You don't need to change the HTTPS configuration." msgstr "" -#: bluesky.php:354 +#: bluesky.php:365 #, php-format msgid "Allow to use %s as your Bluesky handle." msgstr "" -#: bluesky.php:354 +#: bluesky.php:365 #, php-format -msgid "" -"When enabled, you can use %s as your Bluesky handle. After you enabled this " -"option, please go to https://bsky.app/settings and select to change your " -"handle. Select that you have got your own domain. Then enter %s and select " -"\"No DNS Panel\". Then select \"Verify Text File\"." -msgstr "" - -#: bluesky.php:361 -msgid "Enable Bluesky Post Addon" -msgstr "" - -#: bluesky.php:362 -msgid "Post to Bluesky by default" -msgstr "" - -#: bluesky.php:363 -msgid "Import the remote timeline" -msgstr "" - -#: bluesky.php:364 -msgid "Import the pinned feeds" -msgstr "" - -#: bluesky.php:364 -msgid "" -"When activated, Posts will be imported from all the feeds that you pinned in " -"Bluesky." -msgstr "" - -#: bluesky.php:366 -msgid "Personal Data Server" -msgstr "" - -#: bluesky.php:366 -msgid "The personal data server (PDS) is the system that hosts your profile." -msgstr "" - -#: bluesky.php:367 -msgid "Bluesky handle" -msgstr "" - -#: bluesky.php:368 -msgid "Bluesky DID" -msgstr "" - -#: bluesky.php:368 -msgid "" -"This is the unique identifier. It will be fetched automatically, when the " -"handle is entered." -msgstr "" - -#: bluesky.php:369 -msgid "Bluesky app password" -msgstr "" - -#: bluesky.php:369 -msgid "" -"Please don't add your real password here, but instead create a specific app " -"password in the Bluesky settings." +msgid "When enabled, you can use %s as your Bluesky handle. After you enabled this option, please go to https://bsky.app/settings and select to change your handle. Select that you have got your own domain. Then enter %s and select \"No DNS Panel\". Then select \"Verify Text File\"." msgstr "" #: bluesky.php:375 +msgid "Enable Bluesky Post Addon" +msgstr "" + +#: bluesky.php:376 +msgid "Post to Bluesky by default" +msgstr "" + +#: bluesky.php:377 +msgid "Import the remote timeline" +msgstr "" + +#: bluesky.php:378 +msgid "Import the pinned feeds" +msgstr "" + +#: bluesky.php:378 +msgid "When activated, Posts will be imported from all the feeds that you pinned in Bluesky." +msgstr "" + +#: bluesky.php:379 +msgid "Complete the threads" +msgstr "" + +#: bluesky.php:379 +msgid "When activated, the system fetches additional replies for the posts in the timeline. This leads to more complete threads." +msgstr "" + +#: bluesky.php:381 +msgid "Personal Data Server" +msgstr "" + +#: bluesky.php:381 +msgid "The personal data server (PDS) is the system that hosts your profile." +msgstr "" + +#: bluesky.php:382 +msgid "Bluesky handle" +msgstr "" + +#: bluesky.php:383 +msgid "Bluesky DID" +msgstr "" + +#: bluesky.php:383 +msgid "This is the unique identifier. It will be fetched automatically, when the handle is entered." +msgstr "" + +#: bluesky.php:384 +msgid "Bluesky app password" +msgstr "" + +#: bluesky.php:384 +msgid "Please don't add your real password here, but instead create a specific app password in the Bluesky settings." +msgstr "" + +#: bluesky.php:390 msgid "Bluesky Import/Export" msgstr "" -#: bluesky.php:385 -msgid "" -"You are not authenticated. Please enter your handle and the app password." +#: bluesky.php:400 +msgid "You are not authenticated. Please enter your handle and the app password." msgstr "" -#: bluesky.php:405 -msgid "" -"You are authenticated to Bluesky. For security reasons the password isn't " -"stored." +#: bluesky.php:420 +msgid "You are authenticated to Bluesky. For security reasons the password isn't stored." msgstr "" -#: bluesky.php:407 -msgid "" -"The communication with the personal data server service (PDS) is established." +#: bluesky.php:422 +msgid "The communication with the personal data server service (PDS) is established." msgstr "" -#: bluesky.php:409 +#: bluesky.php:424 msgid "Communication issues with the personal data server service (PDS)." msgstr "" -#: bluesky.php:411 -msgid "" -"The DID for the provided handle could not be detected. Please check if you " -"entered the correct handle." +#: bluesky.php:426 +msgid "The DID for the provided handle could not be detected. Please check if you entered the correct handle." msgstr "" -#: bluesky.php:413 +#: bluesky.php:428 msgid "The personal data server service (PDS) could not be detected." msgstr "" -#: bluesky.php:415 -msgid "" -"The authentication with the provided handle and password failed. Please " -"check if you entered the correct password." +#: bluesky.php:430 +msgid "The authentication with the provided handle and password failed. Please check if you entered the correct password." msgstr "" -#: bluesky.php:484 +#: bluesky.php:492 msgid "Post to Bluesky" msgstr "" diff --git a/bluesky/templates/connector_settings.tpl b/bluesky/templates/connector_settings.tpl index 3ebea827..a85bcd89 100644 --- a/bluesky/templates/connector_settings.tpl +++ b/bluesky/templates/connector_settings.tpl @@ -3,6 +3,7 @@ {{include file="field_checkbox.tpl" field=$bydefault}} {{include file="field_checkbox.tpl" field=$import}} {{include file="field_checkbox.tpl" field=$import_feeds}} +{{include file="field_checkbox.tpl" field=$complete_threads}} {{if $custom_handle}} {{include file="field_checkbox.tpl" field=$custom_handle}} {{/if}} diff --git a/buglink/buglink.php b/buglink/buglink.php index 78fb8bef..b7dd6504 100644 --- a/buglink/buglink.php +++ b/buglink/buglink.php @@ -6,7 +6,6 @@ * Author: Mike Macgirvin */ -use Friendica\App; use Friendica\Core\Hook; use Friendica\DI; diff --git a/calc/calc.php b/calc/calc.php index a8a340c4..76d1805c 100644 --- a/calc/calc.php +++ b/calc/calc.php @@ -6,7 +6,6 @@ * Author: Mike Macgirvin */ -use Friendica\App; use Friendica\Core\Hook; use Friendica\DI; @@ -16,7 +15,7 @@ function calc_install() { function calc_app_menu(array &$b) { - $b['app_menu'][] = ''; + $b['app_menu'][] = ''; } /** @@ -296,7 +295,7 @@ $o .= <<< EOT

Calculator



-
+
@@ -323,7 +322,7 @@ $o .= <<< EOT - + @@ -345,13 +344,13 @@ $o .= <<< EOT - +
diff --git a/catavatar/catavatar.php b/catavatar/catavatar.php index 2116ac44..7b5f05c0 100644 --- a/catavatar/catavatar.php +++ b/catavatar/catavatar.php @@ -6,11 +6,8 @@ * Author: Fabio */ -use Friendica\App; use Friendica\Core\Hook; -use Friendica\Core\Logger; use Friendica\Core\Renderer; -use Friendica\Core\Worker; use Friendica\Database\DBA; use Friendica\DI; use Friendica\Model\Contact; @@ -29,7 +26,7 @@ function catavatar_install() Hook::register('addon_settings', __FILE__, 'catavatar_addon_settings'); Hook::register('addon_settings_post', __FILE__, 'catavatar_addon_settings_post'); - Logger::notice('registered catavatar'); + DI::logger()->notice('registered catavatar'); } /** diff --git a/catavatar/lang/it/messages.po b/catavatar/lang/it/messages.po index e05bd277..9155bb48 100644 --- a/catavatar/lang/it/messages.po +++ b/catavatar/lang/it/messages.po @@ -6,55 +6,55 @@ # Translators: # fabrixxm , 2018 # Davide Pesenti , 2018 -# Sylke Vicious , 2021 +# Sylke Vicious , 2023 # #, fuzzy msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-12-29 00:53+0000\n" +"POT-Creation-Date: 2021-11-21 19:14-0500\n" "PO-Revision-Date: 2018-04-07 05:23+0000\n" -"Last-Translator: Sylke Vicious , 2021\n" -"Language-Team: Italian (https://www.transifex.com/Friendica/teams/12172/it/)\n" +"Last-Translator: Sylke Vicious , 2023\n" +"Language-Team: Italian (https://app.transifex.com/Friendica/teams/12172/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: it\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" #: catavatar.php:48 -msgid "Use Cat as Avatar" -msgstr "Usa il Gatto come avatar" - -#: catavatar.php:49 -msgid "More Random Cat!" -msgstr "Altro Gatto a caso!" - -#: catavatar.php:50 -msgid "Reset to email Cat" -msgstr "Reimposta Gatto" - -#: catavatar.php:52 -msgid "Cat Avatar Settings" -msgstr "Impostazioni Avatar Gatto" - -#: catavatar.php:53 msgid "Set default profile avatar or randomize the cat." msgstr "Imposta l'immagine di profilo predefinita o crea un gatto casuale." -#: catavatar.php:78 +#: catavatar.php:53 +msgid "Cat Avatar Settings" +msgstr "Impostazioni Avatar Gatto" + +#: catavatar.php:56 +msgid "Use Cat as Avatar" +msgstr "Usa il Gatto come avatar" + +#: catavatar.php:57 +msgid "Another random Cat!" +msgstr "Un altro Gatto casuale!" + +#: catavatar.php:58 +msgid "Reset to email Cat" +msgstr "Reimposta Gatto" + +#: catavatar.php:77 msgid "The cat hadn't found itself." msgstr "Il gatto non ha trovato sé stesso." -#: catavatar.php:87 +#: catavatar.php:86 msgid "There was an error, the cat ran away." msgstr "Si è verificato un errore, il gatto è scappato." -#: catavatar.php:93 +#: catavatar.php:92 msgid "Profile Photos" msgstr "Foto del profilo" -#: catavatar.php:108 +#: catavatar.php:102 msgid "Meow!" msgstr "Miao!" diff --git a/catavatar/lang/it/strings.php b/catavatar/lang/it/strings.php index 3a33374a..8f78b3fe 100644 --- a/catavatar/lang/it/strings.php +++ b/catavatar/lang/it/strings.php @@ -3,13 +3,13 @@ if(! function_exists("string_plural_select_it")) { function string_plural_select_it($n){ $n = intval($n); - return intval($n != 1); + if ($n == 1) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; } }} -$a->strings['Use Cat as Avatar'] = 'Usa il Gatto come avatar'; -$a->strings['More Random Cat!'] = 'Altro Gatto a caso!'; -$a->strings['Reset to email Cat'] = 'Reimposta Gatto'; -$a->strings['Cat Avatar Settings'] = 'Impostazioni Avatar Gatto'; $a->strings['Set default profile avatar or randomize the cat.'] = 'Imposta l\'immagine di profilo predefinita o crea un gatto casuale.'; +$a->strings['Cat Avatar Settings'] = 'Impostazioni Avatar Gatto'; +$a->strings['Use Cat as Avatar'] = 'Usa il Gatto come avatar'; +$a->strings['Another random Cat!'] = 'Un altro Gatto casuale!'; +$a->strings['Reset to email Cat'] = 'Reimposta Gatto'; $a->strings['The cat hadn\'t found itself.'] = 'Il gatto non ha trovato sé stesso.'; $a->strings['There was an error, the cat ran away.'] = 'Si è verificato un errore, il gatto è scappato.'; $a->strings['Profile Photos'] = 'Foto del profilo'; diff --git a/cld/cld.php b/cld/cld.php index 5ca4c932..d4fef6c5 100644 --- a/cld/cld.php +++ b/cld/cld.php @@ -7,7 +7,6 @@ */ use Friendica\Core\Hook; -use Friendica\Core\Logger; use Friendica\DI; function cld_install() @@ -18,7 +17,17 @@ function cld_install() function cld_detect_languages(array &$data) { if (!in_array('cld2', get_loaded_extensions())) { - Logger::warning('CLD2 is not installed.'); + DI::logger()->warning('CLD2 is not installed.'); + return; + } + + if (!class_exists('CLD2Detector')) { + DI::logger()->warning('CLD2Detector class does not exist.'); + return; + } + + if (!class_exists('CLD2Encoding')) { + DI::logger()->warning('CLD2Encoding class does not exist.'); return; } @@ -43,7 +52,7 @@ function cld_detect_languages(array &$data) } if (!$result['is_reliable']) { - Logger::debug('Unreliable detection', ['uri-id' => $data['uri-id'], 'original' => $original, 'detected' => $detected, 'name' => $result['language_name'], 'probability' => $result['language_probability'], 'text' => $data['text']]); + DI::logger()->debug('Unreliable detection', ['uri-id' => $data['uri-id'], 'original' => $original, 'detected' => $detected, 'name' => $result['language_name'], 'probability' => $result['language_probability'], 'text' => $data['text']]); if (($original == $detected) && ($data['detected'][$original] < $result['language_probability'] / 100)) { $data['detected'][$original] = $result['language_probability'] / 100; } @@ -53,12 +62,12 @@ function cld_detect_languages(array &$data) $available = array_keys(DI::l10n()->getLanguageCodes()); if (!in_array($detected, $available)) { - Logger::debug('Unsupported language', ['uri-id' => $data['uri-id'], 'original' => $original, 'detected' => $detected, 'name' => $result['language_name'], 'probability' => $result['language_probability'], 'text' => $data['text']]); + DI::logger()->debug('Unsupported language', ['uri-id' => $data['uri-id'], 'original' => $original, 'detected' => $detected, 'name' => $result['language_name'], 'probability' => $result['language_probability'], 'text' => $data['text']]); return; } if ($original != $detected) { - Logger::debug('Detected different language', ['uri-id' => $data['uri-id'], 'original' => $original, 'detected' => $detected, 'name' => $result['language_name'], 'probability' => $result['language_probability'], 'text' => $data['text']]); + DI::logger()->debug('Detected different language', ['uri-id' => $data['uri-id'], 'original' => $original, 'detected' => $detected, 'name' => $result['language_name'], 'probability' => $result['language_probability'], 'text' => $data['text']]); } $length = count($data['detected']); diff --git a/convert/UnitConvertor.php b/convert/UnitConvertor.php index d7933a8f..a3650e9b 100644 --- a/convert/UnitConvertor.php +++ b/convert/UnitConvertor.php @@ -169,7 +169,6 @@ class UnitConvertor * @param string name of the source unit from which to convert * @param string name of the target unit to which we are converting * @param integer double precision of the end result - * @return void * @access public */ function convert($value, $from_unit, $to_unit, $precision) @@ -280,4 +279,4 @@ class UnitConvertor } // end func getConvSpecs } // end class UnitConvertor -?> \ No newline at end of file +?> diff --git a/convert/convert.php b/convert/convert.php index 57ce6ea8..2545974c 100644 --- a/convert/convert.php +++ b/convert/convert.php @@ -6,7 +6,6 @@ * Author: Mike Macgirvin */ -use Friendica\App; use Friendica\Core\Hook; function convert_install() { @@ -26,7 +25,7 @@ function convert_content() { // @TODO Let's one day rewrite this to a modern composer package include 'UnitConvertor.php'; - class TP_Converter extends UnitConvertor + $conv = new class('en') extends UnitConvertor { public function __construct(string $lang = 'en') { @@ -43,7 +42,7 @@ function convert_content() { private function findBaseUnit($from, $to) { - while (list($skey, $sval) = each($this->bases)) { + foreach ($this->bases as $skey => $sval) { if ($skey == $from || $to == $skey || in_array($to, $sval) || in_array($from, $sval)) { return $skey; } @@ -63,7 +62,7 @@ function convert_content() { $cells[] = $cell; // We now have the base unit and value now lets produce the table; - while (list($key, $val) = each($this->bases[$base_unit])) { + foreach ($this->bases[$base_unit] as $val) { $cell ['value'] = $this->convert($value, $from_unit, $val, $precision) . ' ' . $val; $cell ['class'] = ($val == $from_unit || $val == $to_unit) ? 'framedred' : ''; $cells[] = $cell; @@ -86,9 +85,7 @@ function convert_content() { return $string; } - } - - $conv = new TP_Converter('en'); + }; $conversions = [ 'Temperature' => ['base' => 'Celsius', @@ -176,15 +173,15 @@ function convert_content() { ] ]; - while (list($key, $val) = each($conversions)) { + foreach ($conversions as $key => $val) { $conv->addConversion($val['base'], $val['conv']); $list[$key][] = $val['base']; - while (list($ukey, $uval) = each($val['conv'])) { + foreach ($val['conv'] as $ukey => $uval) { $list[$key][] = $ukey; } } - $o .= '

Unit Conversions

'; + $o = '

Unit Conversions

'; if (isset($_POST['from_unit']) && isset($_POST['value'])) { $o .= ($conv->getTable(intval($_POST['value']), $_POST['from_unit'], $_POST['to_unit'], 5)) . '

'; @@ -202,10 +199,9 @@ function convert_content() { $o .= ''; $o .= ' +
+ +
+ +
+ +
+

Enter id and secret

+

These details are obtained by setting up an app in your provider's developer console. +

+

ClientId:

+

ClientSecret:

+

TenantID (only relevant for Azure):

+ + [ + 'https://outlook.office.com/SMTP.Send', + 'offline_access' + ] + ]; + break; } if (null === $provider) { @@ -142,5 +178,5 @@ if (!isset($_GET['code'])) { ); //Use this to interact with an API on the users behalf //Use this to get a new access token if the old one expires - echo 'Refresh Token: ', $token->getRefreshToken(); + echo 'Refresh Token: ', htmlspecialchars($token->getRefreshToken()); } diff --git a/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-as.php b/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-as.php new file mode 100644 index 00000000..327dfbaf --- /dev/null +++ b/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-as.php @@ -0,0 +1,35 @@ + + */ + +$PHPMAILER_LANG['authenticate'] = 'SMTP ত্ৰুটি: প্ৰমাণীকৰণ কৰিব নোৱাৰি'; +$PHPMAILER_LANG['buggy_php'] = 'আপোনাৰ PHP সংস্কৰণ এটা বাগৰ দ্বাৰা প্ৰভাৱিত হয় যাৰ ফলত নষ্ট বাৰ্তা হব পাৰে । ইয়াক সমাধান কৰিবলে, প্ৰেৰণ কৰিবলে SMTP ব্যৱহাৰ কৰক, আপোনাৰ php.ini ত mail.add_x_header বিকল্প নিষ্ক্ৰিয় কৰক, MacOS বা Linux লৈ সলনি কৰক, বা আপোনাৰ PHP সংস্কৰণ 7.0.17+ বা 7.1.3+ লৈ সলনি কৰক ।'; +$PHPMAILER_LANG['connect_host'] = 'SMTP ত্ৰুটি: SMTP চাৰ্ভাৰৰ সৈতে সংযোগ কৰিবলে অক্ষম'; +$PHPMAILER_LANG['data_not_accepted'] = 'SMTP ত্ৰুটি: তথ্য গ্ৰহণ কৰা হোৱা নাই'; +$PHPMAILER_LANG['empty_message'] = 'বাৰ্তাৰ মূখ্য অংশ খালী।'; +$PHPMAILER_LANG['encoding'] = 'অজ্ঞাত এনকোডিং: '; +$PHPMAILER_LANG['execute'] = 'এক্সিকিউট কৰিব নোৱাৰি: '; +$PHPMAILER_LANG['extension_missing'] = 'সম্প্ৰসাৰণ নোহোৱা হৈছে: '; +$PHPMAILER_LANG['file_access'] = 'ফাইল অভিগম কৰিবলে অক্ষম: '; +$PHPMAILER_LANG['file_open'] = 'ফাইল ত্ৰুটি: ফাইল খোলিবলৈ অক্ষম: '; +$PHPMAILER_LANG['from_failed'] = 'নিম্নলিখিত প্ৰেৰকৰ ঠিকনা(সমূহ) ব্যৰ্থ: '; +$PHPMAILER_LANG['instantiate'] = 'মেইল ফাংচনৰ এটা উদাহৰণ সৃষ্টি কৰিবলে অক্ষম'; +$PHPMAILER_LANG['invalid_address'] = 'প্ৰেৰণ কৰিব নোৱাৰি: অবৈধ ইমেইল ঠিকনা: '; +$PHPMAILER_LANG['invalid_header'] = 'অবৈধ হেডাৰৰ নাম বা মান'; +$PHPMAILER_LANG['invalid_hostentry'] = 'অবৈধ হোষ্টেন্ট্ৰি: '; +$PHPMAILER_LANG['invalid_host'] = 'অবৈধ হস্ট:'; +$PHPMAILER_LANG['mailer_not_supported'] = 'মেইলাৰ সমৰ্থিত নহয়।'; +$PHPMAILER_LANG['provide_address'] = 'আপুনি অন্ততঃ এটা গন্তব্য ইমেইল ঠিকনা দিব লাগিব'; +$PHPMAILER_LANG['recipients_failed'] = 'SMTP ত্ৰুটি: নিম্নলিখিত গন্তব্যস্থানসমূহ ব্যৰ্থ: '; +$PHPMAILER_LANG['signing'] = 'স্বাক্ষৰ কৰাত ব্যৰ্থ: '; +$PHPMAILER_LANG['smtp_code'] = 'SMTP কড: '; +$PHPMAILER_LANG['smtp_code_ex'] = 'অতিৰিক্ত SMTP তথ্য: '; +$PHPMAILER_LANG['smtp_detail'] = 'বিৱৰণ:'; +$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP সংযোগ() ব্যৰ্থ'; +$PHPMAILER_LANG['smtp_error'] = 'SMTP চাৰ্ভাৰৰ ত্ৰুটি: '; +$PHPMAILER_LANG['variable_set'] = 'চলক নিৰ্ধাৰণ কৰিব পৰা নগল: '; +$PHPMAILER_LANG['extension_missing'] = 'অনুপস্থিত সম্প্ৰসাৰণ: '; diff --git a/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-bn.php b/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-bn.php new file mode 100644 index 00000000..47365108 --- /dev/null +++ b/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-bn.php @@ -0,0 +1,35 @@ + + */ + +$PHPMAILER_LANG['authenticate'] = 'SMTP ত্রুটি: প্রমাণীকরণ করতে অক্ষম৷'; +$PHPMAILER_LANG['buggy_php'] = 'আপনার PHP সংস্করণ একটি বাগ দ্বারা প্রভাবিত হয় যার ফলে দূষিত বার্তা হতে পারে। এটি ঠিক করতে, পাঠাতে SMTP ব্যবহার করুন, আপনার php.ini এ mail.add_x_header বিকল্পটি নিষ্ক্রিয় করুন, MacOS বা Linux-এ স্যুইচ করুন, অথবা আপনার PHP সংস্করণকে 7.0.17+ বা 7.1.3+ এ পরিবর্তন করুন।'; +$PHPMAILER_LANG['connect_host'] = 'SMTP ত্রুটি: SMTP সার্ভারের সাথে সংযোগ করতে অক্ষম৷'; +$PHPMAILER_LANG['data_not_accepted'] = 'SMTP ত্রুটি: ডেটা গ্রহণ করা হয়নি৷'; +$PHPMAILER_LANG['empty_message'] = 'বার্তার অংশটি খালি।'; +$PHPMAILER_LANG['encoding'] = 'অজানা এনকোডিং: '; +$PHPMAILER_LANG['execute'] = 'নির্বাহ করতে অক্ষম: '; +$PHPMAILER_LANG['extension_missing'] = 'এক্সটেনশন অনুপস্থিত:'; +$PHPMAILER_LANG['file_access'] = 'ফাইল অ্যাক্সেস করতে অক্ষম: '; +$PHPMAILER_LANG['file_open'] = 'ফাইল ত্রুটি: ফাইল খুলতে অক্ষম: '; +$PHPMAILER_LANG['from_failed'] = 'নিম্নলিখিত প্রেরকের ঠিকানা(গুলি) ব্যর্থ হয়েছে: '; +$PHPMAILER_LANG['instantiate'] = 'মেল ফাংশনের একটি উদাহরণ তৈরি করতে অক্ষম৷'; +$PHPMAILER_LANG['invalid_address'] = 'পাঠাতে অক্ষম: অবৈধ ইমেল ঠিকানা: '; +$PHPMAILER_LANG['invalid_header'] = 'অবৈধ হেডার নাম বা মান'; +$PHPMAILER_LANG['invalid_hostentry'] = 'অবৈধ হোস্টেন্ট্রি: '; +$PHPMAILER_LANG['invalid_host'] = 'অবৈধ হোস্ট:'; +$PHPMAILER_LANG['mailer_not_supported'] = 'মেইলার সমর্থিত নয়।'; +$PHPMAILER_LANG['provide_address'] = 'আপনাকে অবশ্যই অন্তত একটি গন্তব্য ইমেল ঠিকানা প্রদান করতে হবে৷'; +$PHPMAILER_LANG['recipients_failed'] = 'SMTP ত্রুটি: নিম্নলিখিত গন্তব্যগুলি ব্যর্থ হয়েছে: '; +$PHPMAILER_LANG['signing'] = 'স্বাক্ষর করতে ব্যর্থ হয়েছে: '; +$PHPMAILER_LANG['smtp_code'] = 'SMTP কোড: '; +$PHPMAILER_LANG['smtp_code_ex'] = 'অতিরিক্ত SMTP তথ্য:'; +$PHPMAILER_LANG['smtp_detail'] = 'বর্ণনা: '; +$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP সংযোগ() ব্যর্থ হয়েছে৷'; +$PHPMAILER_LANG['smtp_error'] = 'SMTP সার্ভার ত্রুটি: '; +$PHPMAILER_LANG['variable_set'] = 'পরিবর্তনশীল সেট করা যায়নি: '; +$PHPMAILER_LANG['extension_missing'] = 'অনুপস্থিত এক্সটেনশন: '; diff --git a/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-ch.php b/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-ch.php deleted file mode 100644 index 500c9526..00000000 --- a/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-ch.php +++ /dev/null @@ -1,27 +0,0 @@ - - */ - -$PHPMAILER_LANG['authenticate'] = 'SMTP 错误:身份验证失败。'; -$PHPMAILER_LANG['connect_host'] = 'SMTP 错误: 不能连接SMTP主机。'; -$PHPMAILER_LANG['data_not_accepted'] = 'SMTP 错误: 数据不可接受。'; -//$PHPMAILER_LANG['empty_message'] = 'Message body empty'; -$PHPMAILER_LANG['encoding'] = '未知编码:'; -$PHPMAILER_LANG['execute'] = '不能执行: '; -$PHPMAILER_LANG['file_access'] = '不能访问文件:'; -$PHPMAILER_LANG['file_open'] = '文件错误:不能打开文件:'; -$PHPMAILER_LANG['from_failed'] = '下面的发送地址邮件发送失败了: '; -$PHPMAILER_LANG['instantiate'] = '不能实现mail方法。'; -//$PHPMAILER_LANG['invalid_address'] = 'Invalid address: '; -$PHPMAILER_LANG['mailer_not_supported'] = ' 您所选择的发送邮件的方法并不支持。'; -$PHPMAILER_LANG['provide_address'] = '您必须提供至少一个 收信人的email地址。'; -$PHPMAILER_LANG['recipients_failed'] = 'SMTP 错误: 下面的 收件人失败了: '; -//$PHPMAILER_LANG['signing'] = 'Signing Error: '; -//$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() failed.'; -//$PHPMAILER_LANG['smtp_error'] = 'SMTP server error: '; -//$PHPMAILER_LANG['variable_set'] = 'Cannot set or reset variable: '; -//$PHPMAILER_LANG['extension_missing'] = 'Extension missing: '; diff --git a/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-da.php b/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-da.php index 1edba1d7..db9a1ef5 100644 --- a/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-da.php +++ b/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-da.php @@ -9,21 +9,28 @@ */ $PHPMAILER_LANG['authenticate'] = 'SMTP fejl: Login mislykkedes.'; +$PHPMAILER_LANG['buggy_php'] = 'Din version af PHP er berørt af en fejl, som gør at dine beskeder muligvis vises forkert. For at rette dette kan du skifte til SMTP, slå mail.add_x_header headeren i din php.ini fil fra, skifte til MacOS eller Linux eller opgradere din version af PHP til 7.0.17+ eller 7.1.3+.'; $PHPMAILER_LANG['connect_host'] = 'SMTP fejl: Forbindelse til SMTP serveren kunne ikke oprettes.'; $PHPMAILER_LANG['data_not_accepted'] = 'SMTP fejl: Data blev ikke accepteret.'; $PHPMAILER_LANG['empty_message'] = 'Meddelelsen er uden indhold'; $PHPMAILER_LANG['encoding'] = 'Ukendt encode-format: '; $PHPMAILER_LANG['execute'] = 'Kunne ikke afvikle: '; +$PHPMAILER_LANG['extension_missing'] = 'Udvidelse mangler: '; $PHPMAILER_LANG['file_access'] = 'Kunne ikke tilgå filen: '; $PHPMAILER_LANG['file_open'] = 'Fil fejl: Kunne ikke åbne filen: '; $PHPMAILER_LANG['from_failed'] = 'Følgende afsenderadresse er forkert: '; $PHPMAILER_LANG['instantiate'] = 'Email funktionen kunne ikke initialiseres.'; $PHPMAILER_LANG['invalid_address'] = 'Udgyldig adresse: '; +$PHPMAILER_LANG['invalid_header'] = 'Ugyldig header navn eller værdi'; +$PHPMAILER_LANG['invalid_hostentry'] = 'Ugyldig hostentry: '; +$PHPMAILER_LANG['invalid_host'] = 'Ugyldig vært: '; $PHPMAILER_LANG['mailer_not_supported'] = ' mailer understøttes ikke.'; $PHPMAILER_LANG['provide_address'] = 'Indtast mindst en modtagers email adresse.'; -$PHPMAILER_LANG['recipients_failed'] = 'SMTP fejl: Følgende modtagere er forkerte: '; +$PHPMAILER_LANG['recipients_failed'] = 'SMTP fejl: Følgende modtagere fejlede: '; $PHPMAILER_LANG['signing'] = 'Signeringsfejl: '; +$PHPMAILER_LANG['smtp_code'] = 'SMTP kode: '; +$PHPMAILER_LANG['smtp_code_ex'] = 'Yderligere SMTP info: '; $PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() fejlede.'; +$PHPMAILER_LANG['smtp_detail'] = 'Detalje: '; $PHPMAILER_LANG['smtp_error'] = 'SMTP server fejl: '; $PHPMAILER_LANG['variable_set'] = 'Kunne ikke definere eller nulstille variablen: '; -$PHPMAILER_LANG['extension_missing'] = 'Udvidelse mangler: '; diff --git a/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-el.php b/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-el.php index b3d5ca94..339ee575 100644 --- a/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-el.php +++ b/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-el.php @@ -5,22 +5,29 @@ * @package PHPMailer */ -$PHPMAILER_LANG['authenticate'] = 'SMTP Σφάλμα: Αδυναμία πιστοποίησης (authentication).'; -$PHPMAILER_LANG['connect_host'] = 'SMTP Σφάλμα: Αδυναμία σύνδεσης στον SMTP-Host.'; -$PHPMAILER_LANG['data_not_accepted'] = 'SMTP Σφάλμα: Τα δεδομένα δεν έγιναν αποδεκτά.'; -$PHPMAILER_LANG['empty_message'] = 'Το E-Mail δεν έχει περιεχόμενο .'; -$PHPMAILER_LANG['encoding'] = 'Αγνωστο Encoding-Format: '; -$PHPMAILER_LANG['execute'] = 'Αδυναμία εκτέλεσης ακόλουθης εντολής: '; -$PHPMAILER_LANG['file_access'] = 'Αδυναμία προσπέλασης του αρχείου: '; -$PHPMAILER_LANG['file_open'] = 'Σφάλμα Αρχείου: Δεν είναι δυνατό το άνοιγμα του ακόλουθου αρχείου: '; -$PHPMAILER_LANG['from_failed'] = 'Η παρακάτω διεύθυνση αποστολέα δεν είναι σωστή: '; -$PHPMAILER_LANG['instantiate'] = 'Αδυναμία εκκίνησης Mail function.'; -$PHPMAILER_LANG['invalid_address'] = 'Το μήνυμα δεν εστάλη, η διεύθυνση δεν είναι έγκυρη: '; +$PHPMAILER_LANG['authenticate'] = 'Σφάλμα SMTP: Αδυναμία πιστοποίησης.'; +$PHPMAILER_LANG['buggy_php'] = 'Η έκδοση PHP που χρησιμοποιείτε παρουσιάζει σφάλμα που μπορεί να έχει ως αποτέλεσμα κατεστραμένα μηνύματα. Για να το διορθώσετε, αλλάξτε τον τρόπο αποστολής σε SMTP, απενεργοποιήστε την επιλογή mail.add_x_header στο αρχείο php.ini, αλλάξτε λειτουργικό σε MacOS ή Linux ή αναβαθμίστε την PHP σε έκδοση 7.0.17+ ή 7.1.3+.'; +$PHPMAILER_LANG['connect_host'] = 'Σφάλμα SMTP: Αδυναμία σύνδεσης με τον φιλοξενητή SMTP.'; +$PHPMAILER_LANG['data_not_accepted'] = 'Σφάλμα SMTP: Μη αποδεκτά δεδομένα.'; +$PHPMAILER_LANG['empty_message'] = 'Η ηλεκτρονική επιστολή δεν έχει περιεχόμενο.'; +$PHPMAILER_LANG['encoding'] = 'Άγνωστη μορφή κωδικοποίησης: '; +$PHPMAILER_LANG['execute'] = 'Αδυναμία εκτέλεσης: '; +$PHPMAILER_LANG['extension_missing'] = 'Απουσία επέκτασης: '; +$PHPMAILER_LANG['file_access'] = 'Αδυναμία πρόσβασης στο αρχείο: '; +$PHPMAILER_LANG['file_open'] = 'Σφάλμα Αρχείου: Αδυναμία ανοίγματος αρχείου: '; +$PHPMAILER_LANG['from_failed'] = 'Η ακόλουθη διεύθυνση αποστολέα δεν είναι σωστή: '; +$PHPMAILER_LANG['instantiate'] = 'Αδυναμία εκκίνησης συνάρτησης Mail.'; +$PHPMAILER_LANG['invalid_address'] = 'Μη έγκυρη διεύθυνση: '; +$PHPMAILER_LANG['invalid_header'] = 'Μη έγκυρο όνομα κεφαλίδας ή τιμή'; +$PHPMAILER_LANG['invalid_hostentry'] = 'Μη έγκυρη εισαγωγή φιλοξενητή: '; +$PHPMAILER_LANG['invalid_host'] = 'Μη έγκυρος φιλοξενητής: '; $PHPMAILER_LANG['mailer_not_supported'] = ' mailer δεν υποστηρίζεται.'; -$PHPMAILER_LANG['provide_address'] = 'Παρακαλούμε δώστε τουλάχιστον μια e-mail διεύθυνση παραλήπτη.'; -$PHPMAILER_LANG['recipients_failed'] = 'SMTP Σφάλμα: Οι παρακάτω διευθύνσεις παραλήπτη δεν είναι έγκυρες: '; +$PHPMAILER_LANG['provide_address'] = 'Δώστε τουλάχιστον μια ηλεκτρονική διεύθυνση παραλήπτη.'; +$PHPMAILER_LANG['recipients_failed'] = 'Σφάλμα SMTP: Οι παρακάτω διευθύνσεις παραλήπτη δεν είναι έγκυρες: '; $PHPMAILER_LANG['signing'] = 'Σφάλμα υπογραφής: '; -$PHPMAILER_LANG['smtp_connect_failed'] = 'Αποτυχία σύνδεσης στον SMTP Server.'; -$PHPMAILER_LANG['smtp_error'] = 'Σφάλμα από τον SMTP Server: '; -$PHPMAILER_LANG['variable_set'] = 'Αδυναμία ορισμού ή αρχικοποίησης μεταβλητής: '; -//$PHPMAILER_LANG['extension_missing'] = 'Extension missing: '; +$PHPMAILER_LANG['smtp_code'] = 'Κώδικάς SMTP: '; +$PHPMAILER_LANG['smtp_code_ex'] = 'Πρόσθετες πληροφορίες SMTP: '; +$PHPMAILER_LANG['smtp_connect_failed'] = 'Αποτυχία σύνδεσης SMTP.'; +$PHPMAILER_LANG['smtp_detail'] = 'Λεπτομέρεια: '; +$PHPMAILER_LANG['smtp_error'] = 'Σφάλμα με τον διακομιστή SMTP: '; +$PHPMAILER_LANG['variable_set'] = 'Αδυναμία ορισμού ή επαναφοράς μεταβλητής: '; diff --git a/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-es.php b/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-es.php index 6ba74627..4e74bfb7 100644 --- a/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-es.php +++ b/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-es.php @@ -4,24 +4,33 @@ * Spanish PHPMailer language file: refer to English translation for definitive list * @package PHPMailer * @author Matt Sturdy + * @author Crystopher Glodzienski Cardoso + * @author Daniel Cruz */ $PHPMAILER_LANG['authenticate'] = 'Error SMTP: Imposible autentificar.'; +$PHPMAILER_LANG['buggy_php'] = 'Tu versión de PHP está afectada por un bug que puede resultar en mensajes corruptos. Para arreglarlo, cambia a enviar usando SMTP, deshabilita la opción mail.add_x_header en tu php.ini, cambia a MacOS o Linux, o actualiza tu PHP a la versión 7.0.17+ o 7.1.3+.'; $PHPMAILER_LANG['connect_host'] = 'Error SMTP: Imposible conectar al servidor SMTP.'; $PHPMAILER_LANG['data_not_accepted'] = 'Error SMTP: Datos no aceptados.'; $PHPMAILER_LANG['empty_message'] = 'El cuerpo del mensaje está vacío.'; $PHPMAILER_LANG['encoding'] = 'Codificación desconocida: '; $PHPMAILER_LANG['execute'] = 'Imposible ejecutar: '; +$PHPMAILER_LANG['extension_missing'] = 'Extensión faltante: '; $PHPMAILER_LANG['file_access'] = 'Imposible acceder al archivo: '; $PHPMAILER_LANG['file_open'] = 'Error de Archivo: Imposible abrir el archivo: '; $PHPMAILER_LANG['from_failed'] = 'La(s) siguiente(s) direcciones de remitente fallaron: '; $PHPMAILER_LANG['instantiate'] = 'Imposible crear una instancia de la función Mail.'; $PHPMAILER_LANG['invalid_address'] = 'Imposible enviar: dirección de email inválido: '; +$PHPMAILER_LANG['invalid_header'] = 'Nombre o valor de encabezado no válido'; +$PHPMAILER_LANG['invalid_hostentry'] = 'Hostentry inválido: '; +$PHPMAILER_LANG['invalid_host'] = 'Host inválido: '; $PHPMAILER_LANG['mailer_not_supported'] = ' mailer no está soportado.'; $PHPMAILER_LANG['provide_address'] = 'Debe proporcionar al menos una dirección de email de destino.'; $PHPMAILER_LANG['recipients_failed'] = 'Error SMTP: Los siguientes destinos fallaron: '; $PHPMAILER_LANG['signing'] = 'Error al firmar: '; +$PHPMAILER_LANG['smtp_code'] = 'Código del servidor SMTP: '; +$PHPMAILER_LANG['smtp_code_ex'] = 'Información adicional del servidor SMTP: '; $PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() falló.'; +$PHPMAILER_LANG['smtp_detail'] = 'Detalle: '; $PHPMAILER_LANG['smtp_error'] = 'Error del servidor SMTP: '; $PHPMAILER_LANG['variable_set'] = 'No se pudo configurar la variable: '; -$PHPMAILER_LANG['extension_missing'] = 'Extensión faltante: '; diff --git a/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-fi.php b/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-fi.php index 243c0548..6d1e6373 100644 --- a/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-fi.php +++ b/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-fi.php @@ -20,7 +20,6 @@ $PHPMAILER_LANG['instantiate'] = 'mail-funktion luonti epäonnistui.'; $PHPMAILER_LANG['mailer_not_supported'] = 'postivälitintyyppiä ei tueta.'; $PHPMAILER_LANG['provide_address'] = 'Aseta vähintään yksi vastaanottajan sähköpostiosoite.'; $PHPMAILER_LANG['recipients_failed'] = 'SMTP-virhe: seuraava vastaanottaja osoite on virheellinen.'; -$PHPMAILER_LANG['encoding'] = 'Tuntematon koodaustyyppi: '; //$PHPMAILER_LANG['signing'] = 'Signing Error: '; //$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() failed.'; //$PHPMAILER_LANG['smtp_error'] = 'SMTP server error: '; diff --git a/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-fr.php b/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-fr.php index b57f0ec6..a6d582d8 100644 --- a/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-fr.php +++ b/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-fr.php @@ -6,27 +6,31 @@ * Some French punctuation requires a thin non-breaking space (U+202F) character before it, * for example before a colon or exclamation mark. * There is one of these characters between these quotes: " " - * @see http://unicode.org/udhr/n/notes_fra.html */ -$PHPMAILER_LANG['authenticate'] = 'Erreur SMTP : échec de l\'authentification.'; +$PHPMAILER_LANG['authenticate'] = 'Erreur SMTP : échec de l’authentification.'; +$PHPMAILER_LANG['buggy_php'] = 'Votre version de PHP est affectée par un bug qui peut entraîner des messages corrompus. Pour résoudre ce problème, passez à l’envoi par SMTP, désactivez l’option mail.add_x_header dans le fichier php.ini, passez à MacOS ou Linux, ou passez PHP à la version 7.0.17+ ou 7.1.3+.'; $PHPMAILER_LANG['connect_host'] = 'Erreur SMTP : impossible de se connecter au serveur SMTP.'; $PHPMAILER_LANG['data_not_accepted'] = 'Erreur SMTP : données incorrectes.'; $PHPMAILER_LANG['empty_message'] = 'Corps du message vide.'; $PHPMAILER_LANG['encoding'] = 'Encodage inconnu : '; -$PHPMAILER_LANG['execute'] = 'Impossible de lancer l\'exécution : '; -$PHPMAILER_LANG['file_access'] = 'Impossible d\'accéder au fichier : '; +$PHPMAILER_LANG['execute'] = 'Impossible de lancer l’exécution : '; +$PHPMAILER_LANG['extension_missing'] = 'Extension manquante : '; +$PHPMAILER_LANG['file_access'] = 'Impossible d’accéder au fichier : '; $PHPMAILER_LANG['file_open'] = 'Ouverture du fichier impossible : '; -$PHPMAILER_LANG['from_failed'] = 'L\'adresse d\'expéditeur suivante a échoué : '; -$PHPMAILER_LANG['instantiate'] = 'Impossible d\'instancier la fonction mail.'; -$PHPMAILER_LANG['invalid_address'] = 'L\'adresse courriel n\'est pas valide : '; -$PHPMAILER_LANG['invalid_hostentry'] = 'L\'entrée hôte n\'est pas valide : '; -$PHPMAILER_LANG['invalid_host'] = 'L\'hôte n\'est pas valide : '; +$PHPMAILER_LANG['from_failed'] = 'L’adresse d’expéditeur suivante a échoué : '; +$PHPMAILER_LANG['instantiate'] = 'Impossible d’instancier la fonction mail.'; +$PHPMAILER_LANG['invalid_address'] = 'Adresse courriel non valide : '; +$PHPMAILER_LANG['invalid_header'] = 'Nom ou valeur de l’en-tête non valide'; +$PHPMAILER_LANG['invalid_hostentry'] = 'Entrée d’hôte non valide : '; +$PHPMAILER_LANG['invalid_host'] = 'Hôte non valide : '; $PHPMAILER_LANG['mailer_not_supported'] = ' client de messagerie non supporté.'; $PHPMAILER_LANG['provide_address'] = 'Vous devez fournir au moins une adresse de destinataire.'; -$PHPMAILER_LANG['recipients_failed'] = 'Erreur SMTP : les destinataires suivants sont en erreur : '; +$PHPMAILER_LANG['recipients_failed'] = 'Erreur SMTP : les destinataires suivants ont échoué : '; $PHPMAILER_LANG['signing'] = 'Erreur de signature : '; -$PHPMAILER_LANG['smtp_connect_failed'] = 'Échec de la connexion SMTP.'; +$PHPMAILER_LANG['smtp_code'] = 'Code SMTP : '; +$PHPMAILER_LANG['smtp_code_ex'] = 'Informations supplémentaires SMTP : '; +$PHPMAILER_LANG['smtp_connect_failed'] = 'La fonction SMTP connect() a échoué.'; +$PHPMAILER_LANG['smtp_detail'] = 'Détails : '; $PHPMAILER_LANG['smtp_error'] = 'Erreur du serveur SMTP : '; -$PHPMAILER_LANG['variable_set'] = 'Impossible d\'initialiser ou de réinitialiser une variable : '; -$PHPMAILER_LANG['extension_missing'] = 'Extension manquante : '; +$PHPMAILER_LANG['variable_set'] = 'Impossible d’initialiser ou de réinitialiser une variable : '; diff --git a/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-hi.php b/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-hi.php index d973a359..d2856e05 100644 --- a/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-hi.php +++ b/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-hi.php @@ -4,24 +4,32 @@ * Hindi PHPMailer language file: refer to English translation for definitive list * @package PHPMailer * @author Yash Karanke + * Rewrite and extension of the work by Jayanti Suthar */ $PHPMAILER_LANG['authenticate'] = 'SMTP त्रुटि: प्रामाणिकता की जांच नहीं हो सका। '; +$PHPMAILER_LANG['buggy_php'] = 'PHP का आपका संस्करण एक बग से प्रभावित है जिसके परिणामस्वरूप संदेश दूषित हो सकते हैं. इसे ठीक करने हेतु, भेजने के लिए SMTP का उपयोग करे, अपने php.ini में mail.add_x_header विकल्प को अक्षम करें, MacOS या Linux पर जाए, या अपने PHP संस्करण को 7.0.17+ या 7.1.3+ बदले.'; $PHPMAILER_LANG['connect_host'] = 'SMTP त्रुटि: SMTP सर्वर से कनेक्ट नहीं हो सका। '; $PHPMAILER_LANG['data_not_accepted'] = 'SMTP त्रुटि: डेटा स्वीकार नहीं किया जाता है। '; $PHPMAILER_LANG['empty_message'] = 'संदेश खाली है। '; $PHPMAILER_LANG['encoding'] = 'अज्ञात एन्कोडिंग प्रकार। '; $PHPMAILER_LANG['execute'] = 'आदेश को निष्पादित करने में विफल। '; +$PHPMAILER_LANG['extension_missing'] = 'एक्सटेन्षन गायब है: '; $PHPMAILER_LANG['file_access'] = 'फ़ाइल उपलब्ध नहीं है। '; $PHPMAILER_LANG['file_open'] = 'फ़ाइल त्रुटि: फाइल को खोला नहीं जा सका। '; $PHPMAILER_LANG['from_failed'] = 'प्रेषक का पता गलत है। '; $PHPMAILER_LANG['instantiate'] = 'मेल फ़ंक्शन कॉल नहीं कर सकता है।'; $PHPMAILER_LANG['invalid_address'] = 'पता गलत है। '; +$PHPMAILER_LANG['invalid_header'] = 'अमान्य हेडर नाम या मान'; +$PHPMAILER_LANG['invalid_hostentry'] = 'अमान्य hostentry: '; +$PHPMAILER_LANG['invalid_host'] = 'अमान्य होस्ट: '; $PHPMAILER_LANG['mailer_not_supported'] = 'मेल सर्वर के साथ काम नहीं करता है। '; $PHPMAILER_LANG['provide_address'] = 'आपको कम से कम एक प्राप्तकर्ता का ई-मेल पता प्रदान करना होगा।'; $PHPMAILER_LANG['recipients_failed'] = 'SMTP त्रुटि: निम्न प्राप्तकर्ताओं को पते भेजने में विफल। '; -$PHPMAILER_LANG['signing'] = 'साइनअप त्रुटि:। '; +$PHPMAILER_LANG['signing'] = 'साइनअप त्रुटि: '; +$PHPMAILER_LANG['smtp_code'] = 'SMTP कोड: '; +$PHPMAILER_LANG['smtp_code_ex'] = 'अतिरिक्त SMTP जानकारी: '; $PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP का connect () फ़ंक्शन विफल हुआ। '; +$PHPMAILER_LANG['smtp_detail'] = 'विवरण: '; $PHPMAILER_LANG['smtp_error'] = 'SMTP सर्वर त्रुटि। '; $PHPMAILER_LANG['variable_set'] = 'चर को बना या संशोधित नहीं किया जा सकता। '; -$PHPMAILER_LANG['extension_missing'] = 'एक्सटेन्षन गायब है: '; diff --git a/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-ja.php b/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-ja.php index eee79898..d01869ce 100644 --- a/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-ja.php +++ b/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-ja.php @@ -3,26 +3,35 @@ /** * Japanese PHPMailer language file: refer to English translation for definitive list * @package PHPMailer - * @author Mitsuhiro Yoshida + * @author Mitsuhiro Yoshida * @author Yoshi Sakai + * @author Arisophy + * @author ARAKI Musashi */ $PHPMAILER_LANG['authenticate'] = 'SMTPエラー: 認証できませんでした。'; +$PHPMAILER_LANG['buggy_php'] = 'ご利用のバージョンのPHPには不具合があり、メッセージが破損するおそれがあります。問題の解決は以下のいずれかを行ってください。SMTPでの送信に切り替える。php.iniのmail.add_x_headerをoffにする。MacOSまたはLinuxに切り替える。PHPバージョン7.0.17以降または7.1.3以降にアップグレードする。'; $PHPMAILER_LANG['connect_host'] = 'SMTPエラー: SMTPホストに接続できませんでした。'; $PHPMAILER_LANG['data_not_accepted'] = 'SMTPエラー: データが受け付けられませんでした。'; -//$PHPMAILER_LANG['empty_message'] = 'Message body empty'; +$PHPMAILER_LANG['empty_message'] = 'メール本文が空です。'; $PHPMAILER_LANG['encoding'] = '不明なエンコーディング: '; $PHPMAILER_LANG['execute'] = '実行できませんでした: '; +$PHPMAILER_LANG['extension_missing'] = '拡張機能が見つかりません: '; $PHPMAILER_LANG['file_access'] = 'ファイルにアクセスできません: '; $PHPMAILER_LANG['file_open'] = 'ファイルエラー: ファイルを開けません: '; $PHPMAILER_LANG['from_failed'] = 'Fromアドレスを登録する際にエラーが発生しました: '; $PHPMAILER_LANG['instantiate'] = 'メール関数が正常に動作しませんでした。'; -//$PHPMAILER_LANG['invalid_address'] = 'Invalid address: '; -$PHPMAILER_LANG['provide_address'] = '少なくとも1つメールアドレスを 指定する必要があります。'; +$PHPMAILER_LANG['invalid_address'] = '不正なメールアドレス: '; +$PHPMAILER_LANG['invalid_header'] = '不正なヘッダー名またはその内容'; +$PHPMAILER_LANG['invalid_hostentry'] = '不正なホストエントリー: '; +$PHPMAILER_LANG['invalid_host'] = '不正なホスト: '; $PHPMAILER_LANG['mailer_not_supported'] = ' メーラーがサポートされていません。'; +$PHPMAILER_LANG['provide_address'] = '少なくとも1つメールアドレスを 指定する必要があります。'; $PHPMAILER_LANG['recipients_failed'] = 'SMTPエラー: 次の受信者アドレスに 間違いがあります: '; -//$PHPMAILER_LANG['signing'] = 'Signing Error: '; -//$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() failed.'; -//$PHPMAILER_LANG['smtp_error'] = 'SMTP server error: '; -//$PHPMAILER_LANG['variable_set'] = 'Cannot set or reset variable: '; -//$PHPMAILER_LANG['extension_missing'] = 'Extension missing: '; +$PHPMAILER_LANG['signing'] = '署名エラー: '; +$PHPMAILER_LANG['smtp_code'] = 'SMTPコード: '; +$PHPMAILER_LANG['smtp_code_ex'] = 'SMTP追加情報: '; +$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP接続に失敗しました。'; +$PHPMAILER_LANG['smtp_detail'] = '詳細: '; +$PHPMAILER_LANG['smtp_error'] = 'SMTPサーバーエラー: '; +$PHPMAILER_LANG['variable_set'] = '変数が存在しません: '; diff --git a/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-ku.php b/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-ku.php new file mode 100644 index 00000000..cf3bda69 --- /dev/null +++ b/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-ku.php @@ -0,0 +1,27 @@ + + */ + +$PHPMAILER_LANG['authenticate'] = 'هەڵەی SMTP : نەتوانرا کۆدەکە پشتڕاست بکرێتەوە '; +$PHPMAILER_LANG['connect_host'] = 'هەڵەی SMTP: نەتوانرا پەیوەندی بە سێرڤەرەوە بکات SMTP.'; +$PHPMAILER_LANG['data_not_accepted'] = 'هەڵەی SMTP: ئەو زانیاریانە قبوڵ نەکرا.'; +$PHPMAILER_LANG['empty_message'] = 'پەیامەکە بەتاڵە'; +$PHPMAILER_LANG['encoding'] = 'کۆدکردنی نەزانراو : '; +$PHPMAILER_LANG['execute'] = 'ناتوانرێت جێبەجێ بکرێت: '; +$PHPMAILER_LANG['file_access'] = 'ناتوانرێت دەستت بگات بە فایلەکە: '; +$PHPMAILER_LANG['file_open'] = 'هەڵەی پەڕگە(فایل): ناتوانرێت بکرێتەوە: '; +$PHPMAILER_LANG['from_failed'] = 'هەڵە لە ئاستی ناونیشانی نێرەر: '; +$PHPMAILER_LANG['instantiate'] = 'ناتوانرێت خزمەتگوزاری پۆستە پێشکەش بکرێت.'; +$PHPMAILER_LANG['invalid_address'] = 'نەتوانرا بنێردرێت ، چونکە ناونیشانی ئیمەیڵەکە نادروستە: '; +$PHPMAILER_LANG['mailer_not_supported'] = ' مەیلەر پشتگیری ناکات'; +$PHPMAILER_LANG['provide_address'] = 'دەبێت ناونیشانی ئیمەیڵی لانیکەم یەک وەرگر دابین بکرێت.'; +$PHPMAILER_LANG['recipients_failed'] = ' هەڵەی SMTP: ئەم هەڵانەی خوارەوەشکستی هێنا لە ناردن بۆ هەردووکیان: '; +$PHPMAILER_LANG['signing'] = 'هەڵەی واژۆ: '; +$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect()پەیوەندی شکستی هێنا .'; +$PHPMAILER_LANG['smtp_error'] = 'هەڵەی ئاستی سێرڤەری SMTP: '; +$PHPMAILER_LANG['variable_set'] = 'ناتوانرێت بیگۆڕیت یان دوبارە بینێریتەوە: '; +$PHPMAILER_LANG['extension_missing'] = 'درێژکراوە نەماوە: '; diff --git a/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-mn.php b/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-mn.php new file mode 100644 index 00000000..04d262c7 --- /dev/null +++ b/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-mn.php @@ -0,0 +1,27 @@ + + * @author João Vieira */ -$PHPMAILER_LANG['authenticate'] = 'Erro do SMTP: Não foi possível realizar a autenticação.'; -$PHPMAILER_LANG['connect_host'] = 'Erro do SMTP: Não foi possível realizar ligação com o servidor SMTP.'; -$PHPMAILER_LANG['data_not_accepted'] = 'Erro do SMTP: Os dados foram rejeitados.'; -$PHPMAILER_LANG['empty_message'] = 'A mensagem no e-mail está vazia.'; +$PHPMAILER_LANG['authenticate'] = 'Erro SMTP: Falha na autenticação.'; +$PHPMAILER_LANG['buggy_php'] = 'A sua versão do PHP tem um bug que pode causar mensagens corrompidas. Para resolver, utilize o envio por SMTP, desative a opção mail.add_x_header no ficheiro php.ini, mude para MacOS ou Linux, ou atualize o PHP para a versão 7.0.17+ ou 7.1.3+.'; +$PHPMAILER_LANG['connect_host'] = 'Erro SMTP: Não foi possível ligar ao servidor SMTP.'; +$PHPMAILER_LANG['data_not_accepted'] = 'Erro SMTP: Dados não aceites.'; +$PHPMAILER_LANG['empty_message'] = 'A mensagem de e-mail está vazia.'; $PHPMAILER_LANG['encoding'] = 'Codificação desconhecida: '; $PHPMAILER_LANG['execute'] = 'Não foi possível executar: '; -$PHPMAILER_LANG['file_access'] = 'Não foi possível aceder o ficheiro: '; -$PHPMAILER_LANG['file_open'] = 'Abertura do ficheiro: Não foi possível abrir o ficheiro: '; -$PHPMAILER_LANG['from_failed'] = 'Ocorreram falhas nos endereços dos seguintes remententes: '; -$PHPMAILER_LANG['instantiate'] = 'Não foi possível iniciar uma instância da função mail.'; -$PHPMAILER_LANG['invalid_address'] = 'Não foi enviado nenhum e-mail para o endereço de e-mail inválido: '; -$PHPMAILER_LANG['mailer_not_supported'] = ' mailer não é suportado.'; -$PHPMAILER_LANG['provide_address'] = 'Tem de fornecer pelo menos um endereço como destinatário do e-mail.'; -$PHPMAILER_LANG['recipients_failed'] = 'Erro do SMTP: O endereço do seguinte destinatário falhou: '; -$PHPMAILER_LANG['signing'] = 'Erro ao assinar: '; -$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() falhou.'; -$PHPMAILER_LANG['smtp_error'] = 'Erro de servidor SMTP: '; -$PHPMAILER_LANG['variable_set'] = 'Não foi possível definir ou redefinir a variável: '; $PHPMAILER_LANG['extension_missing'] = 'Extensão em falta: '; +$PHPMAILER_LANG['file_access'] = 'Não foi possível aceder ao ficheiro: '; +$PHPMAILER_LANG['file_open'] = 'Erro ao abrir o ficheiro: '; +$PHPMAILER_LANG['from_failed'] = 'O envio falhou para o seguinte endereço do remetente: '; +$PHPMAILER_LANG['instantiate'] = 'Não foi possível instanciar a função mail.'; +$PHPMAILER_LANG['invalid_address'] = 'Endereço de e-mail inválido: '; +$PHPMAILER_LANG['invalid_header'] = 'Nome ou valor do cabeçalho inválido.'; +$PHPMAILER_LANG['invalid_hostentry'] = 'Entrada de host inválida: '; +$PHPMAILER_LANG['invalid_host'] = 'Host inválido: '; +$PHPMAILER_LANG['mailer_not_supported'] = 'O cliente de e-mail não é suportado.'; +$PHPMAILER_LANG['provide_address'] = 'Deve fornecer pelo menos um endereço de destinatário.'; +$PHPMAILER_LANG['recipients_failed'] = 'Erro SMTP: Falha no envio para os seguintes destinatários: '; +$PHPMAILER_LANG['signing'] = 'Erro ao assinar: '; +$PHPMAILER_LANG['smtp_code'] = 'Código SMTP: '; +$PHPMAILER_LANG['smtp_code_ex'] = 'Informações adicionais SMTP: '; +$PHPMAILER_LANG['smtp_connect_failed'] = 'Falha na função SMTP connect().'; +$PHPMAILER_LANG['smtp_detail'] = 'Detalhes: '; +$PHPMAILER_LANG['smtp_error'] = 'Erro do servidor SMTP: '; +$PHPMAILER_LANG['variable_set'] = 'Não foi possível definir ou redefinir a variável: '; diff --git a/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-pt_br.php b/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-pt_br.php index d8638098..5239865a 100644 --- a/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-pt_br.php +++ b/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-pt_br.php @@ -7,24 +7,32 @@ * @author Lucas Guimarães * @author Phelipe Alves * @author Fabio Beneditto + * @author Geidson Benício Coelho */ $PHPMAILER_LANG['authenticate'] = 'Erro de SMTP: Não foi possível autenticar.'; +$PHPMAILER_LANG['buggy_php'] = 'Sua versão do PHP é afetada por um bug que por resultar em messagens corrompidas. Para corrigir, mude para enviar usando SMTP, desative a opção mail.add_x_header em seu php.ini, mude para MacOS ou Linux, ou atualize seu PHP para versão 7.0.17+ ou 7.1.3+ '; $PHPMAILER_LANG['connect_host'] = 'Erro de SMTP: Não foi possível conectar ao servidor SMTP.'; $PHPMAILER_LANG['data_not_accepted'] = 'Erro de SMTP: Dados rejeitados.'; $PHPMAILER_LANG['empty_message'] = 'Mensagem vazia'; $PHPMAILER_LANG['encoding'] = 'Codificação desconhecida: '; $PHPMAILER_LANG['execute'] = 'Não foi possível executar: '; +$PHPMAILER_LANG['extension_missing'] = 'Extensão não existe: '; $PHPMAILER_LANG['file_access'] = 'Não foi possível acessar o arquivo: '; $PHPMAILER_LANG['file_open'] = 'Erro de Arquivo: Não foi possível abrir o arquivo: '; $PHPMAILER_LANG['from_failed'] = 'Os seguintes remetentes falharam: '; $PHPMAILER_LANG['instantiate'] = 'Não foi possível instanciar a função mail.'; $PHPMAILER_LANG['invalid_address'] = 'Endereço de e-mail inválido: '; +$PHPMAILER_LANG['invalid_header'] = 'Nome ou valor de cabeçalho inválido'; +$PHPMAILER_LANG['invalid_hostentry'] = 'hostentry inválido: '; +$PHPMAILER_LANG['invalid_host'] = 'host inválido: '; $PHPMAILER_LANG['mailer_not_supported'] = ' mailer não é suportado.'; $PHPMAILER_LANG['provide_address'] = 'Você deve informar pelo menos um destinatário.'; $PHPMAILER_LANG['recipients_failed'] = 'Erro de SMTP: Os seguintes destinatários falharam: '; $PHPMAILER_LANG['signing'] = 'Erro de Assinatura: '; $PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() falhou.'; +$PHPMAILER_LANG['smtp_code'] = 'Código do servidor SMTP: '; $PHPMAILER_LANG['smtp_error'] = 'Erro de servidor SMTP: '; +$PHPMAILER_LANG['smtp_code_ex'] = 'Informações adicionais do servidor SMTP: '; +$PHPMAILER_LANG['smtp_detail'] = 'Detalhes do servidor SMTP: '; $PHPMAILER_LANG['variable_set'] = 'Não foi possível definir ou redefinir a variável: '; -$PHPMAILER_LANG['extension_missing'] = 'Extensão não existe: '; diff --git a/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-ro.php b/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-ro.php index 292ec1e4..45bef915 100644 --- a/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-ro.php +++ b/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-ro.php @@ -3,25 +3,31 @@ /** * Romanian PHPMailer language file: refer to English translation for definitive list * @package PHPMailer - * @author Alex Florea */ $PHPMAILER_LANG['authenticate'] = 'Eroare SMTP: Autentificarea a eșuat.'; +$PHPMAILER_LANG['buggy_php'] = 'Versiunea instalată de PHP este afectată de o problemă care poate duce la coruperea mesajelor Pentru a preveni această problemă, folosiți SMTP, dezactivați opțiunea mail.add_x_header din php.ini, folosiți MacOS/Linux sau actualizați versiunea de PHP la 7.0.17+ sau 7.1.3+.'; $PHPMAILER_LANG['connect_host'] = 'Eroare SMTP: Conectarea la serverul SMTP a eșuat.'; $PHPMAILER_LANG['data_not_accepted'] = 'Eroare SMTP: Datele nu au fost acceptate.'; $PHPMAILER_LANG['empty_message'] = 'Mesajul este gol.'; $PHPMAILER_LANG['encoding'] = 'Encodare necunoscută: '; $PHPMAILER_LANG['execute'] = 'Nu se poate executa următoarea comandă: '; +$PHPMAILER_LANG['extension_missing'] = 'Lipsește extensia: '; $PHPMAILER_LANG['file_access'] = 'Nu se poate accesa următorul fișier: '; $PHPMAILER_LANG['file_open'] = 'Eroare fișier: Nu se poate deschide următorul fișier: '; $PHPMAILER_LANG['from_failed'] = 'Următoarele adrese From au dat eroare: '; $PHPMAILER_LANG['instantiate'] = 'Funcția mail nu a putut fi inițializată.'; $PHPMAILER_LANG['invalid_address'] = 'Adresa de email nu este validă: '; +$PHPMAILER_LANG['invalid_header'] = 'Numele sau valoarea header-ului nu este validă: '; +$PHPMAILER_LANG['invalid_hostentry'] = 'Hostentry invalid: '; +$PHPMAILER_LANG['invalid_host'] = 'Host invalid: '; $PHPMAILER_LANG['mailer_not_supported'] = ' mailer nu este suportat.'; $PHPMAILER_LANG['provide_address'] = 'Trebuie să adăugați cel puțin o adresă de email.'; $PHPMAILER_LANG['recipients_failed'] = 'Eroare SMTP: Următoarele adrese de email au eșuat: '; $PHPMAILER_LANG['signing'] = 'A aparut o problemă la semnarea emailului. '; +$PHPMAILER_LANG['smtp_code'] = 'Cod SMTP: '; +$PHPMAILER_LANG['smtp_code_ex'] = 'Informații SMTP adiționale: '; $PHPMAILER_LANG['smtp_connect_failed'] = 'Conectarea la serverul SMTP a eșuat.'; +$PHPMAILER_LANG['smtp_detail'] = 'Detalii SMTP: '; $PHPMAILER_LANG['smtp_error'] = 'Eroare server SMTP: '; $PHPMAILER_LANG['variable_set'] = 'Nu se poate seta/reseta variabila. '; -$PHPMAILER_LANG['extension_missing'] = 'Lipsește extensia: '; diff --git a/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-ru.php b/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-ru.php index 8c8c5e81..8013f37c 100644 --- a/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-ru.php +++ b/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-ru.php @@ -5,24 +5,32 @@ * @package PHPMailer * @author Alexey Chumakov * @author Foster Snowhill + * @author ProjectSoft */ -$PHPMAILER_LANG['authenticate'] = 'Ошибка SMTP: ошибка авторизации.'; +$PHPMAILER_LANG['authenticate'] = 'Ошибка SMTP: не удалось пройти аутентификацию.'; +$PHPMAILER_LANG['buggy_php'] = 'В вашей версии PHP есть ошибка, которая может привести к повреждению сообщений. Чтобы исправить, переключитесь на отправку по SMTP, отключите опцию mail.add_x_header в ваш php.ini, переключитесь на MacOS или Linux или обновите PHP до версии 7.0.17+ или 7.1.3+.'; $PHPMAILER_LANG['connect_host'] = 'Ошибка SMTP: не удается подключиться к SMTP-серверу.'; $PHPMAILER_LANG['data_not_accepted'] = 'Ошибка SMTP: данные не приняты.'; +$PHPMAILER_LANG['empty_message'] = 'Пустое сообщение'; $PHPMAILER_LANG['encoding'] = 'Неизвестная кодировка: '; $PHPMAILER_LANG['execute'] = 'Невозможно выполнить команду: '; +$PHPMAILER_LANG['extension_missing'] = 'Расширение отсутствует: '; $PHPMAILER_LANG['file_access'] = 'Нет доступа к файлу: '; $PHPMAILER_LANG['file_open'] = 'Файловая ошибка: не удаётся открыть файл: '; $PHPMAILER_LANG['from_failed'] = 'Неверный адрес отправителя: '; $PHPMAILER_LANG['instantiate'] = 'Невозможно запустить функцию mail().'; -$PHPMAILER_LANG['provide_address'] = 'Пожалуйста, введите хотя бы один email-адрес получателя.'; -$PHPMAILER_LANG['mailer_not_supported'] = ' — почтовый сервер не поддерживается.'; -$PHPMAILER_LANG['recipients_failed'] = 'Ошибка SMTP: не удалась отправка таким адресатам: '; -$PHPMAILER_LANG['empty_message'] = 'Пустое сообщение'; $PHPMAILER_LANG['invalid_address'] = 'Не отправлено из-за неправильного формата email-адреса: '; +$PHPMAILER_LANG['invalid_header'] = 'Неверное имя или значение заголовка'; +$PHPMAILER_LANG['invalid_hostentry'] = 'Неверная запись хоста: '; +$PHPMAILER_LANG['invalid_host'] = 'Неверный хост: '; +$PHPMAILER_LANG['mailer_not_supported'] = ' — почтовый сервер не поддерживается.'; +$PHPMAILER_LANG['provide_address'] = 'Вы должны указать хотя бы один адрес электронной почты получателя.'; +$PHPMAILER_LANG['recipients_failed'] = 'Ошибка SMTP: Ошибка следующих получателей: '; $PHPMAILER_LANG['signing'] = 'Ошибка подписи: '; -$PHPMAILER_LANG['smtp_connect_failed'] = 'Ошибка соединения с SMTP-сервером'; +$PHPMAILER_LANG['smtp_code'] = 'Код SMTP: '; +$PHPMAILER_LANG['smtp_code_ex'] = 'Дополнительная информация SMTP: '; +$PHPMAILER_LANG['smtp_connect_failed'] = 'Ошибка соединения с SMTP-сервером.'; +$PHPMAILER_LANG['smtp_detail'] = 'Детали: '; $PHPMAILER_LANG['smtp_error'] = 'Ошибка SMTP-сервера: '; $PHPMAILER_LANG['variable_set'] = 'Невозможно установить или сбросить переменную: '; -$PHPMAILER_LANG['extension_missing'] = 'Расширение отсутствует: '; diff --git a/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-si.php b/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-si.php new file mode 100644 index 00000000..dce502aa --- /dev/null +++ b/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-si.php @@ -0,0 +1,34 @@ + + */ + +$PHPMAILER_LANG['authenticate'] = 'SMTP දෝෂය: සත්‍යාපනය අසාර්ථක විය.'; +$PHPMAILER_LANG['buggy_php'] = 'ඔබගේ PHP version එකෙහි පවතින දෝෂයක් නිසා email පණිවිඩ දෝෂ සහගත වීමේ හැකියාවක් ඇත. මෙය විසදීම සදහා SMTP භාවිතා කිරීම, mail.add_x_header INI setting එක අක්‍රීය කිරීම, MacOS හෝ Linux වලට මාරු වීම, හෝ ඔබගේ PHP version එක 7.0.17+ හෝ 7.1.3+ වලට අලුත් කිරීම කරගන්න.'; +$PHPMAILER_LANG['connect_host'] = 'SMTP දෝෂය: සම්බන්ධ වීමට නොහැකි විය.'; +$PHPMAILER_LANG['data_not_accepted'] = 'SMTP දෝෂය: දත්ත පිළිගනු නොලැබේ.'; +$PHPMAILER_LANG['empty_message'] = 'පණිවිඩ අන්තර්ගතය හිස්'; +$PHPMAILER_LANG['encoding'] = 'නොදන්නා කේතනය: '; +$PHPMAILER_LANG['execute'] = 'ක්‍රියාත්මක කළ නොහැකි විය: '; +$PHPMAILER_LANG['extension_missing'] = 'Extension එක නොමැත: '; +$PHPMAILER_LANG['file_access'] = 'File එකට ප්‍රවේශ විය නොහැකි විය: '; +$PHPMAILER_LANG['file_open'] = 'File දෝෂය: File එක විවෘත කළ නොහැක: '; +$PHPMAILER_LANG['from_failed'] = 'පහත From ලිපිනයන් අසාර්ථක විය: '; +$PHPMAILER_LANG['instantiate'] = 'mail function එක ක්‍රියාත්මක කළ නොහැක.'; +$PHPMAILER_LANG['invalid_address'] = 'වලංගු නොවන ලිපිනය: '; +$PHPMAILER_LANG['invalid_header'] = 'වලංගු නොවන header නාමයක් හෝ අගයක්'; +$PHPMAILER_LANG['invalid_hostentry'] = 'වලංගු නොවන hostentry එකක්: '; +$PHPMAILER_LANG['invalid_host'] = 'වලංගු නොවන host එකක්: '; +$PHPMAILER_LANG['mailer_not_supported'] = ' mailer සහාය නොදක්වයි.'; +$PHPMAILER_LANG['provide_address'] = 'ඔබ අවම වශයෙන් එක් ලබන්නෙකුගේ ඊමේල් ලිපිනයක් සැපයිය යුතුය.'; +$PHPMAILER_LANG['recipients_failed'] = 'SMTP දෝෂය: පහත ලබන්නන් අසමත් විය: '; +$PHPMAILER_LANG['signing'] = 'Sign කිරීමේ දෝෂය: '; +$PHPMAILER_LANG['smtp_code'] = 'SMTP කේතය: '; +$PHPMAILER_LANG['smtp_code_ex'] = 'අමතර SMTP තොරතුරු: '; +$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP සම්බන්ධය අසාර්ථක විය.'; +$PHPMAILER_LANG['smtp_detail'] = 'තොරතුරු: '; +$PHPMAILER_LANG['smtp_error'] = 'SMTP දෝෂය: '; +$PHPMAILER_LANG['variable_set'] = 'Variable එක සැකසීමට හෝ නැවත සැකසීමට නොහැක: '; diff --git a/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-sl.php b/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-sl.php index c437a886..3e00c259 100644 --- a/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-sl.php +++ b/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-sl.php @@ -9,23 +9,28 @@ */ $PHPMAILER_LANG['authenticate'] = 'SMTP napaka: Avtentikacija ni uspela.'; +$PHPMAILER_LANG['buggy_php'] = 'Na vašo PHP različico vpliva napaka, ki lahko povzroči poškodovana sporočila. Če želite težavo odpraviti, preklopite na pošiljanje prek SMTP, onemogočite možnost mail.add_x_header v vaši php.ini datoteki, preklopite na MacOS ali Linux, ali nadgradite vašo PHP zaličico na 7.0.17+ ali 7.1.3+.'; $PHPMAILER_LANG['connect_host'] = 'SMTP napaka: Vzpostavljanje povezave s SMTP gostiteljem ni uspelo.'; $PHPMAILER_LANG['data_not_accepted'] = 'SMTP napaka: Strežnik zavrača podatke.'; $PHPMAILER_LANG['empty_message'] = 'E-poštno sporočilo nima vsebine.'; $PHPMAILER_LANG['encoding'] = 'Nepoznan tip kodiranja: '; $PHPMAILER_LANG['execute'] = 'Operacija ni uspela: '; +$PHPMAILER_LANG['extension_missing'] = 'Manjkajoča razširitev: '; $PHPMAILER_LANG['file_access'] = 'Nimam dostopa do datoteke: '; $PHPMAILER_LANG['file_open'] = 'Ne morem odpreti datoteke: '; $PHPMAILER_LANG['from_failed'] = 'Neveljaven e-naslov pošiljatelja: '; $PHPMAILER_LANG['instantiate'] = 'Ne morem inicializirati mail funkcije.'; $PHPMAILER_LANG['invalid_address'] = 'E-poštno sporočilo ni bilo poslano. E-naslov je neveljaven: '; +$PHPMAILER_LANG['invalid_header'] = 'Neveljavno ime ali vrednost glave'; $PHPMAILER_LANG['invalid_hostentry'] = 'Neveljaven vnos gostitelja: '; $PHPMAILER_LANG['invalid_host'] = 'Neveljaven gostitelj: '; $PHPMAILER_LANG['mailer_not_supported'] = ' mailer ni podprt.'; $PHPMAILER_LANG['provide_address'] = 'Prosimo, vnesite vsaj enega naslovnika.'; $PHPMAILER_LANG['recipients_failed'] = 'SMTP napaka: Sledeči naslovniki so neveljavni: '; $PHPMAILER_LANG['signing'] = 'Napaka pri podpisovanju: '; +$PHPMAILER_LANG['smtp_code'] = 'SMTP koda: '; +$PHPMAILER_LANG['smtp_code_ex'] = 'Dodatne informacije o SMTP: '; $PHPMAILER_LANG['smtp_connect_failed'] = 'Ne morem vzpostaviti povezave s SMTP strežnikom.'; +$PHPMAILER_LANG['smtp_detail'] = 'Podrobnosti: '; $PHPMAILER_LANG['smtp_error'] = 'Napaka SMTP strežnika: '; $PHPMAILER_LANG['variable_set'] = 'Ne morem nastaviti oz. ponastaviti spremenljivke: '; -$PHPMAILER_LANG['extension_missing'] = 'Manjkajoča razširitev: '; diff --git a/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-tr.php b/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-tr.php index f938f802..3c45bc1c 100644 --- a/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-tr.php +++ b/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-tr.php @@ -11,21 +11,28 @@ */ $PHPMAILER_LANG['authenticate'] = 'SMTP Hatası: Oturum açılamadı.'; +$PHPMAILER_LANG['buggy_php'] = 'PHP sürümünüz iletilerin bozulmasına neden olabilecek bir hatadan etkileniyor. Bunu düzeltmek için, SMTP kullanarak göndermeye geçin, mail.add_x_header seçeneğini devre dışı bırakın php.ini dosyanızdaki mail.add_x_header seçeneğini devre dışı bırakın, MacOS veya Linux geçin veya PHP sürümünü 7.0.17+ veya 7.1.3+ sürümüne yükseltin,'; $PHPMAILER_LANG['connect_host'] = 'SMTP Hatası: SMTP sunucusuna bağlanılamadı.'; $PHPMAILER_LANG['data_not_accepted'] = 'SMTP Hatası: Veri kabul edilmedi.'; $PHPMAILER_LANG['empty_message'] = 'Mesajın içeriği boş'; $PHPMAILER_LANG['encoding'] = 'Bilinmeyen karakter kodlama: '; $PHPMAILER_LANG['execute'] = 'Çalıştırılamadı: '; +$PHPMAILER_LANG['extension_missing'] = 'Eklenti bulunamadı: '; $PHPMAILER_LANG['file_access'] = 'Dosyaya erişilemedi: '; $PHPMAILER_LANG['file_open'] = 'Dosya Hatası: Dosya açılamadı: '; $PHPMAILER_LANG['from_failed'] = 'Belirtilen adreslere gönderme başarısız: '; $PHPMAILER_LANG['instantiate'] = 'Örnek e-posta fonksiyonu oluşturulamadı.'; $PHPMAILER_LANG['invalid_address'] = 'Geçersiz e-posta adresi: '; +$PHPMAILER_LANG['invalid_header'] = 'Geçersiz başlık adı veya değeri: '; +$PHPMAILER_LANG['invalid_hostentry'] = 'Geçersiz ana bilgisayar girişi: '; +$PHPMAILER_LANG['invalid_host'] = 'Geçersiz ana bilgisayar: '; $PHPMAILER_LANG['mailer_not_supported'] = ' e-posta kütüphanesi desteklenmiyor.'; $PHPMAILER_LANG['provide_address'] = 'En az bir alıcı e-posta adresi belirtmelisiniz.'; $PHPMAILER_LANG['recipients_failed'] = 'SMTP Hatası: Belirtilen alıcılara ulaşılamadı: '; $PHPMAILER_LANG['signing'] = 'İmzalama hatası: '; +$PHPMAILER_LANG['smtp_code'] = 'SMTP kodu: '; +$PHPMAILER_LANG['smtp_code_ex'] = 'ek SMTP bilgileri: '; $PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP connect() fonksiyonu başarısız.'; +$PHPMAILER_LANG['smtp_detail'] = 'SMTP SMTP Detayı: '; $PHPMAILER_LANG['smtp_error'] = 'SMTP sunucu hatası: '; $PHPMAILER_LANG['variable_set'] = 'Değişken ayarlanamadı ya da sıfırlanamadı: '; -$PHPMAILER_LANG['extension_missing'] = 'Eklenti bulunamadı: '; diff --git a/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-ur.php b/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-ur.php new file mode 100644 index 00000000..0b9de0f1 --- /dev/null +++ b/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-ur.php @@ -0,0 +1,30 @@ + + */ + +$PHPMAILER_LANG['authenticate'] = 'SMTP خرابی: تصدیق کرنے سے قاصر۔'; +$PHPMAILER_LANG['connect_host'] = 'SMTP خرابی: سرور سے منسلک ہونے سے قاصر۔'; +$PHPMAILER_LANG['data_not_accepted'] = 'SMTP خرابی: ڈیٹا قبول نہیں کیا گیا۔'; +$PHPMAILER_LANG['empty_message'] = 'پیغام کی باڈی خالی ہے۔'; +$PHPMAILER_LANG['encoding'] = 'نامعلوم انکوڈنگ: '; +$PHPMAILER_LANG['execute'] = 'عمل کرنے کے قابل نہیں '; +$PHPMAILER_LANG['file_access'] = 'فائل تک رسائی سے قاصر:'; +$PHPMAILER_LANG['file_open'] = 'فائل کی خرابی: فائل کو کھولنے سے قاصر:'; +$PHPMAILER_LANG['from_failed'] = 'درج ذیل بھیجنے والے کا پتہ ناکام ہو گیا:'; +$PHPMAILER_LANG['instantiate'] = 'میل فنکشن کی مثال بنانے سے قاصر۔'; +$PHPMAILER_LANG['invalid_address'] = 'بھیجنے سے قاصر: غلط ای میل پتہ:'; +$PHPMAILER_LANG['mailer_not_supported'] = ' میلر تعاون یافتہ نہیں ہے۔'; +$PHPMAILER_LANG['provide_address'] = 'آپ کو کم از کم ایک منزل کا ای میل پتہ فراہم کرنا چاہیے۔'; +$PHPMAILER_LANG['recipients_failed'] = 'SMTP خرابی: درج ذیل پتہ پر نہیں بھیجا جاسکا: '; +$PHPMAILER_LANG['signing'] = 'دستخط کی خرابی: '; +$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP ملنا ناکام ہوا'; +$PHPMAILER_LANG['smtp_error'] = 'SMTP سرور کی خرابی: '; +$PHPMAILER_LANG['variable_set'] = 'متغیر سیٹ نہیں کیا جا سکا: '; +$PHPMAILER_LANG['extension_missing'] = 'ایکٹینشن موجود نہیں ہے۔ '; +$PHPMAILER_LANG['smtp_code'] = 'SMTP سرور کوڈ: '; +$PHPMAILER_LANG['smtp_code_ex'] = 'اضافی SMTP سرور کی معلومات:'; +$PHPMAILER_LANG['invalid_header'] = 'غلط ہیڈر کا نام یا قدر'; diff --git a/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-zh_cn.php b/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-zh_cn.php index 728a4994..03d49116 100644 --- a/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-zh_cn.php +++ b/phpmailer/vendor/phpmailer/phpmailer/language/phpmailer.lang-zh_cn.php @@ -9,11 +9,13 @@ */ $PHPMAILER_LANG['authenticate'] = 'SMTP 错误:登录失败。'; +$PHPMAILER_LANG['buggy_php'] = '您的 PHP 版本存在漏洞,可能会导致消息损坏。为修复此问题,请切换到使用 SMTP 发送,在您的 php.ini 中禁用 mail.add_x_header 选项。切换到 MacOS 或 Linux,或将您的 PHP 升级到 7.0.17+ 或 7.1.3+ 版本。'; $PHPMAILER_LANG['connect_host'] = 'SMTP 错误:无法连接到 SMTP 主机。'; $PHPMAILER_LANG['data_not_accepted'] = 'SMTP 错误:数据不被接受。'; $PHPMAILER_LANG['empty_message'] = '邮件正文为空。'; $PHPMAILER_LANG['encoding'] = '未知编码:'; $PHPMAILER_LANG['execute'] = '无法执行:'; +$PHPMAILER_LANG['extension_missing'] = '缺少扩展名:'; $PHPMAILER_LANG['file_access'] = '无法访问文件:'; $PHPMAILER_LANG['file_open'] = '文件错误:无法打开文件:'; $PHPMAILER_LANG['from_failed'] = '发送地址错误:'; @@ -22,8 +24,13 @@ $PHPMAILER_LANG['invalid_address'] = '发送失败,电子邮箱地址是 $PHPMAILER_LANG['mailer_not_supported'] = '发信客户端不被支持。'; $PHPMAILER_LANG['provide_address'] = '必须提供至少一个收件人地址。'; $PHPMAILER_LANG['recipients_failed'] = 'SMTP 错误:收件人地址错误:'; -$PHPMAILER_LANG['signing'] = '登录失败:'; $PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP服务器连接失败。'; $PHPMAILER_LANG['smtp_error'] = 'SMTP服务器出错:'; $PHPMAILER_LANG['variable_set'] = '无法设置或重置变量:'; -$PHPMAILER_LANG['extension_missing'] = '丢失模块 Extension:'; +$PHPMAILER_LANG['invalid_header'] = '无效的标题名称或值'; +$PHPMAILER_LANG['invalid_hostentry'] = '无效的hostentry: '; +$PHPMAILER_LANG['invalid_host'] = '无效的主机:'; +$PHPMAILER_LANG['signing'] = '签名错误:'; +$PHPMAILER_LANG['smtp_code'] = 'SMTP代码: '; +$PHPMAILER_LANG['smtp_code_ex'] = '附加SMTP信息: '; +$PHPMAILER_LANG['smtp_detail'] = '详情:'; diff --git a/phpmailer/vendor/phpmailer/phpmailer/phpunit.xml.dist b/phpmailer/vendor/phpmailer/phpmailer/phpunit.xml.dist deleted file mode 100644 index c68df965..00000000 --- a/phpmailer/vendor/phpmailer/phpmailer/phpunit.xml.dist +++ /dev/null @@ -1,35 +0,0 @@ - - - - - ./test/ - - - - - - - - languages - pop3 - - - - - ./src - - - - - - - - diff --git a/phpmailer/vendor/phpmailer/phpmailer/src/DSNConfigurator.php b/phpmailer/vendor/phpmailer/phpmailer/src/DSNConfigurator.php new file mode 100644 index 00000000..7058c1f0 --- /dev/null +++ b/phpmailer/vendor/phpmailer/phpmailer/src/DSNConfigurator.php @@ -0,0 +1,245 @@ + + * @author Jim Jagielski (jimjag) + * @author Andy Prevost (codeworxtech) + * @author Brent R. Matzelle (original founder) + * @copyright 2012 - 2023 Marcus Bointon + * @copyright 2010 - 2012 Jim Jagielski + * @copyright 2004 - 2009 Andy Prevost + * @license https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html GNU Lesser General Public License + * @note This program is distributed in the hope that it will be useful - WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + */ + +namespace PHPMailer\PHPMailer; + +/** + * Configure PHPMailer with DSN string. + * + * @see https://en.wikipedia.org/wiki/Data_source_name + * + * @author Oleg Voronkovich + */ +class DSNConfigurator +{ + /** + * Create new PHPMailer instance configured by DSN. + * + * @param string $dsn DSN + * @param bool $exceptions Should we throw external exceptions? + * + * @return PHPMailer + */ + public static function mailer($dsn, $exceptions = null) + { + static $configurator = null; + + if (null === $configurator) { + $configurator = new DSNConfigurator(); + } + + return $configurator->configure(new PHPMailer($exceptions), $dsn); + } + + /** + * Configure PHPMailer instance with DSN string. + * + * @param PHPMailer $mailer PHPMailer instance + * @param string $dsn DSN + * + * @return PHPMailer + */ + public function configure(PHPMailer $mailer, $dsn) + { + $config = $this->parseDSN($dsn); + + $this->applyConfig($mailer, $config); + + return $mailer; + } + + /** + * Parse DSN string. + * + * @param string $dsn DSN + * + * @throws Exception If DSN is malformed + * + * @return array Configuration + */ + private function parseDSN($dsn) + { + $config = $this->parseUrl($dsn); + + if (false === $config || !isset($config['scheme']) || !isset($config['host'])) { + throw new Exception('Malformed DSN'); + } + + if (isset($config['query'])) { + parse_str($config['query'], $config['query']); + } + + return $config; + } + + /** + * Apply configuration to mailer. + * + * @param PHPMailer $mailer PHPMailer instance + * @param array $config Configuration + * + * @throws Exception If scheme is invalid + */ + private function applyConfig(PHPMailer $mailer, $config) + { + switch ($config['scheme']) { + case 'mail': + $mailer->isMail(); + break; + case 'sendmail': + $mailer->isSendmail(); + break; + case 'qmail': + $mailer->isQmail(); + break; + case 'smtp': + case 'smtps': + $mailer->isSMTP(); + $this->configureSMTP($mailer, $config); + break; + default: + throw new Exception( + sprintf( + 'Invalid scheme: "%s". Allowed values: "mail", "sendmail", "qmail", "smtp", "smtps".', + $config['scheme'] + ) + ); + } + + if (isset($config['query'])) { + $this->configureOptions($mailer, $config['query']); + } + } + + /** + * Configure SMTP. + * + * @param PHPMailer $mailer PHPMailer instance + * @param array $config Configuration + */ + private function configureSMTP($mailer, $config) + { + $isSMTPS = 'smtps' === $config['scheme']; + + if ($isSMTPS) { + $mailer->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; + } + + $mailer->Host = $config['host']; + + if (isset($config['port'])) { + $mailer->Port = $config['port']; + } elseif ($isSMTPS) { + $mailer->Port = SMTP::DEFAULT_SECURE_PORT; + } + + $mailer->SMTPAuth = isset($config['user']) || isset($config['pass']); + + if (isset($config['user'])) { + $mailer->Username = $config['user']; + } + + if (isset($config['pass'])) { + $mailer->Password = $config['pass']; + } + } + + /** + * Configure options. + * + * @param PHPMailer $mailer PHPMailer instance + * @param array $options Options + * + * @throws Exception If option is unknown + */ + private function configureOptions(PHPMailer $mailer, $options) + { + $allowedOptions = get_object_vars($mailer); + + unset($allowedOptions['Mailer']); + unset($allowedOptions['SMTPAuth']); + unset($allowedOptions['Username']); + unset($allowedOptions['Password']); + unset($allowedOptions['Hostname']); + unset($allowedOptions['Port']); + unset($allowedOptions['ErrorInfo']); + + $allowedOptions = \array_keys($allowedOptions); + + foreach ($options as $key => $value) { + if (!in_array($key, $allowedOptions)) { + throw new Exception( + sprintf( + 'Unknown option: "%s". Allowed values: "%s"', + $key, + implode('", "', $allowedOptions) + ) + ); + } + + switch ($key) { + case 'AllowEmpty': + case 'SMTPAutoTLS': + case 'SMTPKeepAlive': + case 'SingleTo': + case 'UseSendmailOptions': + case 'do_verp': + case 'DKIM_copyHeaderFields': + $mailer->$key = (bool) $value; + break; + case 'Priority': + case 'SMTPDebug': + case 'WordWrap': + $mailer->$key = (int) $value; + break; + default: + $mailer->$key = $value; + break; + } + } + } + + /** + * Parse a URL. + * Wrapper for the built-in parse_url function to work around a bug in PHP 5.5. + * + * @param string $url URL + * + * @return array|false + */ + protected function parseUrl($url) + { + if (\PHP_VERSION_ID >= 50600 || false === strpos($url, '?')) { + return parse_url($url); + } + + $chunks = explode('?', $url); + if (is_array($chunks)) { + $result = parse_url($chunks[0]); + if (is_array($result)) { + $result['query'] = $chunks[1]; + } + return $result; + } + + return false; + } +} diff --git a/phpmailer/vendor/phpmailer/phpmailer/src/Exception.php b/phpmailer/vendor/phpmailer/phpmailer/src/Exception.php index a50a8991..09c1a2cf 100644 --- a/phpmailer/vendor/phpmailer/phpmailer/src/Exception.php +++ b/phpmailer/vendor/phpmailer/phpmailer/src/Exception.php @@ -13,7 +13,7 @@ * @copyright 2012 - 2020 Marcus Bointon * @copyright 2010 - 2012 Jim Jagielski * @copyright 2004 - 2009 Andy Prevost - * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License + * @license https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html GNU Lesser General Public License * @note This program is distributed in the hope that it will be useful - WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. @@ -35,6 +35,6 @@ class Exception extends \Exception */ public function errorMessage() { - return '' . htmlspecialchars($this->getMessage()) . "
\n"; + return '' . htmlspecialchars($this->getMessage(), ENT_COMPAT | ENT_HTML401) . "
\n"; } } diff --git a/phpmailer/vendor/phpmailer/phpmailer/src/OAuth.php b/phpmailer/vendor/phpmailer/phpmailer/src/OAuth.php index c93d0be1..a7e95886 100644 --- a/phpmailer/vendor/phpmailer/phpmailer/src/OAuth.php +++ b/phpmailer/vendor/phpmailer/phpmailer/src/OAuth.php @@ -13,7 +13,7 @@ * @copyright 2012 - 2020 Marcus Bointon * @copyright 2010 - 2012 Jim Jagielski * @copyright 2004 - 2009 Andy Prevost - * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License + * @license https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html GNU Lesser General Public License * @note This program is distributed in the hope that it will be useful - WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. @@ -29,11 +29,11 @@ use League\OAuth2\Client\Token\AccessToken; * OAuth - OAuth2 authentication wrapper class. * Uses the oauth2-client package from the League of Extraordinary Packages. * - * @see http://oauth2-client.thephpleague.com + * @see https://oauth2-client.thephpleague.com * * @author Marcus Bointon (Synchro/coolbru) */ -class OAuth +class OAuth implements OAuthTokenProvider { /** * An instance of the League OAuth Client Provider. diff --git a/phpmailer/vendor/phpmailer/phpmailer/src/OAuthTokenProvider.php b/phpmailer/vendor/phpmailer/phpmailer/src/OAuthTokenProvider.php new file mode 100644 index 00000000..cbda1a12 --- /dev/null +++ b/phpmailer/vendor/phpmailer/phpmailer/src/OAuthTokenProvider.php @@ -0,0 +1,44 @@ + + * @author Jim Jagielski (jimjag) + * @author Andy Prevost (codeworxtech) + * @author Brent R. Matzelle (original founder) + * @copyright 2012 - 2020 Marcus Bointon + * @copyright 2010 - 2012 Jim Jagielski + * @copyright 2004 - 2009 Andy Prevost + * @license https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html GNU Lesser General Public License + * @note This program is distributed in the hope that it will be useful - WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + */ + +namespace PHPMailer\PHPMailer; + +/** + * OAuthTokenProvider - OAuth2 token provider interface. + * Provides base64 encoded OAuth2 auth strings for SMTP authentication. + * + * @see OAuth + * @see SMTP::authenticate() + * + * @author Peter Scopes (pdscopes) + * @author Marcus Bointon (Synchro/coolbru) + */ +interface OAuthTokenProvider +{ + /** + * Generate a base64-encoded OAuth token ensuring that the access token has not expired. + * The string to be base 64 encoded should be in the form: + * "user=\001auth=Bearer \001\001" + * + * @return string + */ + public function getOauth64(); +} diff --git a/phpmailer/vendor/phpmailer/phpmailer/src/PHPMailer.php b/phpmailer/vendor/phpmailer/phpmailer/src/PHPMailer.php index eb4b742b..2444bcf3 100644 --- a/phpmailer/vendor/phpmailer/phpmailer/src/PHPMailer.php +++ b/phpmailer/vendor/phpmailer/phpmailer/src/PHPMailer.php @@ -13,7 +13,7 @@ * @copyright 2012 - 2020 Marcus Bointon * @copyright 2010 - 2012 Jim Jagielski * @copyright 2004 - 2009 Andy Prevost - * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License + * @license https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html GNU Lesser General Public License * @note This program is distributed in the hope that it will be useful - WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. @@ -103,14 +103,14 @@ class PHPMailer * * @var string */ - public $From = 'root@localhost'; + public $From = ''; /** * The From name of the message. * * @var string */ - public $FromName = 'Root User'; + public $FromName = ''; /** * The envelope sender of the message. @@ -152,8 +152,7 @@ class PHPMailer * Only supported in simple alt or alt_inline message types * To generate iCal event structures, use classes like EasyPeasyICS or iCalcreator. * - * @see http://sprain.ch/blog/downloads/php-class-easypeasyics-create-ical-files-with-php/ - * @see http://kigkonsult.se/iCalcreator/ + * @see https://kigkonsult.se/iCalcreator/ * * @var string */ @@ -254,7 +253,7 @@ class PHPMailer * You can set your own, but it must be in the format "", * as defined in RFC5322 section 3.6.4 or it will be ignored. * - * @see https://tools.ietf.org/html/rfc5322#section-3.6.4 + * @see https://www.rfc-editor.org/rfc/rfc5322#section-3.6.4 * * @var string */ @@ -350,17 +349,24 @@ class PHPMailer public $Password = ''; /** - * SMTP auth type. - * Options are CRAM-MD5, LOGIN, PLAIN, XOAUTH2, attempted in that order if not specified. + * SMTP authentication type. Options are CRAM-MD5, LOGIN, PLAIN, XOAUTH2. + * If not specified, the first one from that list that the server supports will be selected. * * @var string */ public $AuthType = ''; /** - * An instance of the PHPMailer OAuth class. + * SMTP SMTPXClient command attributes * - * @var OAuth + * @var array + */ + protected $SMTPXClient = []; + + /** + * An implementation of the PHPMailer OAuthTokenProvider interface. + * + * @var OAuthTokenProvider */ protected $oauth; @@ -381,7 +387,7 @@ class PHPMailer * 'DELAY' will notify you if there is an unusual delay in delivery, but the actual * delivery's outcome (success or failure) is not yet decided. * - * @see https://tools.ietf.org/html/rfc3461 See section 4.1 for more information about NOTIFY + * @see https://www.rfc-editor.org/rfc/rfc3461.html#section-4.1 for more information about NOTIFY */ public $dsn = ''; @@ -461,7 +467,7 @@ class PHPMailer * Only applicable when sending via SMTP. * * @see https://en.wikipedia.org/wiki/Variable_envelope_return_path - * @see http://www.postfix.org/VERP_README.html Postfix VERP info + * @see https://www.postfix.org/VERP_README.html Postfix VERP info * * @var bool */ @@ -544,10 +550,10 @@ class PHPMailer * The function that handles the result of the send email action. * It is called out by send() for each email sent. * - * Value can be any php callable: http://www.php.net/is_callable + * Value can be any php callable: https://www.php.net/is_callable * * Parameters: - * bool $result result of the send action + * bool $result result of the send action * array $to email addresses of the recipients * array $cc cc email addresses * array $bcc bcc email addresses @@ -574,6 +580,10 @@ class PHPMailer * May be a callable to inject your own validator, but there are several built-in validators. * The default validator uses PHP's FILTER_VALIDATE_EMAIL filter_var option. * + * If CharSet is UTF8, the validator is left at the default value, + * and you send to addresses that use non-ASCII local parts, then + * PHPMailer automatically changes to the 'eai' validator. + * * @see PHPMailer::validateAddress() * * @var string|callable @@ -653,6 +663,14 @@ class PHPMailer */ protected $ReplyToQueue = []; + /** + * Whether the need for SMTPUTF8 has been detected. Set by + * preSend() if necessary. + * + * @var bool + */ + public $UseSMTPUTF8 = false; + /** * The array of attachments. * @@ -689,7 +707,7 @@ class PHPMailer protected $boundary = []; /** - * The array of available languages. + * The array of available text strings for the current language. * * @var array */ @@ -750,7 +768,7 @@ class PHPMailer * * @var string */ - const VERSION = '6.5.0'; + const VERSION = '6.10.0'; /** * Error severity: message only, continue processing. @@ -795,7 +813,7 @@ class PHPMailer * The maximum line length supported by mail(). * * Background: mail() will sometimes corrupt messages - * with headers headers longer than 65 chars, see #818. + * with headers longer than 65 chars, see #818. * * @var int */ @@ -858,7 +876,7 @@ class PHPMailer private function mailPassthru($to, $subject, $body, $header, $params) { //Check overloading of mail function to avoid double-encoding - if (ini_get('mbstring.func_overload') & 1) { + if ((int)ini_get('mbstring.func_overload') & 1) { $subject = $this->secureHeader($subject); } else { $subject = $this->encodeHeader($this->secureHeader($subject)); @@ -896,7 +914,7 @@ class PHPMailer } //Is this a PSR-3 logger? if ($this->Debugoutput instanceof \Psr\Log\LoggerInterface) { - $this->Debugoutput->debug($str); + $this->Debugoutput->debug(rtrim($str, "\r\n")); return; } @@ -1065,9 +1083,9 @@ class PHPMailer * be modified after calling this function), addition of such addresses is delayed until send(). * Addresses that have been added already return false, but do not throw exceptions. * - * @param string $kind One of 'to', 'cc', 'bcc', or 'ReplyTo' - * @param string $address The email address to send, resp. to reply to - * @param string $name + * @param string $kind One of 'to', 'cc', 'bcc', or 'Reply-To' + * @param string $address The email address + * @param string $name An optional username associated with the address * * @throws Exception * @@ -1075,9 +1093,11 @@ class PHPMailer */ protected function addOrEnqueueAnAddress($kind, $address, $name) { - $address = trim($address); - $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim - $pos = strrpos($address, '@'); + $pos = false; + if ($address !== null) { + $address = trim($address); + $pos = strrpos($address, '@'); + } if (false === $pos) { //At-sign is missing. $error_message = sprintf( @@ -1094,21 +1114,30 @@ class PHPMailer return false; } + if ($name !== null && is_string($name)) { + $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim + } else { + $name = ''; + } $params = [$kind, $address, $name]; //Enqueue addresses with IDN until we know the PHPMailer::$CharSet. - if (static::idnSupported() && $this->has8bitChars(substr($address, ++$pos))) { - if ('Reply-To' !== $kind) { - if (!array_key_exists($address, $this->RecipientsQueue)) { - $this->RecipientsQueue[$address] = $params; + //Domain is assumed to be whatever is after the last @ symbol in the address + if ($this->has8bitChars(substr($address, ++$pos))) { + if (static::idnSupported()) { + if ('Reply-To' !== $kind) { + if (!array_key_exists($address, $this->RecipientsQueue)) { + $this->RecipientsQueue[$address] = $params; + + return true; + } + } elseif (!array_key_exists($address, $this->ReplyToQueue)) { + $this->ReplyToQueue[$address] = $params; return true; } - } elseif (!array_key_exists($address, $this->ReplyToQueue)) { - $this->ReplyToQueue[$address] = $params; - - return true; } - + //We have an 8-bit domain, but we are missing the necessary extensions to support it + //Or we are already sending to this address return false; } @@ -1116,6 +1145,22 @@ class PHPMailer return call_user_func_array([$this, 'addAnAddress'], $params); } + /** + * Set the boundaries to use for delimiting MIME parts. + * If you override this, ensure you set all 3 boundaries to unique values. + * The default boundaries include a "=_" sequence which cannot occur in quoted-printable bodies, + * as suggested by https://www.rfc-editor.org/rfc/rfc2045#section-6.7 + * + * @return void + */ + public function setBoundaries() + { + $this->uniqueid = $this->generateId(); + $this->boundary[1] = 'b1=_' . $this->uniqueid; + $this->boundary[2] = 'b2=_' . $this->uniqueid; + $this->boundary[3] = 'b3=_' . $this->uniqueid; + } + /** * Add an address to one of the recipient arrays or to the ReplyTo array. * Addresses that have been added already return false, but do not throw exceptions. @@ -1130,6 +1175,15 @@ class PHPMailer */ protected function addAnAddress($kind, $address, $name = '') { + if ( + self::$validator === 'php' && + ((bool) preg_match('/[\x80-\xFF]/', $address)) + ) { + //The caller has not altered the validator and is sending to an address + //with UTF-8, so assume that they want UTF-8 support instead of failing + $this->CharSet = self::CHARSET_UTF8; + self::$validator = 'eai'; + } if (!in_array($kind, ['to', 'cc', 'bcc', 'Reply-To'])) { $error_message = sprintf( '%s: %s', @@ -1181,32 +1235,41 @@ class PHPMailer * Uses the imap_rfc822_parse_adrlist function if the IMAP extension is available. * Note that quotes in the name part are removed. * - * @see http://www.andrew.cmu.edu/user/agreen1/testing/mrbs/web/Mail/RFC822.php A more careful implementation + * @see https://www.andrew.cmu.edu/user/agreen1/testing/mrbs/web/Mail/RFC822.php A more careful implementation * * @param string $addrstr The address list string * @param bool $useimap Whether to use the IMAP extension to parse the list + * @param string $charset The charset to use when decoding the address list string. * * @return array */ - public static function parseAddresses($addrstr, $useimap = true) + public static function parseAddresses($addrstr, $useimap = true, $charset = self::CHARSET_ISO88591) { $addresses = []; if ($useimap && function_exists('imap_rfc822_parse_adrlist')) { //Use this built-in parser if it's available $list = imap_rfc822_parse_adrlist($addrstr, ''); + // Clear any potential IMAP errors to get rid of notices being thrown at end of script. + imap_errors(); foreach ($list as $address) { if ( - ('.SYNTAX-ERROR.' !== $address->host) && static::validateAddress( - $address->mailbox . '@' . $address->host - ) + '.SYNTAX-ERROR.' !== $address->host && + static::validateAddress($address->mailbox . '@' . $address->host) ) { //Decode the name part if it's present and encoded if ( property_exists($address, 'personal') && - extension_loaded('mbstring') && - preg_match('/^=\?.*\?=$/', $address->personal) + //Check for a Mbstring constant rather than using extension_loaded, which is sometimes disabled + defined('MB_CASE_UPPER') && + preg_match('/^=\?.*\?=$/s', $address->personal) ) { + $origCharset = mb_internal_encoding(); + mb_internal_encoding($charset); + //Undo any RFC2047-encoded spaces-as-underscores + $address->personal = str_replace('_', '=20', $address->personal); + //Decode the name $address->personal = mb_decode_mimeheader($address->personal); + mb_internal_encoding($origCharset); } $addresses[] = [ @@ -1234,9 +1297,16 @@ class PHPMailer $email = trim(str_replace('>', '', $email)); $name = trim($name); if (static::validateAddress($email)) { + //Check for a Mbstring constant rather than using extension_loaded, which is sometimes disabled //If this name is encoded, decode it - if (preg_match('/^=\?.*\?=$/', $name)) { + if (defined('MB_CASE_UPPER') && preg_match('/^=\?.*\?=$/s', $name)) { + $origCharset = mb_internal_encoding(); + mb_internal_encoding($charset); + //Undo any RFC2047-encoded spaces-as-underscores + $name = str_replace('_', '=20', $name); + //Decode the name $name = mb_decode_mimeheader($name); + mb_internal_encoding($origCharset); } $addresses[] = [ //Remove any surrounding quotes and spaces from the name @@ -1264,7 +1334,7 @@ class PHPMailer */ public function setFrom($address, $name = '', $auto = true) { - $address = trim($address); + $address = trim((string)$address); $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim //Don't validate now addresses with IDN. Will be done in send(). $pos = strrpos($address, '@'); @@ -1316,6 +1386,7 @@ class PHPMailer * * `pcre` Use old PCRE implementation; * * `php` Use PHP built-in FILTER_VALIDATE_EMAIL; * * `html5` Use the pattern given by the HTML5 spec for 'email' type form input elements. + * * `eai` Use a pattern similar to the HTML5 spec for 'email' and to firefox, extended to support EAI (RFC6530). * * `noregex` Don't use a regex: super fast, really dumb. * Alternatively you may pass in a callable to inject your own validator, for example: * @@ -1360,7 +1431,6 @@ class PHPMailer * * IPv6 literals: 'first.last@[IPv6:a1::]' * Not all of these will necessarily work for sending! * - * @see http://squiloople.com/2009/12/20/email-address-validation/ * @copyright 2009-2010 Michael Rushton * Feel free to use and redistribute this code. But please keep this copyright notice. */ @@ -1387,6 +1457,24 @@ class PHPMailer '[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/sD', $address ); + case 'eai': + /* + * This is the pattern used in the HTML5 spec for validation of 'email' type + * form input elements (as above), modified to accept Unicode email addresses. + * This is also more lenient than Firefox' html5 spec, in order to make the regex faster. + * 'eai' is an acronym for Email Address Internationalization. + * This validator is selected automatically if you attempt to use recipient addresses + * that contain Unicode characters in the local part. + * + * @see https://html.spec.whatwg.org/#e-mail-state-(type=email) + * @see https://en.wikipedia.org/wiki/International_email + */ + return (bool) preg_match( + '/^[-\p{L}\p{N}\p{M}.!#$%&\'*+\/=?^_`{|}~]+@[\p{L}\p{N}\p{M}](?:[\p{L}\p{N}\p{M}-]{0,61}' . + '[\p{L}\p{N}\p{M}])?(?:\.[\p{L}\p{N}\p{M}]' . + '(?:[-\p{L}\p{N}\p{M}]{0,61}[\p{L}\p{N}\p{M}])?)*$/usD', + $address + ); case 'php': default: return filter_var($address, FILTER_VALIDATE_EMAIL) !== false; @@ -1436,7 +1524,12 @@ class PHPMailer $errorcode = 0; if (defined('INTL_IDNA_VARIANT_UTS46')) { //Use the current punycode standard (appeared in PHP 7.2) - $punycode = idn_to_ascii($domain, $errorcode, \INTL_IDNA_VARIANT_UTS46); + $punycode = idn_to_ascii( + $domain, + \IDNA_DEFAULT | \IDNA_USE_STD3_RULES | \IDNA_CHECK_BIDI | + \IDNA_CHECK_CONTEXTJ | \IDNA_NONTRANSITIONAL_TO_ASCII, + \INTL_IDNA_VARIANT_UTS46 + ); } elseif (defined('INTL_IDNA_VARIANT_2003')) { //Fall back to this old, deprecated/removed encoding $punycode = idn_to_ascii($domain, $errorcode, \INTL_IDNA_VARIANT_2003); @@ -1508,21 +1601,33 @@ class PHPMailer && ini_get('mail.add_x_header') === '1' && stripos(PHP_OS, 'WIN') === 0 ) { - trigger_error( - 'Your version of PHP is affected by a bug that may result in corrupted messages.' . - ' To fix it, switch to sending using SMTP, disable the mail.add_x_header option in' . - ' your php.ini, switch to MacOS or Linux, or upgrade your PHP to version 7.0.17+ or 7.1.3+.', - E_USER_WARNING - ); + trigger_error($this->lang('buggy_php'), E_USER_WARNING); } try { $this->error_count = 0; //Reset errors $this->mailHeader = ''; + //The code below tries to support full use of Unicode, + //while remaining compatible with legacy SMTP servers to + //the greatest degree possible: If the message uses + //Unicode in the local parts of any addresses, it is sent + //using SMTPUTF8. If not, it it sent using + //punycode-encoded domains and plain SMTP. + if ( + static::CHARSET_UTF8 === strtolower($this->CharSet) && + ($this->anyAddressHasUnicodeLocalPart($this->RecipientsQueue) || + $this->anyAddressHasUnicodeLocalPart(array_keys($this->all_recipients)) || + $this->anyAddressHasUnicodeLocalPart($this->ReplyToQueue) || + $this->addressHasUnicodeLocalPart($this->From)) + ) { + $this->UseSMTPUTF8 = true; + } //Dequeue recipient and Reply-To addresses with IDN foreach (array_merge($this->RecipientsQueue, $this->ReplyToQueue) as $params) { - $params[1] = $this->punyencodeAddress($params[1]); + if (!$this->UseSMTPUTF8) { + $params[1] = $this->punyencodeAddress($params[1]); + } call_user_func_array([$this, 'addAnAddress'], $params); } if (count($this->to) + count($this->cc) + count($this->bcc) < 1) { @@ -1531,17 +1636,21 @@ class PHPMailer //Validate From, Sender, and ConfirmReadingTo addresses foreach (['From', 'Sender', 'ConfirmReadingTo'] as $address_kind) { - $this->$address_kind = trim($this->$address_kind); - if (empty($this->$address_kind)) { + if ($this->{$address_kind} === null) { + $this->{$address_kind} = ''; continue; } - $this->$address_kind = $this->punyencodeAddress($this->$address_kind); - if (!static::validateAddress($this->$address_kind)) { + $this->{$address_kind} = trim($this->{$address_kind}); + if (empty($this->{$address_kind})) { + continue; + } + $this->{$address_kind} = $this->punyencodeAddress($this->{$address_kind}); + if (!static::validateAddress($this->{$address_kind})) { $error_message = sprintf( '%s (%s): %s', $this->lang('invalid_address'), $address_kind, - $this->$address_kind + $this->{$address_kind} ); $this->setError($error_message); $this->edebug($error_message); @@ -1641,17 +1750,17 @@ class PHPMailer default: $sendMethod = $this->Mailer . 'Send'; if (method_exists($this, $sendMethod)) { - return $this->$sendMethod($this->MIMEHeader, $this->MIMEBody); + return $this->{$sendMethod}($this->MIMEHeader, $this->MIMEBody); } return $this->mailSend($this->MIMEHeader, $this->MIMEBody); } } catch (Exception $exc) { - if ($this->Mailer === 'smtp' && $this->SMTPKeepAlive == true) { - $this->smtp->reset(); - } $this->setError($exc->getMessage()); $this->edebug($exc->getMessage()); + if ($this->Mailer === 'smtp' && $this->SMTPKeepAlive == true && $this->smtp->connected()) { + $this->smtp->reset(); + } if ($this->exceptions) { throw $exc; } @@ -1683,11 +1792,13 @@ class PHPMailer //This sets the SMTP envelope sender which gets turned into a return-path header by the receiver //A space after `-f` is optional, but there is a long history of its presence //causing problems, so we don't use one - //Exim docs: http://www.exim.org/exim-html-current/doc/html/spec_html/ch-the_exim_command_line.html - //Sendmail docs: http://www.sendmail.org/~ca/email/man/sendmail.html - //Qmail docs: http://www.qmail.org/man/man8/qmail-inject.html + //Exim docs: https://www.exim.org/exim-html-current/doc/html/spec_html/ch-the_exim_command_line.html + //Sendmail docs: https://www.sendmail.org/~ca/email/man/sendmail.html //Example problem: https://www.drupal.org/node/1057954 - if (empty($this->Sender) && !empty(ini_get('sendmail_from'))) { + + //PHP 5.6 workaround + $sendmail_from_value = ini_get('sendmail_from'); + if (empty($this->Sender) && !empty($sendmail_from_value)) { //PHP config has a sender address we can use $this->Sender = ini_get('sendmail_from'); } @@ -1724,7 +1835,7 @@ class PHPMailer fwrite($mail, $header); fwrite($mail, $body); $result = pclose($mail); - $addrinfo = static::parseAddresses($toAddr); + $addrinfo = static::parseAddresses($toAddr, true, $this->CharSet); $this->doCallback( ($result === 0), [[$addrinfo['address'], $addrinfo['name']]], @@ -1779,7 +1890,13 @@ class PHPMailer */ protected static function isShellSafe($string) { - //Future-proof + //It's not possible to use shell commands safely (which includes the mail() function) without escapeshellarg, + //but some hosting providers disable it, creating a security problem that we don't want to have to deal with, + //so we don't. + if (!function_exists('escapeshellarg') || !function_exists('escapeshellcmd')) { + return false; + } + if ( escapeshellcmd($string) !== $string || !in_array(escapeshellarg($string), ["'$string'", "\"$string\""]) @@ -1814,7 +1931,7 @@ class PHPMailer */ protected static function isPermittedPath($path) { - //Matches scheme definition from https://tools.ietf.org/html/rfc3986#section-3.1 + //Matches scheme definition from https://www.rfc-editor.org/rfc/rfc3986#section-3.1 return !preg_match('#^[a-z][a-z\d+.-]*://#i', $path); } @@ -1830,7 +1947,7 @@ class PHPMailer if (!static::isPermittedPath($path)) { return false; } - $readable = file_exists($path); + $readable = is_file($path); //If not a UNC path (expected to start with \\), check read permission, see #2069 if (strpos($path, '\\\\') !== 0) { $readable = $readable && is_readable($path); @@ -1841,7 +1958,7 @@ class PHPMailer /** * Send mail using the PHP mail() function. * - * @see http://www.php.net/manual/en/book.mail.php + * @see https://www.php.net/manual/en/book.mail.php * * @param string $header The message headers * @param string $body The message body @@ -1858,18 +1975,27 @@ class PHPMailer foreach ($this->to as $toaddr) { $toArr[] = $this->addrFormat($toaddr); } - $to = implode(', ', $toArr); + $to = trim(implode(', ', $toArr)); + + //If there are no To-addresses (e.g. when sending only to BCC-addresses) + //the following should be added to get a correct DKIM-signature. + //Compare with $this->preSend() + if ($to === '') { + $to = 'undisclosed-recipients:;'; + } $params = null; //This sets the SMTP envelope sender which gets turned into a return-path header by the receiver //A space after `-f` is optional, but there is a long history of its presence //causing problems, so we don't use one - //Exim docs: http://www.exim.org/exim-html-current/doc/html/spec_html/ch-the_exim_command_line.html - //Sendmail docs: http://www.sendmail.org/~ca/email/man/sendmail.html - //Qmail docs: http://www.qmail.org/man/man8/qmail-inject.html + //Exim docs: https://www.exim.org/exim-html-current/doc/html/spec_html/ch-the_exim_command_line.html + //Sendmail docs: https://www.sendmail.org/~ca/email/man/sendmail.html //Example problem: https://www.drupal.org/node/1057954 //CVE-2016-10033, CVE-2016-10045: Don't pass -f if characters will be escaped. - if (empty($this->Sender) && !empty(ini_get('sendmail_from'))) { + + //PHP 5.6 workaround + $sendmail_from_value = ini_get('sendmail_from'); + if (empty($this->Sender) && !empty($sendmail_from_value)) { //PHP config has a sender address we can use $this->Sender = ini_get('sendmail_from'); } @@ -1884,7 +2010,7 @@ class PHPMailer if ($this->SingleTo && count($toArr) > 1) { foreach ($toArr as $toAddr) { $result = $this->mailPassthru($toAddr, $this->Subject, $body, $header, $params); - $addrinfo = static::parseAddresses($toAddr); + $addrinfo = static::parseAddresses($toAddr, true, $this->CharSet); $this->doCallback( $result, [[$addrinfo['address'], $addrinfo['name']]], @@ -1938,6 +2064,38 @@ class PHPMailer return $this->smtp; } + /** + * Provide SMTP XCLIENT attributes + * + * @param string $name Attribute name + * @param ?string $value Attribute value + * + * @return bool + */ + public function setSMTPXclientAttribute($name, $value) + { + if (!in_array($name, SMTP::$xclient_allowed_attributes)) { + return false; + } + if (isset($this->SMTPXClient[$name]) && $value === null) { + unset($this->SMTPXClient[$name]); + } elseif ($value !== null) { + $this->SMTPXClient[$name] = $value; + } + + return true; + } + + /** + * Get SMTP XCLIENT attributes + * + * @return array + */ + public function getSMTPXclientAttributes() + { + return $this->SMTPXClient; + } + /** * Send mail via SMTP. * Returns false if there is a bad MAIL FROM, RCPT, or DATA input. @@ -1960,12 +2118,20 @@ class PHPMailer if (!$this->smtpConnect($this->SMTPOptions)) { throw new Exception($this->lang('smtp_connect_failed'), self::STOP_CRITICAL); } + //If we have recipient addresses that need Unicode support, + //but the server doesn't support it, stop here + if ($this->UseSMTPUTF8 && !$this->smtp->getServerExt('SMTPUTF8')) { + throw new Exception($this->lang('no_smtputf8'), self::STOP_CRITICAL); + } //Sender already validated in preSend() if ('' === $this->Sender) { $smtp_from = $this->From; } else { $smtp_from = $this->Sender; } + if (count($this->SMTPXClient)) { + $this->smtp->xclient($this->SMTPXClient); + } if (!$this->smtp->mail($smtp_from)) { $this->setError($this->lang('from_failed') . $smtp_from . ' : ' . implode(',', $this->smtp->getError())); throw new Exception($this->ErrorInfo, self::STOP_CRITICAL); @@ -2058,6 +2224,10 @@ class PHPMailer $this->smtp->setDebugLevel($this->SMTPDebug); $this->smtp->setDebugOutput($this->Debugoutput); $this->smtp->setVerp($this->do_verp); + $this->smtp->setSMTPUTF8($this->UseSMTPUTF8); + if ($this->Host === null) { + $this->Host = 'localhost'; + } $hosts = explode(';', $this->Host); $lastexception = null; @@ -2125,15 +2295,23 @@ class PHPMailer $this->smtp->hello($hello); //Automatically enable TLS encryption if: //* it's not disabled + //* we are not connecting to localhost //* we have openssl extension //* we are not already using SSL //* the server offers STARTTLS - if ($this->SMTPAutoTLS && $sslext && 'ssl' !== $secure && $this->smtp->getServerExt('STARTTLS')) { + if ( + $this->SMTPAutoTLS && + $this->Host !== 'localhost' && + $sslext && + $secure !== 'ssl' && + $this->smtp->getServerExt('STARTTLS') + ) { $tls = true; } if ($tls) { if (!$this->smtp->startTLS()) { - throw new Exception($this->lang('connect_host')); + $message = $this->getSmtpErrorMessage('connect_host'); + throw new Exception($message); } //We must resend EHLO after TLS negotiation $this->smtp->hello($hello); @@ -2164,6 +2342,11 @@ class PHPMailer if ($this->exceptions && null !== $lastexception) { throw $lastexception; } + if ($this->exceptions) { + // no exception was thrown, likely $this->smtp->connect() failed + $message = $this->getSmtpErrorMessage('connect_host'); + throw new Exception($message); + } return false; } @@ -2181,14 +2364,15 @@ class PHPMailer /** * Set the language for error messages. - * Returns false if it cannot load the language file. * The default language is English. * * @param string $langcode ISO 639-1 2-character language code (e.g. French is "fr") - * @param string $lang_path Path to the language file directory, with trailing separator (slash).D + * Optionally, the language code can be enhanced with a 4-character + * script annotation and/or a 2-character country annotation. + * @param string $lang_path Path to the language file directory, with trailing separator (slash) * Do not set this from user input! * - * @return bool + * @return bool Returns true if the requested language was loaded, false otherwise. */ public function setLanguage($langcode = 'en', $lang_path = '') { @@ -2211,44 +2395,78 @@ class PHPMailer //Define full set of translatable strings in English $PHPMAILER_LANG = [ 'authenticate' => 'SMTP Error: Could not authenticate.', + 'buggy_php' => 'Your version of PHP is affected by a bug that may result in corrupted messages.' . + ' To fix it, switch to sending using SMTP, disable the mail.add_x_header option in' . + ' your php.ini, switch to MacOS or Linux, or upgrade your PHP to version 7.0.17+ or 7.1.3+.', 'connect_host' => 'SMTP Error: Could not connect to SMTP host.', 'data_not_accepted' => 'SMTP Error: data not accepted.', 'empty_message' => 'Message body empty', 'encoding' => 'Unknown encoding: ', 'execute' => 'Could not execute: ', + 'extension_missing' => 'Extension missing: ', 'file_access' => 'Could not access file: ', 'file_open' => 'File Error: Could not open file: ', 'from_failed' => 'The following From address failed: ', 'instantiate' => 'Could not instantiate mail function.', 'invalid_address' => 'Invalid address: ', + 'invalid_header' => 'Invalid header name or value', 'invalid_hostentry' => 'Invalid hostentry: ', 'invalid_host' => 'Invalid host: ', 'mailer_not_supported' => ' mailer is not supported.', 'provide_address' => 'You must provide at least one recipient email address.', 'recipients_failed' => 'SMTP Error: The following recipients failed: ', 'signing' => 'Signing Error: ', + 'smtp_code' => 'SMTP code: ', + 'smtp_code_ex' => 'Additional SMTP info: ', 'smtp_connect_failed' => 'SMTP connect() failed.', + 'smtp_detail' => 'Detail: ', 'smtp_error' => 'SMTP server error: ', 'variable_set' => 'Cannot set or reset variable: ', - 'extension_missing' => 'Extension missing: ', + 'no_smtputf8' => 'Server does not support SMTPUTF8 needed to send to Unicode addresses', ]; if (empty($lang_path)) { //Calculate an absolute path so it can work if CWD is not here $lang_path = dirname(__DIR__) . DIRECTORY_SEPARATOR . 'language' . DIRECTORY_SEPARATOR; } + //Validate $langcode - if (!preg_match('/^[a-z]{2}(?:_[a-zA-Z]{2})?$/', $langcode)) { + $foundlang = true; + $langcode = strtolower($langcode); + if ( + !preg_match('/^(?P[a-z]{2})(?P + + +
+

+ {{$title}} - {{$page}} ({{$count}}) + +

+
+ + + + + + + {{foreach $th_users as $k=>$th}} + {{if $k < 2 || $order_users == $th.1 || ($k==4 && !in_array($order_users,[$th_users.2.1, $th_users.3.1, $th_users.5.1])) }} + + {{/if}} + {{/foreach}} + + + + + {{foreach $users as $u}} + + + + + + {{if $order_users == $th_users.2.1}} + + {{/if}} + + {{if $order_users == $th_users.3.1}} + + {{/if}} + + {{if $order_users == $th_users.5.1}} + + {{/if}} + + {{if !in_array($order_users,[$th_users.2.1, $th_users.3.1, $th_users.5.1]) }} + + {{/if}} + + + + + + + + + {{/foreach}} + +
+ + {{if $order_users == $th.1}} + {{if $order_direction_users == "+"}} + ↓ + {{else}} + ↑ + {{/if}} + {{else}} + ↕ + {{/if}} + {{$th.0}} + +
{{$u.name}}{{$u.email}}{{$u.register_date}}{{$u.login_date}} + + + {{if $u.page_flags_raw==0 && $u.account_type_raw > 0}} + + {{/if}} + {{if $u.is_admin}}{{/if}} + {{if $u.account_expired}}{{/if}} + {{$u.lastitem_date}} + +
+ {{$pager nofilter}} +
+
diff --git a/rendertime/rendertime.php b/rendertime/rendertime.php index 731cf003..4523d911 100644 --- a/rendertime/rendertime.php +++ b/rendertime/rendertime.php @@ -7,7 +7,6 @@ * */ -use Friendica\App; use Friendica\Core\Hook; use Friendica\Core\Renderer; use Friendica\DI; @@ -60,7 +59,7 @@ function rendertime_page_end(string &$o) if (DI::userSession()->isSiteAdmin() && (($_GET['mode'] ?? '') != 'minimal') && !DI::mode()->isMobile() && !DI::mode()->isMobile() && !$ignored) { - $o = $o . '
' . DI::l10n()->t("Database: %s/%s, Network: %s, Rendering: %s, Session: %s, I/O: %s, Other: %s, Total: %s", + $o = $o . '
'; //Add css to header - $css_file = __DIR__ . '/view/' . DI::app()->getCurrentTheme() . '.css'; + $css_file = __DIR__ . '/view/' . DI::appHelper()->getCurrentTheme() . '.css'; if (!file_exists($css_file)) { $css_file = __DIR__ . '/view/default.css'; } @@ -105,7 +104,7 @@ function smileybutton_jot_tool(string &$body) DI::page()->registerStylesheet($css_file); //Get the correct image for the theme - $image = 'addon/smileybutton/view/' . DI::app()->getCurrentTheme() . '.png'; + $image = 'addon/smileybutton/view/' . DI::appHelper()->getCurrentTheme() . '.png'; if (!file_exists($image)) { $image = 'addon/smileybutton/view/default.png'; } diff --git a/smilies_adult/smilies_adult.php b/smilies_adult/smilies_adult.php index e8af21e1..4a80168d 100644 --- a/smilies_adult/smilies_adult.php +++ b/smilies_adult/smilies_adult.php @@ -4,12 +4,11 @@ * Description: Smily icons that could or should not be included in core * Version: 1.0 * Author: Mike Macgirvin - * + * * This is a template for how to extend the "smily" code. - * + * */ -use Friendica\App; use Friendica\Core\Hook; use Friendica\DI; diff --git a/startpage/startpage.php b/startpage/startpage.php index e4d80c0c..558af473 100644 --- a/startpage/startpage.php +++ b/startpage/startpage.php @@ -7,7 +7,6 @@ * */ -use Friendica\App; use Friendica\Core\Hook; use Friendica\Core\Renderer; use Friendica\DI; diff --git a/statusnet/library/codebirdsn.php b/statusnet/library/codebirdsn.php index 020c69c4..bffca163 100644 --- a/statusnet/library/codebirdsn.php +++ b/statusnet/library/codebirdsn.php @@ -31,11 +31,10 @@ use Friendica\Core\System; /** * Define constants */ -$constants = explode(' ', 'OBJECT ARRAY JSON'); -foreach ($constants as $i => $id) { - $id = 'CODEBIRD_RETURNFORMAT_' . $id; - defined($id) or define($id, $i); -} +defined('CODEBIRD_RETURNFORMAT_ARRAY') or define('CODEBIRD_RETURNFORMAT_ARRAY', 0); +defined('CODEBIRD_RETURNFORMAT_JSON') or define('CODEBIRD_RETURNFORMAT_JSON', 1); +defined('CODEBIRD_RETURNFORMAT_OBJECT') or define('CODEBIRD_RETURNFORMAT_OBJECT', 2); + $constants = array( 'CURLE_SSL_CERTPROBLEM' => 58, 'CURLE_SSL_CACERT' => 60, @@ -55,6 +54,8 @@ unset($id); * * @package codebird * @subpackage codebird-php + * + * @method object statuses_update(array $postdata) */ class CodebirdSN { @@ -117,7 +118,7 @@ class CodebirdSN * Returns singleton class instance * Always use this method unless you're working with multiple authenticated users at once * - * @return Codebird The instance + * @return CodebirdSN The instance */ public static function getInstance() { @@ -421,6 +422,7 @@ class CodebirdSN } break; case CODEBIRD_RETURNFORMAT_OBJECT: + /** @var object $reply */ $reply->httpstatus = $httpstatus; if ($httpstatus == 200) { self::setBearerToken($reply->access_token); @@ -491,7 +493,7 @@ class CodebirdSN /** * Generates a (hopefully) unique random string * - * @param int optional $length The length of the string to generate + * @param int $length The optional length of the string to generate * * @return string The random string */ @@ -506,9 +508,9 @@ class CodebirdSN /** * Generates an OAuth signature * - * @param string $httpmethod Usually either 'GET' or 'POST' or 'DELETE' - * @param string $method The API method to call - * @param array optional $params The API call parameters, associative + * @param string $httpmethod Usually either 'GET' or 'POST' or 'DELETE' + * @param string $method The API method to call + * @param array $params optional The API call parameters, associative * * @return string Authorization HTTP header */ @@ -762,13 +764,13 @@ class CodebirdSN * @param string $method The API method to call * @param array $params The parameters to send along * - * @return void + * @return string */ protected function _buildMultipart($method, $params) { // well, files will only work in multipart methods if (! $this->_detectMultipart($method)) { - return; + return ''; } // only check specific parameters @@ -783,18 +785,19 @@ class CodebirdSN ); // method might have files? if (! in_array($method, array_keys($possible_files))) { - return; + return ''; } $possible_files = explode(' ', $possible_files[$method]); + $data = ''; + $multipart_border = '--------------------' . $this->_nonce(); $multipart_request = ''; foreach ($params as $key => $value) { // is it an array? if (is_array($value)) { throw new \Exception('Using URL-encoded parameters is not supported for uploading media.'); - continue; } // check for filenames @@ -871,12 +874,12 @@ class CodebirdSN /** * Calls the API using cURL * - * @param string $httpmethod The HTTP method to use for making the request - * @param string $method The API method to call - * @param string $method_template The templated API method to call - * @param array optional $params The parameters to send along - * @param bool optional $multipart Whether to use multipart/form-data - * @param bool optional $app_only_auth Whether to use app-only bearer authentication + * @param string $httpmethod The HTTP method to use for making the request + * @param string $method The API method to call + * @param string $method_template The templated API method to call + * @param array $params optional The parameters to send along + * @param bool $multipart optional Whether to use multipart/form-data + * @param bool $app_only_auth optional Whether to use app-only bearer authentication * * @return mixed The API reply, encoded in the set return_format */ @@ -918,7 +921,7 @@ class CodebirdSN $authorization = 'Authorization: Bearer ' . self::$_oauth_bearer_token; } $request_headers = array(); - if (isset($authorization)) { + if ($authorization !== '') { $request_headers[] = $authorization; $request_headers[] = 'Expect:'; } @@ -959,6 +962,7 @@ class CodebirdSN $httpstatus = curl_getinfo($ch, CURLINFO_HTTP_CODE); $reply = $this->_parseApiReply($method_template, $reply); if ($this->_return_format == CODEBIRD_RETURNFORMAT_OBJECT) { + /** @var object $reply */ $reply->httpstatus = $httpstatus; } elseif ($this->_return_format == CODEBIRD_RETURNFORMAT_ARRAY) { $reply['httpstatus'] = $httpstatus; @@ -972,7 +976,7 @@ class CodebirdSN * @param string $method The method that has been called * @param string $reply The actual reply, JSON-encoded or URL-encoded * - * @return array|object The parsed reply + * @return string|array|object The parsed reply */ protected function _parseApiReply($method, $reply) { diff --git a/statusnet/library/statusnetoauth.php b/statusnet/library/statusnetoauth.php index c9bb0163..da21be58 100644 --- a/statusnet/library/statusnetoauth.php +++ b/statusnet/library/statusnetoauth.php @@ -12,7 +12,7 @@ require_once __DIR__ . DIRECTORY_SEPARATOR . 'twitteroauth.php'; */ class StatusNetOAuth extends TwitterOAuth { - function get_maxlength() + public function get_maxlength() { $config = $this->get($this->host . 'statusnet/config.json'); if (empty($config)) { @@ -21,27 +21,27 @@ class StatusNetOAuth extends TwitterOAuth return $config->site->textlimit; } - function accessTokenURL() + public function accessTokenURL() { return $this->host . 'oauth/access_token'; } - function authenticateURL() + public function authenticateURL() { return $this->host . 'oauth/authenticate'; } - function authorizeURL() + public function authorizeURL() { return $this->host . 'oauth/authorize'; } - function requestTokenURL() + public function requestTokenURL() { return $this->host . 'oauth/request_token'; } - function __construct($apipath, $consumer_key, $consumer_secret, $oauth_token = NULL, $oauth_token_secret = NULL) + public function __construct($apipath, $consumer_key, $consumer_secret, $oauth_token = NULL, $oauth_token_secret = NULL) { parent::__construct($consumer_key, $consumer_secret, $oauth_token, $oauth_token_secret); $this->host = $apipath; @@ -52,14 +52,9 @@ class StatusNetOAuth extends TwitterOAuth * * Copied here from the TwitterOAuth library and complemented by applying the proxy settings of Friendica * - * @param string $method - * @param string $host - * @param string $path - * @param array $parameters - * - * @return array|object API results + * @return array|object|mixed API results */ - function http($url, $method, $postfields = NULL) + public function http($url, $method, $postfields = NULL) { $this->http_info = []; $ci = curl_init(); diff --git a/statusnet/library/twitteroauth.php b/statusnet/library/twitteroauth.php index b33b5f9d..bab66195 100644 --- a/statusnet/library/twitteroauth.php +++ b/statusnet/library/twitteroauth.php @@ -45,11 +45,11 @@ class TwitterOAuth public $http_header; /** * Contains the last HTTP request info - * @var string + * @var array */ public $http_info; - /** @var OAuthToken */ + /** @var OAuthToken|null */ private $token; /** @var OAuthConsumer */ private $consumer; @@ -59,27 +59,27 @@ class TwitterOAuth /** * Set API URLS */ - function accessTokenURL() + public function accessTokenURL() { return 'https://api.twitter.com/oauth/access_token'; } - function authenticateURL() + public function authenticateURL() { return 'https://twitter.com/oauth/authenticate'; } - function authorizeURL() + public function authorizeURL() { return 'https://twitter.com/oauth/authorize'; } - function requestTokenURL() + public function requestTokenURL() { return 'https://api.twitter.com/oauth/request_token'; } - function __construct($consumer_key, $consumer_secret, $oauth_token = null, $oauth_token_secret = null) + public function __construct($consumer_key, $consumer_secret, $oauth_token = null, $oauth_token_secret = null) { $this->sha1_method = new OAuthSignatureMethod_HMAC_SHA1(); $this->consumer = new OAuthConsumer($consumer_key, $consumer_secret); @@ -93,10 +93,10 @@ class TwitterOAuth /** * Get a request_token * - * @param callback $oauth_callback + * @param callable $oauth_callback * @return array */ - function getRequestToken($oauth_callback = null) + public function getRequestToken($oauth_callback = null) { $parameters = []; if (!empty($oauth_callback)) { @@ -112,11 +112,9 @@ class TwitterOAuth /** * Get the authorize URL * - * @param array $token - * @param bool $sign_in_with_tumblr * @return string */ - function getAuthorizeURL($token, $sign_in_with_twitter = TRUE) + public function getAuthorizeURL($token, $sign_in_with_twitter = TRUE) { if (is_array($token)) { $token = $token['oauth_token']; @@ -139,7 +137,7 @@ class TwitterOAuth * "user_id" => "9436992", * "screen_name" => "abraham") */ - function getAccessToken($oauth_verifier = FALSE) + public function getAccessToken($oauth_verifier = FALSE) { $parameters = []; if (!empty($oauth_verifier)) { @@ -164,7 +162,7 @@ class TwitterOAuth * "screen_name" => "abraham", * "x_auth_expires" => "0") */ - function getXAuthToken($username, $password) + public function getXAuthToken($username, $password) { $parameters = []; $parameters['x_auth_username'] = $username; @@ -184,7 +182,7 @@ class TwitterOAuth * @param array $parameters * @return mixed|string */ - function get($url, $parameters = []) + public function get($url, $parameters = []) { $response = $this->oAuthRequest($url, 'GET', $parameters); if ($this->format === 'json' && $this->decode_json) { @@ -201,7 +199,7 @@ class TwitterOAuth * @param array $parameters * @return mixed|string */ - function post($url, $parameters = []) + public function post($url, $parameters = []) { $response = $this->oAuthRequest($url, 'POST', $parameters); if ($this->format === 'json' && $this->decode_json) { @@ -218,7 +216,7 @@ class TwitterOAuth * @param array $parameters * @return mixed|string */ - function delete($url, $parameters = []) + public function delete($url, $parameters = []) { $response = $this->oAuthRequest($url, 'DELETE', $parameters); if ($this->format === 'json' && $this->decode_json) { @@ -236,7 +234,7 @@ class TwitterOAuth * @param array $parameters * @return mixed|string */ - function oAuthRequest($url, $method, $parameters) + public function oAuthRequest($url, $method, $parameters) { if (strrpos($url, 'https://') !== 0 && strrpos($url, 'http://') !== 0) { $url = "{$this->host}{$url}.{$this->format}"; @@ -260,9 +258,9 @@ class TwitterOAuth * @param string $url * @param string $method * @param mixed $postfields - * @return string API results + * @return string|bool|mixed API results */ - function http($url, $method, $postfields = null) + public function http($url, $method, $postfields = null) { $this->http_info = []; $ci = curl_init(); @@ -307,7 +305,7 @@ class TwitterOAuth * @param string $header * @return int */ - function getHeader($ch, $header) + public function getHeader($ch, $header) { $i = strpos($header, ':'); if (!empty($i)) { diff --git a/statusnet/statusnet.php b/statusnet/statusnet.php index f0372852..8663aaea 100644 --- a/statusnet/statusnet.php +++ b/statusnet/statusnet.php @@ -38,10 +38,8 @@ define('STATUSNET_DEFAULT_POLL_INTERVAL', 5); // given in minutes require_once __DIR__ . DIRECTORY_SEPARATOR . 'library' . DIRECTORY_SEPARATOR . 'statusnetoauth.php'; use CodebirdSN\CodebirdSN; -use Friendica\App; use Friendica\Content\Text\Plaintext; use Friendica\Core\Hook; -use Friendica\Core\Logger; use Friendica\Core\Renderer; use Friendica\Core\System; use Friendica\Database\DBA; @@ -59,7 +57,7 @@ function statusnet_install() Hook::register('hook_fork', 'addon/statusnet/statusnet.php', 'statusnet_hook_fork'); Hook::register('post_local', 'addon/statusnet/statusnet.php', 'statusnet_post_local'); Hook::register('jot_networks', 'addon/statusnet/statusnet.php', 'statusnet_jot_nets'); - Logger::notice('installed GNU Social'); + DI::logger()->notice('installed GNU Social'); } function statusnet_jot_nets(array &$jotnets_fields) @@ -296,7 +294,7 @@ function statusnet_hook_fork(array &$b) $post = $b['data']; - if ($post['deleted'] || ($post['created'] !== $post['edited']) || strpos($post['postopts'] ?? '', 'statusnet') === false || ($post['parent'] != $post['id']) || $post['private']) { + if ($post['deleted'] || ($post['created'] !== $post['edited']) || strpos($post['postopts'] ?? '', 'statusnet') === false || ($post['gravity'] != Item::GRAVITY_PARENT) || ($post['private'] == Item::PRIVATE)) { $b['execute'] = false; return; } @@ -336,7 +334,7 @@ function statusnet_post_hook(array &$b) /** * Post to GNU Social */ - if ($b['deleted'] || $b['private'] || ($b['created'] !== $b['edited'])) { + if ($b['deleted'] || ($b['private'] == Item::PRIVATE) || ($b['created'] !== $b['edited'])) { return; } @@ -356,7 +354,7 @@ function statusnet_post_hook(array &$b) return; } - Logger::notice('GNU Socialpost invoked'); + DI::logger()->notice('GNU Socialpost invoked'); DI::pConfig()->load($b['uid'], 'statusnet'); @@ -366,6 +364,8 @@ function statusnet_post_hook(array &$b) $otoken = DI::pConfig()->get($b['uid'], 'statusnet', 'oauthtoken'); $osecret = DI::pConfig()->get($b['uid'], 'statusnet', 'oauthsecret'); + $iscomment = null; + if ($ckey && $csecret && $otoken && $osecret) { $dent = new StatusNetOAuth($api, $ckey, $csecret, $otoken, $osecret); $max_char = $dent->get_maxlength(); // max. length for a dent @@ -406,7 +406,7 @@ function statusnet_post_hook(array &$b) $cb->setToken($otoken, $osecret); $result = $cb->statuses_update($postdata); //$result = $dent->post('statuses/update', $postdata); - Logger::info('statusnet_post send, result: ' . print_r($result, true) . + DI::logger()->info('statusnet_post send, result: ' . print_r($result, true) . "\nmessage: " . $msg . "\nOriginal post: " . print_r($b, true) . "\nPost Data: " . print_r($postdata, true)); if (!empty($result->source)) { @@ -414,9 +414,9 @@ function statusnet_post_hook(array &$b) } if (!empty($result->error)) { - Logger::notice('Send to GNU Social failed: "' . $result->error . '"'); + DI::logger()->notice('Send to GNU Social failed: "' . $result->error . '"'); } elseif ($iscomment) { - Logger::notice('statusnet_post: Update extid ' . $result->id . ' for post id ' . $b['id']); + DI::logger()->notice('statusnet_post: Update extid ' . $result->id . ' for post id ' . $b['id']); Item::update(['extid' => $hostname . '::' . $result->id, 'body' => $result->text], ['id' => $b['id']]); } } @@ -439,11 +439,13 @@ function statusnet_addon_admin_post() $secret = trim($_POST['secret'][$id]); $key = trim($_POST['key'][$id]); //$applicationname = (!empty($_POST['applicationname']) ? Strings::escapeTags(trim($_POST['applicationname'][$id])):''); - if ($sitename != '' && + if ( + $sitename != '' && $apiurl != '' && $secret != '' && $key != '' && - empty($_POST['delete'][$id])) { + empty($_POST['delete'][$id]) + ) { $sites[] = [ 'sitename' => $sitename, diff --git a/tesseract/tesseract.php b/tesseract/tesseract.php index b3e1feb6..a07c690c 100644 --- a/tesseract/tesseract.php +++ b/tesseract/tesseract.php @@ -7,8 +7,8 @@ */ use Friendica\Core\Hook; -use Friendica\Core\Logger; use Friendica\Core\System; +use Friendica\DI; use thiagoalessio\TesseractOCR\TesseractOCR; require_once __DIR__ . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php'; @@ -17,7 +17,7 @@ function tesseract_install() { Hook::register('ocr-detection', __FILE__, 'tesseract_ocr_detection'); - Logger::notice('installed tesseract'); + DI::logger()->notice('installed tesseract'); } function tesseract_ocr_detection(&$media) @@ -26,12 +26,13 @@ function tesseract_ocr_detection(&$media) try { $languages = $ocr->availableLanguages(); if ($languages) { + /** @phpstan-ignore-next-line ignore call of \thiagoalessio\TesseractOCR\Option::lang() */ $ocr->lang(implode('+', $languages)); } $ocr->tempDir(System::getTempPath()); $ocr->imageData($media['img_str'], strlen($media['img_str'])); $media['description'] = $ocr->run(); } catch (\Throwable $th) { - Logger::info('Error calling TesseractOCR', ['message' => $th->getMessage()]); - } + DI::logger()->info('Error calling TesseractOCR', ['message' => $th->getMessage()]); + } } diff --git a/testdrive/testdrive.php b/testdrive/testdrive.php index 55645284..90fb5918 100644 --- a/testdrive/testdrive.php +++ b/testdrive/testdrive.php @@ -6,7 +6,6 @@ * Author: Mike Macgirvin */ -use Friendica\App; use Friendica\Core\Hook; use Friendica\Core\Search; use Friendica\Database\DBA; @@ -27,7 +26,7 @@ function testdrive_install() function testdrive_load_config(ConfigFileManager $loader) { - DI::app()->getConfigCache()->load($loader->loadAddonConfig('testdrive'), \Friendica\Core\Config\ValueObject\Cache::SOURCE_STATIC); + DI::appHelper()->getConfigCache()->load($loader->loadAddonConfig('testdrive'), \Friendica\Core\Config\ValueObject\Cache::SOURCE_STATIC); } function testdrive_globaldir_update(array &$b) diff --git a/tictac/tictac.php b/tictac/tictac.php index 0f9f4fb6..082b58c1 100644 --- a/tictac/tictac.php +++ b/tictac/tictac.php @@ -7,7 +7,6 @@ * Status: unsupported */ -use Friendica\App; use Friendica\Core\Hook; use Friendica\DI; @@ -30,7 +29,12 @@ function tictac_module() {} function tictac_content() { - $o = ''; + $o = ''; + $dimen = 3; + $handicap = 0; + $mefirst = 0; + $yours = ''; + $mine = ''; if($_POST['move']) { $handicap = DI::args()->get(1); @@ -45,9 +49,6 @@ function tictac_content() { $handicap = DI::args()->get(1); $dimen = 3; } - else { - $dimen = 3; - } $o .= '

' . DI::l10n()->t('3D Tic-Tac-Toe') . '


'; @@ -70,6 +71,7 @@ class tictac { private $dimen; private $first_move = true; private $handicap = 0; + private $mefirst; private $yours; private $mine; private $winning_play; @@ -161,10 +163,10 @@ class tictac { ]; - function __construct($dimen,$handicap,$mefirst,$yours,$mine) { - $this->dimen = 3; - $this->handicap = (($handicap) ? 1 : 0); - $this->mefirst = (($mefirst) ? 1 : 0); + function __construct($dimen, $handicap, $mefirst, $yours, $mine) { + $this->dimen = $dimen; + $this->handicap = $handicap ? 1 : 0; + $this->mefirst = $mefirst ? 1 : 0; $this->yours = str_replace('XXX','',$yours); $this->mine = $mine; $this->you = $this->parse_moves('you'); @@ -175,6 +177,7 @@ class tictac { } function play() { + $o = ''; if($this->first_move) { if(rand(0,1) == 1) { @@ -226,6 +229,8 @@ class tictac { } function parse_moves($player) { + $str = ''; + if($player == 'me') $str = $this->mine; if($player == 'you') @@ -629,7 +634,7 @@ function winning_move() { function draw_board() { if(! strlen($this->yours)) $this->yours = 'XXX'; - $o .= "
handicap}/{$this->mefirst}/{$this->dimen}/{$this->yours}/{$this->mine}\" method=\"post\" />"; + $o = "handicap}/{$this->mefirst}/{$this->dimen}/{$this->yours}/{$this->mine}\" method=\"post\" />"; for($x = 0; $x < $this->dimen; $x ++) { $o .= ''; for($y = 0; $y < $this->dimen; $y ++) { diff --git a/tumblr/lang/ar/messages.po b/tumblr/lang/ar/messages.po index 7879231d..48a9e8cb 100644 --- a/tumblr/lang/ar/messages.po +++ b/tumblr/lang/ar/messages.po @@ -8,64 +8,81 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-07-25 13:15+0000\n" -"PO-Revision-Date: 2021-02-20 00:23+0000\n" -"Last-Translator: Farida Khalaf \n" -"Language-Team: Arabic (http://www.transifex.com/Friendica/friendica/language/ar/)\n" +"POT-Creation-Date: 2023-04-29 06:56+0000\n" +"PO-Revision-Date: 2014-06-23 12:58+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Arabic (http://app.transifex.com/Friendica/friendica/language/ar/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: ar\n" "Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n" -#: tumblr.php:40 +#: tumblr.php:243 msgid "Permission denied." msgstr "الطلب مرفوض." -#: tumblr.php:70 tumblr.php:284 +#: tumblr.php:296 msgid "Save Settings" msgstr "Save Settings" -#: tumblr.php:72 +#: tumblr.php:297 msgid "Consumer Key" msgstr "" -#: tumblr.php:73 +#: tumblr.php:298 msgid "Consumer Secret" msgstr "" -#: tumblr.php:178 -msgid "You are now authenticated to tumblr." +#: tumblr.php:299 +msgid "Maximum tags" msgstr "" -#: tumblr.php:179 -msgid "return to the connector page" -msgstr "الرجوع إلى صفحة الموصل" - -#: tumblr.php:195 -msgid "Post to Tumblr" +#: tumblr.php:299 +msgid "" +"Maximum number of tags that a user can follow. Enter 0 to deactivate the " +"feature." msgstr "" -#: tumblr.php:225 tumblr.php:229 -msgid "Tumblr Export" -msgstr "" - -#: tumblr.php:233 -msgid "(Re-)Authenticate your tumblr page" -msgstr "" - -#: tumblr.php:237 -msgid "Enable Tumblr Post Addon" -msgstr "" - -#: tumblr.php:243 -msgid "Post to Tumblr by default" -msgstr "" - -#: tumblr.php:264 +#: tumblr.php:336 msgid "Post to page:" msgstr "" -#: tumblr.php:278 +#: tumblr.php:342 +msgid "(Re-)Authenticate your tumblr page" +msgstr "" + +#: tumblr.php:343 msgid "You are not authenticated to tumblr" msgstr "" + +#: tumblr.php:348 +msgid "Enable Tumblr Post Addon" +msgstr "" + +#: tumblr.php:349 +msgid "Post to Tumblr by default" +msgstr "" + +#: tumblr.php:350 +msgid "Import the remote timeline" +msgstr "" + +#: tumblr.php:351 +msgid "Subscribed tags" +msgstr "" + +#: tumblr.php:351 +#, php-format +msgid "" +"Comma separated list of up to %d tags that will be imported additionally to " +"the timeline" +msgstr "" + +#: tumblr.php:357 +msgid "Tumblr Import/Export" +msgstr "" + +#: tumblr.php:375 +msgid "Post to Tumblr" +msgstr "" diff --git a/tumblr/lang/ar/strings.php b/tumblr/lang/ar/strings.php index ffd3337c..3f7ca4e4 100644 --- a/tumblr/lang/ar/strings.php +++ b/tumblr/lang/ar/strings.php @@ -7,4 +7,3 @@ function string_plural_select_ar($n){ }} $a->strings['Permission denied.'] = 'الطلب مرفوض.'; $a->strings['Save Settings'] = 'Save Settings'; -$a->strings['return to the connector page'] = 'الرجوع إلى صفحة الموصل'; diff --git a/tumblr/lang/cs/messages.po b/tumblr/lang/cs/messages.po index 4e031be6..cb6f91e6 100644 --- a/tumblr/lang/cs/messages.po +++ b/tumblr/lang/cs/messages.po @@ -11,7 +11,7 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-11-21 19:17-0500\n" +"POT-Creation-Date: 2023-04-29 06:56+0000\n" "PO-Revision-Date: 2014-06-23 12:58+0000\n" "Last-Translator: Aditoo, 2018\n" "Language-Team: Czech (http://app.transifex.com/Friendica/friendica/language/cs/)\n" @@ -21,54 +21,71 @@ msgstr "" "Language: cs\n" "Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n <= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;\n" -#: tumblr.php:39 +#: tumblr.php:243 msgid "Permission denied." msgstr "Přístup odmítnut." -#: tumblr.php:69 +#: tumblr.php:296 msgid "Save Settings" msgstr "" -#: tumblr.php:71 +#: tumblr.php:297 msgid "Consumer Key" msgstr "" -#: tumblr.php:72 +#: tumblr.php:298 msgid "Consumer Secret" msgstr "" -#: tumblr.php:177 -msgid "You are now authenticated to tumblr." -msgstr "Nyní jste přihlášen/a k Tumblr." +#: tumblr.php:299 +msgid "Maximum tags" +msgstr "" -#: tumblr.php:178 -msgid "return to the connector page" -msgstr "návrat ke stránce konektor" +#: tumblr.php:299 +msgid "" +"Maximum number of tags that a user can follow. Enter 0 to deactivate the " +"feature." +msgstr "" -#: tumblr.php:194 -msgid "Post to Tumblr" -msgstr "Posílat na Tumblr" - -#: tumblr.php:225 +#: tumblr.php:336 msgid "Post to page:" msgstr "Posílat na stránku:" -#: tumblr.php:231 +#: tumblr.php:342 msgid "(Re-)Authenticate your tumblr page" msgstr "(Znovu) přihlásit k Vaší stránce Tumblr" -#: tumblr.php:232 +#: tumblr.php:343 msgid "You are not authenticated to tumblr" msgstr "Nyní nejste přihlášen/a k Tumblr." -#: tumblr.php:237 +#: tumblr.php:348 msgid "Enable Tumblr Post Addon" msgstr "Povolit doplněk Tumblr Post" -#: tumblr.php:238 +#: tumblr.php:349 msgid "Post to Tumblr by default" msgstr "Ve výchozím stavu posílat příspěvky na Tumblr" -#: tumblr.php:244 -msgid "Tumblr Export" +#: tumblr.php:350 +msgid "Import the remote timeline" msgstr "" + +#: tumblr.php:351 +msgid "Subscribed tags" +msgstr "" + +#: tumblr.php:351 +#, php-format +msgid "" +"Comma separated list of up to %d tags that will be imported additionally to " +"the timeline" +msgstr "" + +#: tumblr.php:357 +msgid "Tumblr Import/Export" +msgstr "" + +#: tumblr.php:375 +msgid "Post to Tumblr" +msgstr "Posílat na Tumblr" diff --git a/tumblr/lang/cs/strings.php b/tumblr/lang/cs/strings.php index 2f5f8115..3135b0b8 100644 --- a/tumblr/lang/cs/strings.php +++ b/tumblr/lang/cs/strings.php @@ -6,11 +6,9 @@ function string_plural_select_cs($n){ if (($n == 1 && $n % 1 == 0)) { return 0; } else if (($n >= 2 && $n <= 4 && $n % 1 == 0)) { return 1; } else if (($n % 1 != 0 )) { return 2; } else { return 3; } }} $a->strings['Permission denied.'] = 'Přístup odmítnut.'; -$a->strings['You are now authenticated to tumblr.'] = 'Nyní jste přihlášen/a k Tumblr.'; -$a->strings['return to the connector page'] = 'návrat ke stránce konektor'; -$a->strings['Post to Tumblr'] = 'Posílat na Tumblr'; $a->strings['Post to page:'] = 'Posílat na stránku:'; $a->strings['(Re-)Authenticate your tumblr page'] = '(Znovu) přihlásit k Vaší stránce Tumblr'; $a->strings['You are not authenticated to tumblr'] = 'Nyní nejste přihlášen/a k Tumblr.'; $a->strings['Enable Tumblr Post Addon'] = 'Povolit doplněk Tumblr Post'; $a->strings['Post to Tumblr by default'] = 'Ve výchozím stavu posílat příspěvky na Tumblr'; +$a->strings['Post to Tumblr'] = 'Posílat na Tumblr'; diff --git a/tumblr/lang/de/messages.po b/tumblr/lang/de/messages.po index 8056174d..c41ba45f 100644 --- a/tumblr/lang/de/messages.po +++ b/tumblr/lang/de/messages.po @@ -4,6 +4,8 @@ # # # Translators: +# Raroun, 2023 +# Raroun, 2023 # Tobias Diekershoff , 2014-2015 # Tobias Diekershoff , 2018,2021 # Ulf Rompe , 2019 @@ -11,9 +13,9 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-11-21 19:17-0500\n" +"POT-Creation-Date: 2023-04-29 06:56+0000\n" "PO-Revision-Date: 2014-06-23 12:58+0000\n" -"Last-Translator: Tobias Diekershoff , 2018,2021\n" +"Last-Translator: Raroun, 2023\n" "Language-Team: German (http://app.transifex.com/Friendica/friendica/language/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -21,54 +23,71 @@ msgstr "" "Language: de\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: tumblr.php:39 +#: tumblr.php:243 msgid "Permission denied." msgstr "Zugriff verweigert." -#: tumblr.php:69 +#: tumblr.php:296 msgid "Save Settings" msgstr "Einstellungen speichern" -#: tumblr.php:71 +#: tumblr.php:297 msgid "Consumer Key" msgstr "Consumer Key" -#: tumblr.php:72 +#: tumblr.php:298 msgid "Consumer Secret" msgstr "Consumer Secret" -#: tumblr.php:177 -msgid "You are now authenticated to tumblr." -msgstr "Du bist nun auf tumblr authentifiziert." +#: tumblr.php:299 +msgid "Maximum tags" +msgstr "Maximale Anzahl an Tags" -#: tumblr.php:178 -msgid "return to the connector page" -msgstr "zurück zur Connector-Seite" +#: tumblr.php:299 +msgid "" +"Maximum number of tags that a user can follow. Enter 0 to deactivate the " +"feature." +msgstr "Maximale Anzahl von Tags, die ein Benutzer verfolgen kann. Geben Sie 0 ein, um die Funktion zu deaktivieren." -#: tumblr.php:194 -msgid "Post to Tumblr" -msgstr "Auf Tumblr veröffentlichen" - -#: tumblr.php:225 +#: tumblr.php:336 msgid "Post to page:" msgstr "Auf tumblr veröffentlichen" -#: tumblr.php:231 +#: tumblr.php:342 msgid "(Re-)Authenticate your tumblr page" msgstr "(Re-)Authentifizierung deiner tumblr-Seite" -#: tumblr.php:232 +#: tumblr.php:343 msgid "You are not authenticated to tumblr" msgstr "Du bist gegenüber tumblr nicht authentifiziert" -#: tumblr.php:237 +#: tumblr.php:348 msgid "Enable Tumblr Post Addon" msgstr "Tumblr-Post-Addon aktivieren" -#: tumblr.php:238 +#: tumblr.php:349 msgid "Post to Tumblr by default" msgstr "Standardmäßig bei Tumblr veröffentlichen" -#: tumblr.php:244 -msgid "Tumblr Export" -msgstr "Tumblr Export" +#: tumblr.php:350 +msgid "Import the remote timeline" +msgstr "Importiere die entfernte Timeline" + +#: tumblr.php:351 +msgid "Subscribed tags" +msgstr "Abonnierte Tags" + +#: tumblr.php:351 +#, php-format +msgid "" +"Comma separated list of up to %d tags that will be imported additionally to " +"the timeline" +msgstr "Durch Kommata getrennte Liste von bis zu %d Tags, die zusätzlich in die Timeline importiert werden sollen" + +#: tumblr.php:357 +msgid "Tumblr Import/Export" +msgstr "Tumblr Import/Export" + +#: tumblr.php:375 +msgid "Post to Tumblr" +msgstr "Auf Tumblr veröffentlichen" diff --git a/tumblr/lang/de/strings.php b/tumblr/lang/de/strings.php index ce43615c..ed9af957 100644 --- a/tumblr/lang/de/strings.php +++ b/tumblr/lang/de/strings.php @@ -9,12 +9,15 @@ $a->strings['Permission denied.'] = 'Zugriff verweigert.'; $a->strings['Save Settings'] = 'Einstellungen speichern'; $a->strings['Consumer Key'] = 'Consumer Key'; $a->strings['Consumer Secret'] = 'Consumer Secret'; -$a->strings['You are now authenticated to tumblr.'] = 'Du bist nun auf tumblr authentifiziert.'; -$a->strings['return to the connector page'] = 'zurück zur Connector-Seite'; -$a->strings['Post to Tumblr'] = 'Auf Tumblr veröffentlichen'; +$a->strings['Maximum tags'] = 'Maximale Anzahl an Tags'; +$a->strings['Maximum number of tags that a user can follow. Enter 0 to deactivate the feature.'] = 'Maximale Anzahl von Tags, die ein Benutzer verfolgen kann. Geben Sie 0 ein, um die Funktion zu deaktivieren.'; $a->strings['Post to page:'] = 'Auf tumblr veröffentlichen'; $a->strings['(Re-)Authenticate your tumblr page'] = '(Re-)Authentifizierung deiner tumblr-Seite'; $a->strings['You are not authenticated to tumblr'] = 'Du bist gegenüber tumblr nicht authentifiziert'; $a->strings['Enable Tumblr Post Addon'] = 'Tumblr-Post-Addon aktivieren'; $a->strings['Post to Tumblr by default'] = 'Standardmäßig bei Tumblr veröffentlichen'; -$a->strings['Tumblr Export'] = 'Tumblr Export'; +$a->strings['Import the remote timeline'] = 'Importiere die entfernte Timeline'; +$a->strings['Subscribed tags'] = 'Abonnierte Tags'; +$a->strings['Comma separated list of up to %d tags that will be imported additionally to the timeline'] = 'Durch Kommata getrennte Liste von bis zu %d Tags, die zusätzlich in die Timeline importiert werden sollen'; +$a->strings['Tumblr Import/Export'] = 'Tumblr Import/Export'; +$a->strings['Post to Tumblr'] = 'Auf Tumblr veröffentlichen'; diff --git a/tumblr/lang/fr/messages.po b/tumblr/lang/fr/messages.po index ef2f0e3c..43dba8e3 100644 --- a/tumblr/lang/fr/messages.po +++ b/tumblr/lang/fr/messages.po @@ -5,7 +5,7 @@ # # Translators: # bob lebonche , 2021 -# Florent C., 2023 +# cracrayol, 2023-2024 # StefOfficiel , 2015 msgid "" msgstr "" @@ -13,7 +13,7 @@ msgstr "" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2023-04-29 06:56+0000\n" "PO-Revision-Date: 2014-06-23 12:58+0000\n" -"Last-Translator: Florent C., 2023\n" +"Last-Translator: cracrayol, 2023-2024\n" "Language-Team: French (http://app.transifex.com/Friendica/friendica/language/fr/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -39,13 +39,13 @@ msgstr "Secret utilisateur" #: tumblr.php:299 msgid "Maximum tags" -msgstr "Tags maximum" +msgstr "Étiquettes maximum" #: tumblr.php:299 msgid "" "Maximum number of tags that a user can follow. Enter 0 to deactivate the " "feature." -msgstr "Nombre maximum de tags qu'un utilisateur peut suivre. Entrez 0 pour désactiver cette fonctionnalité." +msgstr "Nombre maximum d'étiquettes qu'un utilisateur peut suivre. Entrez 0 pour désactiver cette fonctionnalité." #: tumblr.php:336 msgid "Post to page:" @@ -73,14 +73,14 @@ msgstr "Importer le flux distant" #: tumblr.php:351 msgid "Subscribed tags" -msgstr "Tags suivis" +msgstr "Étiquettes suivies" #: tumblr.php:351 #, php-format msgid "" "Comma separated list of up to %d tags that will be imported additionally to " "the timeline" -msgstr "Liste séparée par des virgules contenant jusqu'à %d tags qui seront importés dans le flux" +msgstr "Liste contenant jusqu'à %d étiquettes, séparées par des virgules, qui seront importées dans le flux" #: tumblr.php:357 msgid "Tumblr Import/Export" diff --git a/tumblr/lang/fr/strings.php b/tumblr/lang/fr/strings.php index ece76c74..f23c9c44 100644 --- a/tumblr/lang/fr/strings.php +++ b/tumblr/lang/fr/strings.php @@ -9,15 +9,15 @@ $a->strings['Permission denied.'] = 'Permission refusée.'; $a->strings['Save Settings'] = 'Sauvegarder les paramètres'; $a->strings['Consumer Key'] = 'Clé utilisateur'; $a->strings['Consumer Secret'] = 'Secret utilisateur'; -$a->strings['Maximum tags'] = 'Tags maximum'; -$a->strings['Maximum number of tags that a user can follow. Enter 0 to deactivate the feature.'] = 'Nombre maximum de tags qu\'un utilisateur peut suivre. Entrez 0 pour désactiver cette fonctionnalité.'; +$a->strings['Maximum tags'] = 'Étiquettes maximum'; +$a->strings['Maximum number of tags that a user can follow. Enter 0 to deactivate the feature.'] = 'Nombre maximum d\'étiquettes qu\'un utilisateur peut suivre. Entrez 0 pour désactiver cette fonctionnalité.'; $a->strings['Post to page:'] = 'Publier sur la page :'; $a->strings['(Re-)Authenticate your tumblr page'] = '(re)Authentifiez votre page Tumblr'; $a->strings['You are not authenticated to tumblr'] = 'Vous n\'êtes pas identifié sur Tumblr'; $a->strings['Enable Tumblr Post Addon'] = 'Activez l\'extension de publication Tumblr'; $a->strings['Post to Tumblr by default'] = 'Publier sur Tumblr par défaut'; $a->strings['Import the remote timeline'] = 'Importer le flux distant'; -$a->strings['Subscribed tags'] = 'Tags suivis'; -$a->strings['Comma separated list of up to %d tags that will be imported additionally to the timeline'] = 'Liste séparée par des virgules contenant jusqu\'à %d tags qui seront importés dans le flux'; +$a->strings['Subscribed tags'] = 'Étiquettes suivies'; +$a->strings['Comma separated list of up to %d tags that will be imported additionally to the timeline'] = 'Liste contenant jusqu\'à %d étiquettes, séparées par des virgules, qui seront importées dans le flux'; $a->strings['Tumblr Import/Export'] = 'Import/Export Tumblr'; $a->strings['Post to Tumblr'] = 'Publier vers Tumblr'; diff --git a/tumblr/lang/it/messages.po b/tumblr/lang/it/messages.po index f3d1df55..0f7e2237 100644 --- a/tumblr/lang/it/messages.po +++ b/tumblr/lang/it/messages.po @@ -10,7 +10,7 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-11-21 19:17-0500\n" +"POT-Creation-Date: 2023-04-29 06:56+0000\n" "PO-Revision-Date: 2014-06-23 12:58+0000\n" "Last-Translator: Sylke Vicious , 2021\n" "Language-Team: Italian (http://app.transifex.com/Friendica/friendica/language/it/)\n" @@ -20,54 +20,71 @@ msgstr "" "Language: it\n" "Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" -#: tumblr.php:39 +#: tumblr.php:243 msgid "Permission denied." msgstr "Permesso negato." -#: tumblr.php:69 +#: tumblr.php:296 msgid "Save Settings" msgstr "Salva Impostazioni" -#: tumblr.php:71 +#: tumblr.php:297 msgid "Consumer Key" msgstr "Consumer Key" -#: tumblr.php:72 +#: tumblr.php:298 msgid "Consumer Secret" msgstr "Consumer Secret" -#: tumblr.php:177 -msgid "You are now authenticated to tumblr." -msgstr "Sei autenticato su Tumblr." +#: tumblr.php:299 +msgid "Maximum tags" +msgstr "" -#: tumblr.php:178 -msgid "return to the connector page" -msgstr "ritorna alla pagina del connettore" +#: tumblr.php:299 +msgid "" +"Maximum number of tags that a user can follow. Enter 0 to deactivate the " +"feature." +msgstr "" -#: tumblr.php:194 -msgid "Post to Tumblr" -msgstr "Invia a Tumblr" - -#: tumblr.php:225 +#: tumblr.php:336 msgid "Post to page:" msgstr "Invia alla pagina:" -#: tumblr.php:231 +#: tumblr.php:342 msgid "(Re-)Authenticate your tumblr page" msgstr "(Ri)Autenticati con la tua pagina Tumblr" -#: tumblr.php:232 +#: tumblr.php:343 msgid "You are not authenticated to tumblr" msgstr "Non sei autenticato su Tumblr" -#: tumblr.php:237 +#: tumblr.php:348 msgid "Enable Tumblr Post Addon" msgstr "Abilita componente aggiuntivo di invio a Tumblr" -#: tumblr.php:238 +#: tumblr.php:349 msgid "Post to Tumblr by default" msgstr "Invia sempre a Tumblr" -#: tumblr.php:244 -msgid "Tumblr Export" -msgstr "Esporta Tumblr" +#: tumblr.php:350 +msgid "Import the remote timeline" +msgstr "" + +#: tumblr.php:351 +msgid "Subscribed tags" +msgstr "" + +#: tumblr.php:351 +#, php-format +msgid "" +"Comma separated list of up to %d tags that will be imported additionally to " +"the timeline" +msgstr "" + +#: tumblr.php:357 +msgid "Tumblr Import/Export" +msgstr "" + +#: tumblr.php:375 +msgid "Post to Tumblr" +msgstr "Invia a Tumblr" diff --git a/tumblr/lang/it/strings.php b/tumblr/lang/it/strings.php index d4d4e257..e58ab31c 100644 --- a/tumblr/lang/it/strings.php +++ b/tumblr/lang/it/strings.php @@ -9,12 +9,9 @@ $a->strings['Permission denied.'] = 'Permesso negato.'; $a->strings['Save Settings'] = 'Salva Impostazioni'; $a->strings['Consumer Key'] = 'Consumer Key'; $a->strings['Consumer Secret'] = 'Consumer Secret'; -$a->strings['You are now authenticated to tumblr.'] = 'Sei autenticato su Tumblr.'; -$a->strings['return to the connector page'] = 'ritorna alla pagina del connettore'; -$a->strings['Post to Tumblr'] = 'Invia a Tumblr'; $a->strings['Post to page:'] = 'Invia alla pagina:'; $a->strings['(Re-)Authenticate your tumblr page'] = '(Ri)Autenticati con la tua pagina Tumblr'; $a->strings['You are not authenticated to tumblr'] = 'Non sei autenticato su Tumblr'; $a->strings['Enable Tumblr Post Addon'] = 'Abilita componente aggiuntivo di invio a Tumblr'; $a->strings['Post to Tumblr by default'] = 'Invia sempre a Tumblr'; -$a->strings['Tumblr Export'] = 'Esporta Tumblr'; +$a->strings['Post to Tumblr'] = 'Invia a Tumblr'; diff --git a/tumblr/lang/pl/messages.po b/tumblr/lang/pl/messages.po index 27a44e15..a8676455 100644 --- a/tumblr/lang/pl/messages.po +++ b/tumblr/lang/pl/messages.po @@ -10,64 +10,81 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-11-21 19:17-0500\n" +"POT-Creation-Date: 2023-04-29 06:56+0000\n" "PO-Revision-Date: 2014-06-23 12:58+0000\n" "Last-Translator: Piotr Strębski , 2022\n" -"Language-Team: Polish (http://www.transifex.com/Friendica/friendica/language/pl/)\n" +"Language-Team: Polish (http://app.transifex.com/Friendica/friendica/language/pl/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: pl\n" "Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n" -#: tumblr.php:39 +#: tumblr.php:243 msgid "Permission denied." msgstr "Odmowa dostępu." -#: tumblr.php:69 +#: tumblr.php:296 msgid "Save Settings" msgstr "Zapisz ustawienia" -#: tumblr.php:71 +#: tumblr.php:297 msgid "Consumer Key" msgstr "Klucz klienta" -#: tumblr.php:72 +#: tumblr.php:298 msgid "Consumer Secret" msgstr "Tajny klucz klienta" -#: tumblr.php:177 -msgid "You are now authenticated to tumblr." -msgstr "Jesteś teraz uwierzytelniony na tumblr." +#: tumblr.php:299 +msgid "Maximum tags" +msgstr "" -#: tumblr.php:178 -msgid "return to the connector page" -msgstr "powrót do strony łącza" +#: tumblr.php:299 +msgid "" +"Maximum number of tags that a user can follow. Enter 0 to deactivate the " +"feature." +msgstr "" -#: tumblr.php:194 -msgid "Post to Tumblr" -msgstr "Opublikuj w Tumblr" - -#: tumblr.php:225 +#: tumblr.php:336 msgid "Post to page:" msgstr "Opublikuj na stronie:" -#: tumblr.php:231 +#: tumblr.php:342 msgid "(Re-)Authenticate your tumblr page" msgstr "(Re-) Uwierzytelnij swoją stronę tumblr" -#: tumblr.php:232 +#: tumblr.php:343 msgid "You are not authenticated to tumblr" msgstr "Nie jesteś uwierzytelniony w tumblr" -#: tumblr.php:237 +#: tumblr.php:348 msgid "Enable Tumblr Post Addon" msgstr "Włącz dodatek Tumblr" -#: tumblr.php:238 +#: tumblr.php:349 msgid "Post to Tumblr by default" msgstr "Wyślij domyślnie do Tumblr" -#: tumblr.php:244 -msgid "Tumblr Export" -msgstr "Eksportuj do Tumblr" +#: tumblr.php:350 +msgid "Import the remote timeline" +msgstr "" + +#: tumblr.php:351 +msgid "Subscribed tags" +msgstr "" + +#: tumblr.php:351 +#, php-format +msgid "" +"Comma separated list of up to %d tags that will be imported additionally to " +"the timeline" +msgstr "" + +#: tumblr.php:357 +msgid "Tumblr Import/Export" +msgstr "" + +#: tumblr.php:375 +msgid "Post to Tumblr" +msgstr "Opublikuj w Tumblr" diff --git a/tumblr/lang/pl/strings.php b/tumblr/lang/pl/strings.php index a9f3bfb5..896b21ba 100644 --- a/tumblr/lang/pl/strings.php +++ b/tumblr/lang/pl/strings.php @@ -9,12 +9,9 @@ $a->strings['Permission denied.'] = 'Odmowa dostępu.'; $a->strings['Save Settings'] = 'Zapisz ustawienia'; $a->strings['Consumer Key'] = 'Klucz klienta'; $a->strings['Consumer Secret'] = 'Tajny klucz klienta'; -$a->strings['You are now authenticated to tumblr.'] = 'Jesteś teraz uwierzytelniony na tumblr.'; -$a->strings['return to the connector page'] = 'powrót do strony łącza'; -$a->strings['Post to Tumblr'] = 'Opublikuj w Tumblr'; $a->strings['Post to page:'] = 'Opublikuj na stronie:'; $a->strings['(Re-)Authenticate your tumblr page'] = '(Re-) Uwierzytelnij swoją stronę tumblr'; $a->strings['You are not authenticated to tumblr'] = 'Nie jesteś uwierzytelniony w tumblr'; $a->strings['Enable Tumblr Post Addon'] = 'Włącz dodatek Tumblr'; $a->strings['Post to Tumblr by default'] = 'Wyślij domyślnie do Tumblr'; -$a->strings['Tumblr Export'] = 'Eksportuj do Tumblr'; +$a->strings['Post to Tumblr'] = 'Opublikuj w Tumblr'; diff --git a/tumblr/lang/sv/messages.po b/tumblr/lang/sv/messages.po index fe631007..3ff328a8 100644 --- a/tumblr/lang/sv/messages.po +++ b/tumblr/lang/sv/messages.po @@ -10,64 +10,81 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-11-21 19:17-0500\n" -"PO-Revision-Date: 2022-01-16 00:55+0000\n" -"Last-Translator: Kristoffer Grundström \n" -"Language-Team: Swedish (http://www.transifex.com/Friendica/friendica/language/sv/)\n" +"POT-Creation-Date: 2023-04-29 06:56+0000\n" +"PO-Revision-Date: 2014-06-23 12:58+0000\n" +"Last-Translator: Kristoffer Grundström , 2022\n" +"Language-Team: Swedish (http://app.transifex.com/Friendica/friendica/language/sv/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: sv\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: tumblr.php:39 +#: tumblr.php:243 msgid "Permission denied." msgstr "Åtkomst nekad." -#: tumblr.php:69 +#: tumblr.php:296 msgid "Save Settings" msgstr "" -#: tumblr.php:71 +#: tumblr.php:297 msgid "Consumer Key" msgstr "" -#: tumblr.php:72 +#: tumblr.php:298 msgid "Consumer Secret" msgstr "" -#: tumblr.php:177 -msgid "You are now authenticated to tumblr." -msgstr "Du är nu autentiserad till tumblr." - -#: tumblr.php:178 -msgid "return to the connector page" +#: tumblr.php:299 +msgid "Maximum tags" msgstr "" -#: tumblr.php:194 -msgid "Post to Tumblr" +#: tumblr.php:299 +msgid "" +"Maximum number of tags that a user can follow. Enter 0 to deactivate the " +"feature." msgstr "" -#: tumblr.php:225 +#: tumblr.php:336 msgid "Post to page:" msgstr "" -#: tumblr.php:231 +#: tumblr.php:342 msgid "(Re-)Authenticate your tumblr page" msgstr "" -#: tumblr.php:232 +#: tumblr.php:343 msgid "You are not authenticated to tumblr" msgstr "Du är inte autentiserad till tumblr" -#: tumblr.php:237 +#: tumblr.php:348 msgid "Enable Tumblr Post Addon" msgstr "" -#: tumblr.php:238 +#: tumblr.php:349 msgid "Post to Tumblr by default" msgstr "" -#: tumblr.php:244 -msgid "Tumblr Export" +#: tumblr.php:350 +msgid "Import the remote timeline" +msgstr "" + +#: tumblr.php:351 +msgid "Subscribed tags" +msgstr "" + +#: tumblr.php:351 +#, php-format +msgid "" +"Comma separated list of up to %d tags that will be imported additionally to " +"the timeline" +msgstr "" + +#: tumblr.php:357 +msgid "Tumblr Import/Export" +msgstr "" + +#: tumblr.php:375 +msgid "Post to Tumblr" msgstr "" diff --git a/tumblr/lang/sv/strings.php b/tumblr/lang/sv/strings.php index 4d39d3c2..84a0e774 100644 --- a/tumblr/lang/sv/strings.php +++ b/tumblr/lang/sv/strings.php @@ -6,5 +6,4 @@ function string_plural_select_sv($n){ return intval($n != 1); }} $a->strings['Permission denied.'] = 'Åtkomst nekad.'; -$a->strings['You are now authenticated to tumblr.'] = 'Du är nu autentiserad till tumblr.'; $a->strings['You are not authenticated to tumblr'] = 'Du är inte autentiserad till tumblr'; diff --git a/tumblr/tumblr.php b/tumblr/tumblr.php index 78e415ee..9e691bf2 100644 --- a/tumblr/tumblr.php +++ b/tumblr/tumblr.php @@ -14,7 +14,6 @@ use Friendica\Content\Text\NPF; use Friendica\Core\Cache\Enum\Duration; use Friendica\Core\Config\Util\ConfigFileManager; use Friendica\Core\Hook; -use Friendica\Core\Logger; use Friendica\Core\Protocol; use Friendica\Core\Renderer; use Friendica\Core\System; @@ -22,6 +21,7 @@ use Friendica\Core\Worker; use Friendica\Database\DBA; use Friendica\DI; use Friendica\Model\Contact; +use Friendica\Model\Conversation; use Friendica\Model\Item; use Friendica\Model\Photo; use Friendica\Model\Post; @@ -31,7 +31,6 @@ use Friendica\Network\HTTPClient\Client\HttpClientAccept; use Friendica\Network\HTTPClient\Client\HttpClientOptions; use Friendica\Protocol\Activity; use Friendica\Util\DateTimeFormat; -use Friendica\Util\Network; use Friendica\Util\Strings; use GuzzleHttp\Client; use GuzzleHttp\Exception\RequestException; @@ -60,12 +59,12 @@ function tumblr_install() Hook::register('check_item_notification', __FILE__, 'tumblr_check_item_notification'); Hook::register('probe_detect', __FILE__, 'tumblr_probe_detect'); Hook::register('item_by_link', __FILE__, 'tumblr_item_by_link'); - Logger::info('installed tumblr'); + DI::logger()->info('installed tumblr'); } function tumblr_load_config(ConfigFileManager $loader) { - DI::app()->getConfigCache()->load($loader->loadAddonConfig('tumblr'), \Friendica\Core\Config\ValueObject\Cache::SOURCE_STATIC); + DI::appHelper()->getConfigCache()->load($loader->loadAddonConfig('tumblr'), \Friendica\Core\Config\ValueObject\Cache::SOURCE_STATIC); } function tumblr_check_item_notification(array &$notification_data) @@ -121,18 +120,19 @@ function tumblr_item_by_link(array &$hookData) return; } - Logger::debug('Found tumblr post', ['url' => $hookData['uri'], 'blog' => $matches[1], 'id' => $matches[2]]); + DI::logger()->debug('Found tumblr post', ['url' => $hookData['uri'], 'blog' => $matches[1], 'id' => $matches[2]]); $parameters = ['id' => $matches[2], 'reblog_info' => false, 'notes_info' => false, 'npf' => false]; $result = tumblr_get($hookData['uid'], 'blog/' . $matches[1] . '/posts', $parameters); if ($result->meta->status > 399) { - Logger::notice('Error fetching status', ['meta' => $result->meta, 'response' => $result->response, 'errors' => $result->errors, 'blog' => $matches[1], 'id' => $matches[2]]); + DI::logger()->notice('Error fetching status', ['meta' => $result->meta, 'response' => $result->response, 'errors' => $result->errors, 'blog' => $matches[1], 'id' => $matches[2]]); return []; } - Logger::debug('Got post', ['blog' => $matches[1], 'id' => $matches[2], 'result' => $result->response->posts]); + DI::logger()->debug('Got post', ['blog' => $matches[1], 'id' => $matches[2], 'result' => $result->response->posts]); if (!empty($result->response->posts)) { $hookData['item_id'] = tumblr_process_post($result->response->posts[0], $hookData['uid'], Item::PR_FETCHED); + Item::incrementInbound(Protocol::TUMBLR); } } @@ -158,20 +158,20 @@ function tumblr_follow(array &$hook_data) return; } - Logger::debug('Check if contact is Tumblr', ['url' => $hook_data['url']]); + DI::logger()->debug('Check if contact is Tumblr', ['url' => $hook_data['url']]); $fields = tumblr_get_contact_by_url($hook_data['url'], $uid); if (empty($fields)) { - Logger::debug('Contact is not a Tumblr contact', ['url' => $hook_data['url']]); + DI::logger()->debug('Contact is not a Tumblr contact', ['url' => $hook_data['url']]); return; } $result = tumblr_post($uid, 'user/follow', ['url' => $fields['url']]); if ($result->meta->status <= 399) { $hook_data['contact'] = $fields; - Logger::debug('Successfully start following', ['url' => $fields['url']]); + DI::logger()->debug('Successfully start following', ['url' => $fields['url']]); } else { - Logger::notice('Following failed', ['meta' => $result->meta, 'response' => $result->response, 'errors' => $result->errors, 'url' => $fields['url']]); + DI::logger()->notice('Following failed', ['meta' => $result->meta, 'response' => $result->response, 'errors' => $result->errors, 'url' => $fields['url']]); } } @@ -203,9 +203,9 @@ function tumblr_block(array &$hook_data) $hook_data['result'] = ($result->meta->status <= 399); if ($hook_data['result']) { - $cdata = Contact::getPublicAndUserContactID($hook_data['contact']['id'], $hook_data['uid']); - if (!empty($cdata['user'])) { - Contact::remove($cdata['user']); + $ucid = Contact::getUserContactId($hook_data['contact']['id'], $hook_data['uid']); + if ($ucid) { + Contact::remove($ucid); } } } @@ -238,9 +238,7 @@ function tumblr_get_contact_uuid(array $contact): string * existence of this method is checked to figure out if the addon offers a * module. */ -function tumblr_module() -{ -} +function tumblr_module() {} function tumblr_content() { @@ -393,12 +391,17 @@ function tumblr_settings_post(array &$b) DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'tumblr', 'import', intval($_POST['tumblr_import'])); $max_tags = DI::config()->get('tumblr', 'max_tags') ?? TUMBLR_DEFAULT_MAXIMUM_TAGS; - $tags = []; - foreach (explode(',', $_POST['tags']) as $tag) { - if (count($tags) < $max_tags) { - $tags[] = trim($tag, ' #'); - } - } + + $tags = array_slice( + array_filter( + array_map( + function($tag) { return trim($tag, ' #');}, + explode(',', $_POST['tags']) ?: [] + ) + ), + 0, + $max_tags, + ); DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'tumblr', 'tags', $tags); } @@ -416,11 +419,11 @@ function tumblr_cron() if ($last) { $next = $last + ($poll_interval * 60); if ($next > time()) { - Logger::notice('poll interval not reached'); + DI::logger()->notice('poll interval not reached'); return; } } - Logger::notice('cron_start'); + DI::logger()->notice('cron_start'); $abandon_days = intval(DI::config()->get('system', 'account_abandon_days')); if ($abandon_days < 1) { @@ -433,30 +436,30 @@ function tumblr_cron() foreach ($pconfigs as $pconfig) { if ($abandon_days != 0) { if (!DBA::exists('user', ["`uid` = ? AND `login_date` >= ?", $pconfig['uid'], $abandon_limit])) { - Logger::notice('abandoned account: timeline from user will not be imported', ['user' => $pconfig['uid']]); + DI::logger()->notice('abandoned account: timeline from user will not be imported', ['user' => $pconfig['uid']]); continue; } } - Logger::notice('importing timeline - start', ['user' => $pconfig['uid']]); + DI::logger()->notice('importing timeline - start', ['user' => $pconfig['uid']]); tumblr_fetch_dashboard($pconfig['uid'], $last); tumblr_fetch_tags($pconfig['uid'], $last); - Logger::notice('importing timeline - done', ['user' => $pconfig['uid']]); + DI::logger()->notice('importing timeline - done', ['user' => $pconfig['uid']]); } $last_clean = DI::keyValue()->get('tumblr_last_clean'); if (empty($last_clean) || ($last_clean + 86400 < time())) { - Logger::notice('Start contact cleanup'); + DI::logger()->notice('Start contact cleanup'); $contacts = DBA::select('account-user-view', ['id', 'pid'], ["`network` = ? AND `uid` != ? AND `rel` = ?", Protocol::TUMBLR, 0, Contact::NOTHING]); while ($contact = DBA::fetch($contacts)) { Worker::add(Worker::PRIORITY_LOW, 'MergeContact', $contact['pid'], $contact['id'], 0); } DBA::close($contacts); DI::keyValue()->set('tumblr_last_clean', time()); - Logger::notice('Contact cleanup done'); + DI::logger()->notice('Contact cleanup done'); } - Logger::notice('cron_end'); + DI::logger()->notice('cron_end'); DI::keyValue()->set('tumblr_last_poll', time()); } @@ -478,13 +481,13 @@ function tumblr_hook_fork(array &$b) if (DI::pConfig()->get($post['uid'], 'tumblr', 'import')) { // Don't post if it isn't a reply to a tumblr post - if (($post['parent'] != $post['id']) && !Post::exists(['id' => $post['parent'], 'network' => Protocol::TUMBLR])) { - Logger::notice('No tumblr parent found', ['item' => $post['id']]); + if (($post['gravity'] != Item::GRAVITY_PARENT) && !Post::exists(['id' => $post['parent'], 'network' => Protocol::TUMBLR])) { + DI::logger()->notice('No tumblr parent found', ['item' => $post['id']]); $b['execute'] = false; return; } - } elseif (!strstr($post['postopts'] ?? '', 'tumblr') || ($post['parent'] != $post['id']) || $post['private']) { - DI::logger()->info('Activities are never exported when we don\'t import the tumblr timeline', ['uid' => $post['uid']]); + } elseif (!strstr($post['postopts'] ?? '', 'tumblr') || ($post['gravity'] != Item::GRAVITY_PARENT) || ($post['private'] == Item::PRIVATE)) { + DI::logger()->info('Post will not be exported', ['uid' => $post['uid'], 'postopts' => $post['postopts'], 'gravity' => $post['gravity'], 'private' => $post['private']]); $b['execute'] = false; return; } @@ -492,15 +495,11 @@ function tumblr_hook_fork(array &$b) function tumblr_post_local(array &$b) { - if ($b['edit']) { - return; - } - if (!DI::userSession()->getLocalUserId() || (DI::userSession()->getLocalUserId() != $b['uid'])) { return; } - if ($b['private'] || $b['parent']) { + if ($b['edit'] || ($b['private'] == Item::PRIVATE) || ($b['gravity'] != Item::GRAVITY_PARENT)) { return; } @@ -530,20 +529,20 @@ function tumblr_send(array &$b) } if ($b['gravity'] != Item::GRAVITY_PARENT) { - Logger::debug('Got comment', ['item' => $b]); + DI::logger()->debug('Got comment', ['item' => $b]); $parent = tumblr_get_post_from_uri($b['thr-parent']); if (empty($parent)) { - Logger::notice('No tumblr post', ['thr-parent' => $b['thr-parent']]); + DI::logger()->notice('No tumblr post', ['thr-parent' => $b['thr-parent']]); return; } - Logger::debug('Parent found', ['parent' => $parent]); + DI::logger()->debug('Parent found', ['parent' => $parent]); $page = tumblr_get_page($b['uid']); if ($b['gravity'] == Item::GRAVITY_COMMENT) { - Logger::notice('Commenting is not supported (yet)'); + DI::logger()->notice('Commenting is not supported (yet)'); } else { if (($b['verb'] == Activity::LIKE) && !$b['deleted']) { $params = ['id' => $parent['id'], 'reblog_key' => $parent['reblog_key']]; @@ -567,16 +566,16 @@ function tumblr_send(array &$b) } if ($result->meta->status < 400) { - Logger::info('Successfully performed activity', ['verb' => $b['verb'], 'deleted' => $b['deleted'], 'meta' => $result->meta, 'response' => $result->response]); + DI::logger()->info('Successfully performed activity', ['verb' => $b['verb'], 'deleted' => $b['deleted'], 'meta' => $result->meta, 'response' => $result->response]); if (!$b['deleted'] && !empty($result->response->id_string)) { - Item::update(['extid' => 'tumblr::' . $result->response->id_string], ['id' => $b['id']]); + Item::update(['extid' => 'tumblr::' . $result->response->id_string], ['guid' => $b['guid']]); } } else { - Logger::notice('Error while performing activity', ['verb' => $b['verb'], 'deleted' => $b['deleted'], 'meta' => $result->meta, 'response' => $result->response, 'errors' => $result->errors, 'params' => $params]); + DI::logger()->notice('Error while performing activity', ['verb' => $b['verb'], 'deleted' => $b['deleted'], 'meta' => $result->meta, 'response' => $result->response, 'errors' => $result->errors, 'params' => $params]); } } return; - } elseif ($b['private'] || !strstr($b['postopts'], 'tumblr')) { + } elseif (($b['private'] == Item::PRIVATE) || !strstr($b['postopts'], 'tumblr')) { return; } @@ -608,13 +607,22 @@ function tumblr_send_legacy(array $b) $body = BBCode::removeShareInformation($b['body']); $body = Post\Media::removeFromEndOfBody($body); + if (!empty($b['quote-uri-id'])) { + $quote = Post::selectFirstPost(['uri', 'plink'], ['uri-id' => $b['quote-uri-id']]); + if (!empty($quote)) { + if ((strpos($body, $quote['plink'] ?: $quote['uri']) === false) && (strpos($body, $quote['uri']) === false)) { + $body .= "\n[url]" . ($quote['plink'] ?: $quote['uri']) . "[/url]\n"; + } + } + } + if ($photo !== false) { $params['type'] = 'photo'; $params['caption'] = BBCode::convertForUriId($b['uri-id'], $body, BBCode::CONNECTORS); $params['data'] = []; foreach ($media as $photo) { if ($photo['type'] == Post\Media::IMAGE) { - if (Network::isLocalLink($photo['url']) && ($data = Photo::getResourceData($photo['url']))) { + if (DI::baseUrl()->isLocalUrl($photo['url']) && ($data = Photo::getResourceData($photo['url']))) { $photo = Photo::selectFirst([], ["`resource-id` = ? AND `scale` > ?", $data['guid'], 0]); if (!empty($photo)) { $params['data'][] = Photo::getImageDataForPhoto($photo); @@ -648,7 +656,7 @@ function tumblr_send_legacy(array $b) } else { $params['type'] = 'text'; $params['title'] = $title; - $params['body'] = BBCode::convertForUriId($b['uri-id'], $b['body'], BBCode::CONNECTORS); + $params['body'] = BBCode::convertForUriId($b['uri-id'], $body, BBCode::CONNECTORS); } if (isset($params['caption']) && (trim($title) != '')) { @@ -661,9 +669,9 @@ function tumblr_send_legacy(array $b) $result = tumblr_post($b['uid'], 'blog/' . $page . '/post', $params); if ($result->meta->status < 400) { - Logger::info('Success (legacy)', ['blog' => $page, 'meta' => $result->meta, 'response' => $result->response]); + DI::logger()->info('Success (legacy)', ['blog' => $page, 'meta' => $result->meta, 'response' => $result->response]); } else { - Logger::notice('Error posting blog (legacy)', ['blog' => $page, 'meta' => $result->meta, 'response' => $result->response, 'errors' => $result->errors, 'params' => $params]); + DI::logger()->notice('Error posting blog (legacy)', ['blog' => $page, 'meta' => $result->meta, 'response' => $result->response, 'errors' => $result->errors, 'params' => $params]); } } @@ -672,7 +680,7 @@ function tumblr_send_npf(array $post): bool $page = tumblr_get_page($post['uid']); if (empty($page)) { - Logger::notice('Missing page, post will not be send to Tumblr.', ['uid' => $post['uid'], 'page' => $page, 'id' => $post['id']]); + DI::logger()->notice('Missing page, post will not be send to Tumblr.', ['uid' => $post['uid'], 'page' => $page, 'id' => $post['id']]); // "true" is returned, since the legacy function will fail as well. return true; } @@ -703,10 +711,10 @@ function tumblr_send_npf(array $post): bool $result = tumblr_post($post['uid'], 'blog/' . $page . '/posts', $params); if ($result->meta->status < 400) { - Logger::info('Success (NPF)', ['blog' => $page, 'meta' => $result->meta, 'response' => $result->response]); + DI::logger()->info('Success (NPF)', ['blog' => $page, 'meta' => $result->meta, 'response' => $result->response]); return true; } else { - Logger::notice('Error posting blog (NPF)', ['blog' => $page, 'meta' => $result->meta, 'response' => $result->response, 'errors' => $result->errors, 'params' => $params]); + DI::logger()->notice('Error posting blog (NPF)', ['blog' => $page, 'meta' => $result->meta, 'response' => $result->response, 'errors' => $result->errors, 'params' => $params]); return false; } } @@ -739,14 +747,26 @@ function tumblr_fetch_tags(int $uid, int $last_poll) } foreach (DI::pConfig()->get($uid, 'tumblr', 'tags') ?? [] as $tag) { + // Tumblr will return an error for queries on empty tag + if (!$tag) { + continue; + } + $data = tumblr_get($uid, 'tagged', ['tag' => $tag]); + + if (!is_array($data->response)) { + DI::logger()->warning('Unexpected Tumblr response format', ['uid' => $uid, 'url' => 'tagged', 'parameters' => ['tag' => $tag], 'data' => $data]); + continue; + } + foreach (array_reverse($data->response) as $post) { $id = tumblr_process_post($post, $uid, Item::PR_TAG, $last_poll); if (!empty($id)) { - Logger::debug('Tag post imported', ['tag' => $tag, 'id' => $id]); + DI::logger()->debug('Tag post imported', ['tag' => $tag, 'id' => $id]); $post = Post::selectFirst(['uri-id'], ['id' => $id]); $stored = Post\Category::storeFileByURIId($post['uri-id'], $uid, Post\Category::SUBCRIPTION, $tag); - Logger::debug('Stored tag subscription for user', ['uri-id' => $post['uri-id'], 'uid' => $uid, 'tag' => $tag, 'stored' => $stored]); + DI::logger()->debug('Stored tag subscription for user', ['uri-id' => $post['uri-id'], 'uid' => $uid, 'tag' => $tag, 'stored' => $stored]); + Item::incrementInbound(Protocol::TUMBLR); } } } @@ -770,8 +790,8 @@ function tumblr_fetch_dashboard(int $uid, int $last_poll) $dashboard = tumblr_get($uid, 'user/dashboard', $parameters); if ($dashboard->meta->status > 399) { - Logger::notice('Error fetching dashboard', ['meta' => $dashboard->meta, 'response' => $dashboard->response, 'errors' => $dashboard->errors]); - return []; + DI::logger()->notice('Error fetching dashboard', ['meta' => $dashboard->meta, 'response' => $dashboard->response, 'errors' => $dashboard->errors]); + return; } if (empty($dashboard->response->posts)) { @@ -783,9 +803,10 @@ function tumblr_fetch_dashboard(int $uid, int $last_poll) $last = $post->id; } - Logger::debug('Importing post', ['uid' => $uid, 'created' => date(DateTimeFormat::MYSQL, $post->timestamp), 'id' => $post->id_string]); + DI::logger()->debug('Importing post', ['uid' => $uid, 'created' => date(DateTimeFormat::MYSQL, $post->timestamp), 'id' => $post->id_string]); tumblr_process_post($post, $uid, Item::PR_NONE, $last_poll); + Item::incrementInbound(Protocol::TUMBLR); DI::pConfig()->set($uid, 'tumblr', 'last_id', $last); } @@ -840,6 +861,7 @@ function tumblr_get_header(stdClass $post, string $uri, int $uid): array $contact = tumblr_get_contact($post->blog, $uid); $item = [ 'network' => Protocol::TUMBLR, + 'protocol' => Conversation::PARCEL_CONNECTOR, 'uid' => $uid, 'wall' => false, 'uri' => $uri, @@ -1056,7 +1078,7 @@ function tumblr_get_type_replacement(array $data, string $plink): string } default: - Logger::notice('Unknown type', ['type' => $data['type'], 'data' => $data, 'plink' => $plink]); + DI::logger()->notice('Unknown type', ['type' => $data['type'], 'data' => $data, 'plink' => $plink]); $body = ''; } @@ -1111,9 +1133,9 @@ function tumblr_get_contact(stdClass $blog, int $uid): array $cid = $contact['id']; Contact::update($fields, ['id' => $cid], true); } - Logger::debug('Get user contact', ['id' => $cid, 'uid' => $uid, 'update' => $update]); + DI::logger()->debug('Get user contact', ['id' => $cid, 'uid' => $uid, 'update' => $update]); } else { - Logger::debug('Get public contact', ['id' => $cid, 'uid' => $uid, 'update' => $update]); + DI::logger()->debug('Get public contact', ['id' => $cid, 'uid' => $uid, 'update' => $update]); } if (!empty($avatar)) { @@ -1149,15 +1171,16 @@ function tumblr_get_contact_fields(stdClass $blog, int $uid, bool $update): arra ]; if (!$update) { - Logger::debug('Got contact fields', ['uid' => $uid, 'url' => $fields['url']]); + DI::logger()->debug('Got contact fields', ['uid' => $uid, 'url' => $fields['url']]); return $fields; } $info = tumblr_get($uid, 'blog/' . $blog->uuid . '/info'); if ($info->meta->status > 399) { - Logger::notice('Error fetching blog info', ['meta' => $info->meta, 'response' => $info->response, 'errors' => $info->errors]); + DI::logger()->notice('Error fetching blog info', ['meta' => $info->meta, 'response' => $info->response, 'errors' => $info->errors]); return $fields; } + Item::incrementInbound(Protocol::TUMBLR); $avatar = $info->response->blog->avatar; if (!empty($avatar)) { @@ -1176,7 +1199,7 @@ function tumblr_get_contact_fields(stdClass $blog, int $uid, bool $update): arra $fields['header'] = $info->response->blog->theme->header_image_focused; - Logger::debug('Got updated contact fields', ['uid' => $uid, 'url' => $fields['url']]); + DI::logger()->debug('Got updated contact fields', ['uid' => $uid, 'url' => $fields['url']]); return $fields; } @@ -1218,10 +1241,12 @@ function tumblr_get_blogs(int $uid): array { $userinfo = tumblr_get($uid, 'user/info'); if ($userinfo->meta->status > 399) { - Logger::notice('Error fetching blogs', ['meta' => $userinfo->meta, 'response' => $userinfo->response, 'errors' => $userinfo->errors]); + DI::logger()->notice('Error fetching blogs', ['meta' => $userinfo->meta, 'response' => $userinfo->response, 'errors' => $userinfo->errors]); return []; } + Item::incrementInbound(Protocol::TUMBLR); + $blogs = []; foreach ($userinfo->response->user->blogs as $blog) { $blogs[$blog->uuid] = $blog->name; @@ -1272,16 +1297,17 @@ function tumblr_get_contact_by_url(string $url, int $uid): ?array return null; } - Logger::debug('Update Tumblr blog data', ['url' => $url, 'blog' => $blog, 'uid' => $uid]); + DI::logger()->debug('Update Tumblr blog data', ['url' => $url, 'blog' => $blog, 'uid' => $uid]); $info = tumblr_get($uid, 'blog/' . $blog . '/info'); if ($info->meta->status > 399) { - Logger::notice('Error fetching blog info', ['meta' => $info->meta, 'response' => $info->response, 'errors' => $info->errors, 'blog' => $blog, 'uid' => $uid]); + DI::logger()->notice('Error fetching blog info', ['meta' => $info->meta, 'response' => $info->response, 'errors' => $info->errors, 'blog' => $blog, 'uid' => $uid]); return null; - } else { - Logger::debug('Got data', ['blog' => $blog, 'meta' => $info->meta]); } + DI::logger()->debug('Got data', ['blog' => $blog, 'meta' => $info->meta]); + Item::incrementInbound(Protocol::TUMBLR); + $baseurl = 'https://tumblr.com'; $url = $baseurl . '/' . $info->response->blog->name; @@ -1346,6 +1372,7 @@ function tumblr_get(int $uid, string $url, array $parameters = []): stdClass */ function tumblr_post(int $uid, string $url, array $parameters): stdClass { + Item::incrementOutbound(Protocol::TUMBLR); $url = 'https://api.tumblr.com/v2/' . $url; $curlResult = DI::httpClient()->post($url, $parameters, ['Authorization' => ['Bearer ' . tumblr_get_token($uid)]]); @@ -1407,7 +1434,7 @@ function tumblr_get_token(int $uid, string $code = ''): string $refresh_token = DI::pConfig()->get($uid, 'tumblr', 'refresh_token'); if (empty($code) && !empty($access_token) && ($expires_at > (time()))) { - Logger::debug('Got token', ['uid' => $uid, 'expires_at' => date('c', $expires_at)]); + DI::logger()->debug('Got token', ['uid' => $uid, 'expires_at' => date('c', $expires_at)]); return $access_token; } @@ -1419,11 +1446,11 @@ function tumblr_get_token(int $uid, string $code = ''): string if (empty($refresh_token) && empty($code)) { $result = tumblr_exchange_token($uid); if (empty($result->refresh_token)) { - Logger::info('Invalid result while exchanging token', ['uid' => $uid]); + DI::logger()->info('Invalid result while exchanging token', ['uid' => $uid]); return ''; } $expires_at = time() + $result->expires_in; - Logger::debug('Updated token from OAuth1 to OAuth2', ['uid' => $uid, 'expires_at' => date('c', $expires_at)]); + DI::logger()->debug('Updated token from OAuth1 to OAuth2', ['uid' => $uid, 'expires_at' => date('c', $expires_at)]); } else { if (!empty($code)) { $parameters['code'] = $code; @@ -1435,18 +1462,18 @@ function tumblr_get_token(int $uid, string $code = ''): string $curlResult = DI::httpClient()->post('https://api.tumblr.com/v2/oauth2/token', $parameters); if (!$curlResult->isSuccess()) { - Logger::info('Error fetching token', ['uid' => $uid, 'code' => $code, 'result' => $curlResult->getBodyString(), 'parameters' => $parameters]); + DI::logger()->info('Error fetching token', ['uid' => $uid, 'code' => $code, 'result' => $curlResult->getBodyString(), 'parameters' => $parameters]); return ''; } $result = json_decode($curlResult->getBodyString()); if (empty($result)) { - Logger::info('Invalid result when updating token', ['uid' => $uid]); + DI::logger()->info('Invalid result when updating token', ['uid' => $uid]); return ''; } $expires_at = time() + $result->expires_in; - Logger::debug('Renewed token', ['uid' => $uid, 'expires_at' => date('c', $expires_at)]); + DI::logger()->debug('Renewed token', ['uid' => $uid, 'expires_at' => date('c', $expires_at)]); } DI::pConfig()->set($uid, 'tumblr', 'access_token', $result->access_token); @@ -1490,7 +1517,7 @@ function tumblr_exchange_token(int $uid): stdClass $response = $client->post('oauth2/exchange', ['auth' => 'oauth']); return json_decode($response->getBody()->getContents()); } catch (RequestException $exception) { - Logger::notice('Exchange failed', ['code' => $exception->getCode(), 'message' => $exception->getMessage()]); + DI::logger()->notice('Exchange failed', ['code' => $exception->getCode(), 'message' => $exception->getMessage()]); return new stdClass; } } diff --git a/twitter/twitter.php b/twitter/twitter.php index 11c163ef..a9654405 100644 --- a/twitter/twitter.php +++ b/twitter/twitter.php @@ -38,7 +38,6 @@ use Friendica\Content\Text\BBCode; use Friendica\Content\Text\Plaintext; use Friendica\Core\Hook; -use Friendica\Core\Logger; use Friendica\Core\Renderer; use Friendica\Core\Worker; use Friendica\DI; @@ -67,7 +66,7 @@ function twitter_install() function twitter_load_config(ConfigFileManager $loader) { - DI::app()->getConfigCache()->load($loader->loadAddonConfig('twitter'), \Friendica\Core\Config\ValueObject\Cache::SOURCE_STATIC); + DI::appHelper()->getConfigCache()->load($loader->loadAddonConfig('twitter'), \Friendica\Core\Config\ValueObject\Cache::SOURCE_STATIC); } function twitter_jot_nets(array &$jotnets_fields) @@ -170,7 +169,7 @@ function twitter_hook_fork(array &$b) $post = $b['data']; if ( - $post['deleted'] || $post['private'] || ($post['created'] !== $post['edited']) || + $post['deleted'] || ($post['private'] == Item::PRIVATE) || ($post['created'] !== $post['edited']) || !strstr($post['postopts'], 'twitter') || ($post['gravity'] != Item::GRAVITY_PARENT) ) { $b['execute'] = false; @@ -184,7 +183,7 @@ function twitter_post_local(array &$b) return; } - if ($b['edit'] || $b['private'] || $b['parent']) { + if ($b['edit'] || ($b['private'] == Item::PRIVATE) || ($b['gravity'] != Item::GRAVITY_PARENT)) { return; } @@ -211,13 +210,13 @@ function twitter_post_hook(array &$b) { DI::logger()->debug('Invoke post hook', $b); - if (($b['gravity'] != Item::GRAVITY_PARENT) || !strstr($b['postopts'], 'twitter') || $b['private'] || $b['deleted'] || ($b['created'] !== $b['edited'])) { + if (($b['gravity'] != Item::GRAVITY_PARENT) || !strstr($b['postopts'], 'twitter') || ($b['private'] == Item::PRIVATE) || $b['deleted'] || ($b['created'] !== $b['edited'])) { return; } $b['body'] = Post\Media::addAttachmentsToBody($b['uri-id'], DI::contentItem()->addSharedPost($b)); - Logger::notice('twitter post invoked', ['id' => $b['id'], 'guid' => $b['guid']]); + DI::logger()->notice('twitter post invoked', ['id' => $b['id'], 'guid' => $b['guid']]); DI::pConfig()->load($b['uid'], 'twitter'); @@ -227,17 +226,17 @@ function twitter_post_hook(array &$b) $access_secret = DI::pConfig()->get($b['uid'], 'twitter', 'access_secret'); if (empty($api_key) || empty($api_secret) || empty($access_token) || empty($access_secret)) { - Logger::info('Missing keys, secrets or tokens.'); + DI::logger()->info('Missing keys, secrets or tokens.'); return; } $msgarr = Plaintext::getPost($b, 280, true, BBCode::TWITTER); - Logger::debug('Got plaintext', ['id' => $b['id'], 'message' => $msgarr]); + DI::logger()->debug('Got plaintext', ['id' => $b['id'], 'message' => $msgarr]); $media_ids = []; if (!empty($msgarr['images']) || !empty($msgarr['remote_images'])) { - Logger::info('Got images', ['id' => $b['id'], 'images' => $msgarr['images'] ?? []]); + DI::logger()->info('Got images', ['id' => $b['id'], 'images' => $msgarr['images'] ?? []]); $retrial = Worker::getRetrial(); if ($retrial > 4) { @@ -250,7 +249,7 @@ function twitter_post_hook(array &$b) try { $media_ids[] = twitter_upload_image($b['uid'], $image, $retrial); } catch (RequestException $exception) { - Logger::warning('Error while uploading image', ['image' => $image, 'code' => $exception->getCode(), 'message' => $exception->getMessage()]); + DI::logger()->warning('Error while uploading image', ['image' => $image, 'code' => $exception->getCode(), 'message' => $exception->getMessage()]); Worker::defer(); return; } @@ -259,13 +258,13 @@ function twitter_post_hook(array &$b) $in_reply_to_tweet_id = 0; - Logger::debug('Post message', ['id' => $b['id'], 'parts' => count($msgarr['parts'])]); + DI::logger()->debug('Post message', ['id' => $b['id'], 'parts' => count($msgarr['parts'])]); foreach ($msgarr['parts'] as $key => $part) { try { $id = twitter_post_status($b['uid'], $part, $media_ids, $in_reply_to_tweet_id); - Logger::info('twitter_post send', ['part' => $key, 'id' => $b['id'], 'result' => $id]); + DI::logger()->info('twitter_post send', ['part' => $key, 'id' => $b['id'], 'result' => $id]); } catch (RequestException $exception) { - Logger::warning('Error while posting message', ['part' => $key, 'id' => $b['id'], 'code' => $exception->getCode(), 'message' => $exception->getMessage()]); + DI::logger()->warning('Error while posting message', ['part' => $key, 'id' => $b['id'], 'code' => $exception->getCode(), 'message' => $exception->getMessage()]); $status = [ 'code' => $exception->getCode(), 'reason' => $exception->getResponse()->getReasonPhrase(), @@ -319,9 +318,9 @@ function twitter_upload_image(int $uid, array $image, int $retrial) $picturedata = $picture->asString(); $new_size = strlen($picturedata); - Logger::info('Uploading', ['uid' => $uid, 'retrial' => $retrial, 'height' => $new_height, 'width' => $new_width, 'size' => $new_size, 'orig-height' => $height, 'orig-width' => $width, 'orig-size' => $size, 'image' => $image]); + DI::logger()->info('Uploading', ['uid' => $uid, 'retrial' => $retrial, 'height' => $new_height, 'width' => $new_width, 'size' => $new_size, 'orig-height' => $height, 'orig-width' => $width, 'orig-size' => $size, 'image' => $image]); $media = twitter_post($uid, 'https://upload.twitter.com/1.1/media/upload.json', 'form_params', ['media' => base64_encode($picturedata)]); - Logger::info('Uploading done', ['uid' => $uid, 'retrial' => $retrial, 'height' => $new_height, 'width' => $new_width, 'size' => $new_size, 'orig-height' => $height, 'orig-width' => $width, 'orig-size' => $size, 'image' => $image]); + DI::logger()->info('Uploading done', ['uid' => $uid, 'retrial' => $retrial, 'height' => $new_height, 'width' => $new_width, 'size' => $new_size, 'orig-height' => $height, 'orig-width' => $width, 'orig-size' => $size, 'image' => $image]); if (isset($media->media_id_string)) { $media_id = $media->media_id_string; @@ -334,10 +333,10 @@ function twitter_upload_image(int $uid, array $image, int $retrial) ] ]; $ret = twitter_post($uid, 'https://upload.twitter.com/1.1/media/metadata/create.json', 'json', $data); - Logger::info('Metadata create', ['uid' => $uid, 'data' => $data, 'return' => $ret]); + DI::logger()->info('Metadata create', ['uid' => $uid, 'data' => $data, 'return' => $ret]); } } else { - Logger::error('Failed upload', ['uid' => $uid, 'size' => strlen($picturedata), 'image' => $image['url'], 'return' => $media]); + DI::logger()->error('Failed upload', ['uid' => $uid, 'size' => strlen($picturedata), 'image' => $image['url'], 'return' => $media]); throw new Exception('Failed upload of ' . $image['url']); } @@ -373,7 +372,7 @@ function twitter_post(int $uid, string $url, string $type, array $data): stdClas DI::pConfig()->set($uid, 'twitter', 'last_status', $status); $content = json_decode($body) ?? new stdClass; - Logger::debug('Success', ['content' => $content]); + DI::logger()->debug('Success', ['content' => $content]); return $content; } @@ -402,7 +401,7 @@ function twitter_test_connection(int $uid) 'content' => $response->getBody()->getContents() ]; DI::pConfig()->set(1, 'twitter', 'last_status', $status); - Logger::info('Test successful', ['uid' => $uid]); + DI::logger()->info('Test successful', ['uid' => $uid]); } catch (RequestException $exception) { $status = [ 'code' => $exception->getCode(), @@ -410,6 +409,6 @@ function twitter_test_connection(int $uid) 'content' => $exception->getMessage() ]; DI::pConfig()->set(1, 'twitter', 'last_status', $status); - Logger::info('Test failed', ['uid' => $uid]); + DI::logger()->info('Test failed', ['uid' => $uid]); } } diff --git a/unicode_smilies/unicode_smilies.php b/unicode_smilies/unicode_smilies.php index 3bd30644..8ec47175 100644 --- a/unicode_smilies/unicode_smilies.php +++ b/unicode_smilies/unicode_smilies.php @@ -2,12 +2,11 @@ /* * Name: Unicode Smilies * Description: Smilies based on the unicode emojis - On Linux use https://github.com/eosrei/emojione-color-font to see them in color and http://www.unicode.org/emoji/charts/full-emoji-list.html - * Version: 1.1.2 + * Version: 1.1.3 * Author: Michael Vogel * Author: Matthias Ebers */ -use Friendica\App; use Friendica\Content\Smilies; use Friendica\Core\Hook; @@ -25,7 +24,7 @@ function unicode_smilies_smilies(array &$b) Smilies::add($b, ':-D', '😁'); Smilies::add($b, ':D', '😁'); Smilies::add($b, ';-)', '😉'); - // Smilies::add($b, ';)', '😉'); // Deactivated since this leads to disturbed html entities +// Smilies::add($b, ';)', '😉'); // Deactivated since this leads to disturbed html entities Smilies::add($b, ':-P', '😛'); Smilies::add($b, ':-p', '😛'); Smilies::add($b, ':P', '😛'); @@ -54,353 +53,350 @@ function unicode_smilies_smilies(array &$b) // Smilies::add($b, 'O_o', '&#x;'); // face-smiling - Smilies::add($b, ':grinning face:', '😀'); - Smilies::add($b, ':grinning face with big eyes:', '😃'); - Smilies::add($b, ':grinning face with smiling eyes:', '😄'); - Smilies::add($b, ':beaming face with smiling eyes:', '😁'); - Smilies::add($b, ':grinning squinting face:', '😆'); - Smilies::add($b, ':laughing:', '😆'); - Smilies::add($b, ':grinning face with sweat:', '😅'); - Smilies::add($b, ':rolling on the floor laughing:', '🤣'); + Smilies::add($b, ':grinning face:', '😀'); + Smilies::add($b, ':grinning face with big eyes:', '😃'); + Smilies::add($b, ':grinning face with smiling eyes:', '😄'); + Smilies::add($b, ':beaming face with smiling eyes:', '😁'); + Smilies::add($b, ':grinning squinting face:', '😆'); + Smilies::add($b, ':laughing:', '😆'); + Smilies::add($b, ':grinning face with sweat:', '😅'); + Smilies::add($b, ':rolling on the floor laughing:', '🤣'); Smilies::add($b, ':rofl:', '🤣'); - Smilies::add($b, ':face with tears of joy:', '😂'); + Smilies::add($b, ':face with tears of joy:', '😂'); Smilies::add($b, ':tearsofjoy:', '😂'); - Smilies::add($b, ':slightly smiling face:', '🙂'); - Smilies::add($b, ':upside-down face:', '🙃'); - Smilies::add($b, ':winking face:', '😉'); - Smilies::add($b, ':smiling face with smiling eyes:', '😊'); - Smilies::add($b, ':smiling face with halo:', '😇'); + Smilies::add($b, ':slightly smiling face:', '🙂'); + Smilies::add($b, ':upside-down face:', '🙃'); + Smilies::add($b, ':winking face:', '😉'); + Smilies::add($b, ':smiling face with smiling eyes:', '😊'); + Smilies::add($b, ':smiling face with halo:', '😇'); // face-affection - Smilies::add($b, ':smiling face with hearts:', '🥰'); - Smilies::add($b, ':smiling face with heart-eyes:', '😍'); - Smilies::add($b, ':star-struck:', '🤩'); - Smilies::add($b, ':face blowing a kiss:', '😘'); - Smilies::add($b, ':kissing face:', '😗'); - Smilies::add($b, ':smiling face:', '☺'); - Smilies::add($b, ':kissing face with closed eyes:', '😚'); - Smilies::add($b, ':kissing face with smiling eyes:', '😙'); + Smilies::add($b, ':smiling face with hearts:', '🥰'); + Smilies::add($b, ':smiling face with heart-eyes:', '😍'); + Smilies::add($b, ':star-struck:', '🤩'); + Smilies::add($b, ':face blowing a kiss:', '😘'); + Smilies::add($b, ':kissing face:', '😗'); + Smilies::add($b, ':smiling face:', '☺'); + Smilies::add($b, ':kissing face with closed eyes:', '😚'); + Smilies::add($b, ':kissing face with smiling eyes:', '😙'); // face-tongue - Smilies::add($b, ':face savoring food:', '😋'); - Smilies::add($b, ':face with tongue:', '😛'); - Smilies::add($b, ':winking face with tongue:', '😜'); - Smilies::add($b, ':zany face:', '🤪'); - Smilies::add($b, ':squinting face with tongue:', '😝'); - Smilies::add($b, ':money-mouth face:', '🤑'); + Smilies::add($b, ':face savoring food:', '😋'); + Smilies::add($b, ':face with tongue:', '😛'); + Smilies::add($b, ':winking face with tongue:', '😜'); + Smilies::add($b, ':zany face:', '🤪'); + Smilies::add($b, ':squinting face with tongue:', '😝'); + Smilies::add($b, ':money-mouth face:', '🤑'); // face-hand - Smilies::add($b, ':hugging face:', '🤗'); - Smilies::add($b, ':face with hand over mouth:', '🤭'); - Smilies::add($b, ':shushing face:', '🤫'); - Smilies::add($b, ':thinking face:', '🤔'); + Smilies::add($b, ':hugging face:', '🤗'); + Smilies::add($b, ':face with hand over mouth:', '🤭'); + Smilies::add($b, ':shushing face:', '🤫'); + Smilies::add($b, ':thinking face:', '🤔'); // face-neutral-skeptical - Smilies::add($b, ':zipper-mouth face:', '🤐'); - Smilies::add($b, ':face with raised eyebrow:', '🤨'); - Smilies::add($b, ':neutral face:', '😐'); - Smilies::add($b, ':expressionless face:', '😑'); - Smilies::add($b, ':face without mouth:', '😶'); - Smilies::add($b, ':smirking face:', '😏'); - Smilies::add($b, ':unamused face:', '😒'); - Smilies::add($b, ':face with rolling eyes:', '🙄'); - Smilies::add($b, ':grimacing face:', '😬'); - Smilies::add($b, ':lying face:', '🤥'); + Smilies::add($b, ':zipper-mouth face:', '🤐'); + Smilies::add($b, ':face with raised eyebrow:', '🤨'); + Smilies::add($b, ':neutral face:', '😐'); + Smilies::add($b, ':expressionless face:', '😑'); + Smilies::add($b, ':face without mouth:', '😶'); + Smilies::add($b, ':smirking face:', '😏'); + Smilies::add($b, ':unamused face:', '😒'); + Smilies::add($b, ':face with rolling eyes:', '🙄'); + Smilies::add($b, ':grimacing face:', '😬'); + Smilies::add($b, ':lying face:', '🤥'); // face-sleepy - Smilies::add($b, ':relieved face:', '😌'); - Smilies::add($b, ':pensive face:', '😔'); - Smilies::add($b, ':sleepy face:', '😪'); - Smilies::add($b, ':drooling face:', '🤤'); + Smilies::add($b, ':relieved face:', '😌'); + Smilies::add($b, ':pensive face:', '😔'); + Smilies::add($b, ':sleepy face:', '😪'); + Smilies::add($b, ':drooling face:', '🤤'); Smilies::add($b, ':drool:', '🤤'); - Smilies::add($b, ':sleeping face:', '😴'); + Smilies::add($b, ':sleeping face:', '😴'); // face-unwell - Smilies::add($b, ':face with medical mask:', '😷'); - Smilies::add($b, ':face with thermometer:', '🤒'); - Smilies::add($b, ':face with head-bandage:', '🤕'); - Smilies::add($b, ':nauseated face:', '🤢'); - Smilies::add($b, ':face vomiting:', '🤮'); + Smilies::add($b, ':face with medical mask:', '😷'); + Smilies::add($b, ':face with thermometer:', '🤒'); + Smilies::add($b, ':face with head-bandage:', '🤕'); + Smilies::add($b, ':nauseated face:', '🤢'); + Smilies::add($b, ':face vomiting:', '🤮'); Smilies::add($b, ':vomit:', '🤮'); - Smilies::add($b, ':sneezing face:', '🤧'); - Smilies::add($b, ':hot face:', '🥵'); - Smilies::add($b, ':cold face:', '🥶'); - Smilies::add($b, ':woozy face:', '🥴'); - Smilies::add($b, ':dizzy face:', '😵'); + Smilies::add($b, ':sneezing face:', '🤧'); + Smilies::add($b, ':hot face:', '🥵'); + Smilies::add($b, ':cold face:', '🥶'); + Smilies::add($b, ':woozy face:', '🥴'); + Smilies::add($b, ':dizzy face:', '😵'); Smilies::add($b, ':dead:', '😵'); - Smilies::add($b, ':exploding head:', '🤯'); + Smilies::add($b, ':exploding head:', '🤯'); // face-hat - Smilies::add($b, ':cowboy hat face:', '🤠'); - Smilies::add($b, ':partying face:', '🥳'); + Smilies::add($b, ':cowboy hat face:', '🤠'); + Smilies::add($b, ':partying face:', '🥳'); // face-glasses - Smilies::add($b, ':smiling face with sunglasses:', '😎'); - Smilies::add($b, ':nerd face:', '🤓'); - Smilies::add($b, ':face with monocle:', '🧐'); + Smilies::add($b, ':smiling face with sunglasses:', '😎'); + Smilies::add($b, ':nerd face:', '🤓'); + Smilies::add($b, ':face with monocle:', '🧐'); // face-concerned - Smilies::add($b, ':confused face:', '😕'); - Smilies::add($b, ':worried face:', '😟'); - Smilies::add($b, ':slightly frowning face:', '🙁'); - Smilies::add($b, ':frowning face:', '☹'); - Smilies::add($b, ':face with open mouth:', '😮'); - Smilies::add($b, ':hushed face:', '😯'); - Smilies::add($b, ':astonished face:', '😲'); - Smilies::add($b, ':flushed face:', '😳'); + Smilies::add($b, ':confused face:', '😕'); + Smilies::add($b, ':worried face:', '😟'); + Smilies::add($b, ':slightly frowning face:', '🙁'); + Smilies::add($b, ':frowning face:', '☹'); + Smilies::add($b, ':face with open mouth:', '😮'); + Smilies::add($b, ':hushed face:', '😯'); + Smilies::add($b, ':astonished face:', '😲'); + Smilies::add($b, ':flushed face:', '😳'); Smilies::add($b, ':dazed:', '😳'); - Smilies::add($b, ':pleading face:', '🥺'); - Smilies::add($b, ':frowning face with open mouth:', '😦'); - Smilies::add($b, ':anguished face:', '😧'); - Smilies::add($b, ':fearful face:', '😨'); - Smilies::add($b, ':anxious face with sweat:', '😰'); - Smilies::add($b, ':sad but relieved face:', '😥'); - Smilies::add($b, ':crying face:', '😢'); - Smilies::add($b, ':loudly crying face:', '😭'); - Smilies::add($b, ':face screaming in fear:', '😱'); - Smilies::add($b, ':confounded face:', '😖'); - Smilies::add($b, ':persevering face:', '😣'); - Smilies::add($b, ':disappointed face:', '😞'); + Smilies::add($b, ':pleading face:', '🥺'); + Smilies::add($b, ':frowning face with open mouth:', '😦'); + Smilies::add($b, ':anguished face:', '😧'); + Smilies::add($b, ':fearful face:', '😨'); + Smilies::add($b, ':anxious face with sweat:', '😰'); + Smilies::add($b, ':sad but relieved face:', '😥'); + Smilies::add($b, ':crying face:', '😢'); + Smilies::add($b, ':loudly crying face:', '😭'); + Smilies::add($b, ':face screaming in fear:', '😱'); + Smilies::add($b, ':confounded face:', '😖'); + Smilies::add($b, ':persevering face:', '😣'); + Smilies::add($b, ':disappointed face:', '😞'); // face-negative - Smilies::add($b, ':face with steam from nose:', '😤'); - Smilies::add($b, ':pouting face:', '😡'); - Smilies::add($b, ':angry face:', '😠'); - Smilies::add($b, ':face with symbols on mouth:', '🤬'); - Smilies::add($b, ':smiling face with horns:', '😈'); - Smilies::add($b, ':angry face with horns:', '👿'); - Smilies::add($b, ':skull:', '💀'); - Smilies::add($b, ':skull and crossbones:', '☠'); + Smilies::add($b, ':face with steam from nose:', '😤'); + Smilies::add($b, ':pouting face:', '😡'); + Smilies::add($b, ':angry face:', '😠'); + Smilies::add($b, ':face with symbols on mouth:', '🤬'); + Smilies::add($b, ':smiling face with horns:', '😈'); + Smilies::add($b, ':angry face with horns:', '👿'); + Smilies::add($b, ':skull:', '💀'); + Smilies::add($b, ':skull and crossbones:', '☠'); // face-costume - Smilies::add($b, ':pile of poo:', '💩'); - Smilies::add($b, ':clown face:', '🤡'); - Smilies::add($b, ':ogre:', '👹'); - Smilies::add($b, ':goblin:', '👺'); - Smilies::add($b, ':ghost:', '👻'); - Smilies::add($b, ':alien:', '👽'); - Smilies::add($b, ':alien monster:', '👾'); - Smilies::add($b, ':robot:', '🤖'); + Smilies::add($b, ':pile of poo:', '💩'); + Smilies::add($b, ':clown face:', '🤡'); + Smilies::add($b, ':ogre:', '👹'); + Smilies::add($b, ':goblin:', '👺'); + Smilies::add($b, ':ghost:', '👻'); + Smilies::add($b, ':alien:', '👽'); + Smilies::add($b, ':alien monster:', '👾'); + Smilies::add($b, ':robot:', '🤖'); // cat-face - Smilies::add($b, ':grinning cat:', '😺'); - Smilies::add($b, ':grinning cat with smiling eyes:', '😸'); - Smilies::add($b, ':cat with tears of joy:', '😹'); - Smilies::add($b, ':smiling cat with heart-eyes:', '😻'); - Smilies::add($b, ':cat with wry smile:', '😼'); - Smilies::add($b, ':kissing cat:', '😽'); - Smilies::add($b, ':weary cat:', '🙀'); - Smilies::add($b, ':crying cat:', '😿'); - Smilies::add($b, ':pouting cat:', '😾'); + Smilies::add($b, ':grinning cat:', '😺'); + Smilies::add($b, ':grinning cat with smiling eyes:', '😸'); + Smilies::add($b, ':cat with tears of joy:', '😹'); + Smilies::add($b, ':smiling cat with heart-eyes:', '😻'); + Smilies::add($b, ':cat with wry smile:', '😼'); + Smilies::add($b, ':kissing cat:', '😽'); + Smilies::add($b, ':weary cat:', '🙀'); + Smilies::add($b, ':crying cat:', '😿'); + Smilies::add($b, ':pouting cat:', '😾'); // monkey-face - Smilies::add($b, ':see-no-evil monkey:', '🙈'); - Smilies::add($b, ':hear-no-evil monkey:', '🙉'); - Smilies::add($b, ':speak-no-evil monkey:', '🙊'); + Smilies::add($b, ':see-no-evil monkey:', '🙈'); + Smilies::add($b, ':hear-no-evil monkey:', '🙉'); + Smilies::add($b, ':speak-no-evil monkey:', '🙊'); //emotion - Smilies::add($b, ':kiss mark:', '💋'); - Smilies::add($b, ':love letter:', '💌'); - Smilies::add($b, ':heart with arrow:', '💘'); - Smilies::add($b, ':heart with ribbon:', '💝'); - Smilies::add($b, ':sparkling heart:', '💖'); - Smilies::add($b, ':loveheart:', '💖'); - Smilies::add($b, ':growing heart:', '💗'); - Smilies::add($b, ':beating heart:', '💓'); - Smilies::add($b, ':revolving hearts:', '💞'); - Smilies::add($b, ':two hearts:', '💕'); - Smilies::add($b, ':heart decoration:', '💟'); - Smilies::add($b, ':heart exclamation:', '❣'); - Smilies::add($b, ':broken heart:', '💔'); - Smilies::add($b, ':red heart:', '❤'); - Smilies::add($b, ':orange heart:', '🧡'); - Smilies::add($b, ':yellow heart:', '💛'); - Smilies::add($b, ':green heart:', '💚'); - Smilies::add($b, ':blue heart:', '💙'); - Smilies::add($b, ':purple heart:', '💜'); - Smilies::add($b, ':brown heart:', '🤎'); - Smilies::add($b, ':black heart:', '🖤'); - Smilies::add($b, ':white heart:', '🤍'); - Smilies::add($b, ':hundred points:', '💯'); - Smilies::add($b, ':anger symbol:', '💢'); - Smilies::add($b, ':collision:', '💥'); - Smilies::add($b, ':dizzy:', '💫'); - Smilies::add($b, ':sweat droplets:', '💦'); - Smilies::add($b, ':dashing away:', '💨'); - Smilies::add($b, ':hole:', '🕳'); - Smilies::add($b, ':bomb:', '💣'); - Smilies::add($b, ':speech balloon:', '💬'); - Smilies::add($b, ':left speech bubble:', '🗨'); - Smilies::add($b, ':right anger bubble:', '🗯'); - Smilies::add($b, ':thought balloon:', '💭'); - Smilies::add($b, ':zzz:', '💤'); + Smilies::add($b, ':kiss mark:', '💋'); + Smilies::add($b, ':love letter:', '💌'); + Smilies::add($b, ':heart with arrow:', '💘'); + Smilies::add($b, ':heart with ribbon:', '💝'); + Smilies::add($b, ':sparkling heart:', '💖'); + Smilies::add($b, ':loveheart:', '💖'); + Smilies::add($b, ':growing heart:', '💗'); + Smilies::add($b, ':beating heart:', '💓'); + Smilies::add($b, ':revolving hearts:', '💞'); + Smilies::add($b, ':two hearts:', '💕'); + Smilies::add($b, ':heart decoration:', '💟'); + Smilies::add($b, ':heart exclamation:', '❣'); + Smilies::add($b, ':broken heart:', '💔'); + Smilies::add($b, ':red heart:', '❤'); + Smilies::add($b, ':orange heart:', '🧡'); + Smilies::add($b, ':yellow heart:', '💛'); + Smilies::add($b, ':green heart:', '💚'); + Smilies::add($b, ':blue heart:', '💙'); + Smilies::add($b, ':purple heart:', '💜'); + Smilies::add($b, ':brown heart:', '🤎'); + Smilies::add($b, ':black heart:', '🖤'); + Smilies::add($b, ':white heart:', '🤍'); + Smilies::add($b, ':hundred points:', '💯'); + Smilies::add($b, ':anger symbol:', '💢'); + Smilies::add($b, ':collision:', '💥'); + Smilies::add($b, ':dizzy:', '💫'); + Smilies::add($b, ':sweat droplets:', '💦'); + Smilies::add($b, ':dashing away:', '💨'); + Smilies::add($b, ':hole:', '🕳'); + Smilies::add($b, ':bomb:', '💣'); + Smilies::add($b, ':speech balloon:', '💬'); + Smilies::add($b, ':left speech bubble:', '🗨'); + Smilies::add($b, ':right anger bubble:', '🗯'); + Smilies::add($b, ':thought balloon:', '💭'); + Smilies::add($b, ':zzz:', '💤'); // People & Body // hand-fingers-open - Smilies::add($b, ':waving hand:', '👋'); - Smilies::add($b, ':raised back of hand:', '🤚'); - Smilies::add($b, ':hand with fingers splayed:', '🖐'); - Smilies::add($b, ':raised hand:', '✋'); - Smilies::add($b, ':vulcan salute:', '🖖'); + Smilies::add($b, ':waving hand:', '👋'); + Smilies::add($b, ':raised back of hand:', '🤚'); + Smilies::add($b, ':hand with fingers splayed:', '🖐'); + Smilies::add($b, ':raised hand:', '✋'); + Smilies::add($b, ':vulcan salute:', '🖖'); // hand-fingers-partial - Smilies::add($b, ':OK hand:', '👌'); -// Smilies::add($b, ':pinching hand:', '🤏'); - Smilies::add($b, ':victory hand:', '✌'); - Smilies::add($b, ':crossed fingers:', '🤞'); - Smilies::add($b, ':love-you gesture:', '🤟'); - Smilies::add($b, ':sign of the horns:', '🤘'); - Smilies::add($b, ':call me hand:', '🤙'); + Smilies::add($b, ':OK hand:', '👌'); + Smilies::add($b, ':victory hand:', '✌'); + Smilies::add($b, ':crossed fingers:', '🤞'); + Smilies::add($b, ':love-you gesture:', '🤟'); + Smilies::add($b, ':sign of the horns:', '🤘'); + Smilies::add($b, ':call me hand:', '🤙'); // hand-single-finger - Smilies::add($b, ':backhand index pointing left:', '👈'); - Smilies::add($b, ':backhand index pointing right:', '👉'); - Smilies::add($b, ':backhand index pointing up:', '👆'); - Smilies::add($b, ':middle finger:', '🖕'); - Smilies::add($b, ':backhand index pointing down:', '👇'); - Smilies::add($b, ':index pointing up:', '☝'); + Smilies::add($b, ':backhand index pointing left:', '👈'); + Smilies::add($b, ':backhand index pointing right:', '👉'); + Smilies::add($b, ':backhand index pointing up:', '👆'); + Smilies::add($b, ':middle finger:', '🖕'); + Smilies::add($b, ':backhand index pointing down:', '👇'); + Smilies::add($b, ':index pointing up:', '☝'); // hand-fingers-closed - Smilies::add($b, ':thumbs up:', '👍'); + Smilies::add($b, ':thumbs up:', '👍'); Smilies::add($b, ':like:', '👍'); Smilies::add($b, '\\o/', '👍'); - Smilies::add($b, ':thumbs down:', '👎'); + Smilies::add($b, ':thumbs down:', '👎'); Smilies::add($b, ':dislike:', '👎'); - Smilies::add($b, ':raised fist:', '✊'); - Smilies::add($b, ':oncoming fist:', '👊'); - Smilies::add($b, ':left-facing fist:', '🤛'); - Smilies::add($b, ':right-facing fist:', '🤜'); + Smilies::add($b, ':raised fist:', '✊'); + Smilies::add($b, ':oncoming fist:', '👊'); + Smilies::add($b, ':left-facing fist:', '🤛'); + Smilies::add($b, ':right-facing fist:', '🤜'); // hands - Smilies::add($b, ':clapping hands:', '👏'); - Smilies::add($b, ':raising hands:', '🙌'); - Smilies::add($b, ':open hands:', '👐'); - Smilies::add($b, ':palms up together:', '🤲'); - Smilies::add($b, ':handshake:', '🤝'); - Smilies::add($b, ':folded hands:', '🙏'); + Smilies::add($b, ':clapping hands:', '👏'); + Smilies::add($b, ':raising hands:', '🙌'); + Smilies::add($b, ':open hands:', '👐'); + Smilies::add($b, ':palms up together:', '🤲'); + Smilies::add($b, ':handshake:', '🤝'); + Smilies::add($b, ':folded hands:', '🙏'); // hand-prop - Smilies::add($b, ':writing hand:', '✍'); - Smilies::add($b, ':nail polish:', '💅'); - Smilies::add($b, ':selfie:', '🤳'); + Smilies::add($b, ':writing hand:', '✍'); + Smilies::add($b, ':nail polish:', '💅'); + Smilies::add($b, ':selfie:', '🤳'); // body-parts - Smilies::add($b, ':flexed biceps:', '💪'); - Smilies::add($b, ':mechanical arm:', '🦾'); - Smilies::add($b, ':mechanical leg:', '🦿'); - Smilies::add($b, ':leg:', '🦵'); - Smilies::add($b, ':foot:', '🦶'); - Smilies::add($b, ':ear:', '👂'); -// Smilies::add($b, ':ear with hearing aid:', '🦻'); - Smilies::add($b, ':nose:', '👃'); - Smilies::add($b, ':brain:', '🧠'); - Smilies::add($b, ':tooth:', '🦷'); - Smilies::add($b, ':bone:', '🦴'); - Smilies::add($b, ':eyes:', '👀'); - Smilies::add($b, ':eye:', '👁'); - Smilies::add($b, ':tongue:', '👅'); - Smilies::add($b, ':mouth:', '👄'); + Smilies::add($b, ':flexed biceps:', '💪'); + Smilies::add($b, ':mechanical arm:', '🦾'); + Smilies::add($b, ':mechanical leg:', '🦿'); + Smilies::add($b, ':leg:', '🦵'); + Smilies::add($b, ':foot:', '🦶'); + Smilies::add($b, ':ear:', '👂'); + Smilies::add($b, ':brain:', '🧠'); + Smilies::add($b, ':tooth:', '🦷'); + Smilies::add($b, ':bone:', '🦴'); + Smilies::add($b, ':eyes:', '👀'); + Smilies::add($b, ':eye:', '👁'); + Smilies::add($b, ':tongue:', '👅'); + Smilies::add($b, ':mouth:', '👄'); // person - Smilies::add($b, ':baby:', '👶'); - Smilies::add($b, ':child:', '🧒'); - Smilies::add($b, ':boy:', '👦'); - Smilies::add($b, ':girl:', '👧'); - Smilies::add($b, ':person:', '🧑'); - Smilies::add($b, ':person: blond hair:', '👱'); - Smilies::add($b, ':man:', '👨'); - Smilies::add($b, ':man: beard:', '🧔'); + Smilies::add($b, ':baby:', '👶'); + Smilies::add($b, ':child:', '🧒'); + Smilies::add($b, ':boy:', '👦'); + Smilies::add($b, ':girl:', '👧'); + Smilies::add($b, ':person:', '🧑'); + Smilies::add($b, ':person: blond hair:', '👱'); + Smilies::add($b, ':man:', '👨'); + Smilies::add($b, ':man: beard:', '🧔'); Smilies::add($b, ':beard:', '🧔'); - Smilies::add($b, ':man: red hair:', '👨‍🦰'); - Smilies::add($b, ':man: curly hair:', '👨‍🦱'); - Smilies::add($b, ':man: white hair:', '👨‍🦳'); - Smilies::add($b, ':man: bald:', '👨‍🦲'); - Smilies::add($b, ':woman:', '👩'); - Smilies::add($b, ':woman: red hair:', '👩‍🦰'); - Smilies::add($b, ':person: red hair:', '🧑‍🦰'); - Smilies::add($b, ':woman: curly hair:', '👩‍🦱'); - Smilies::add($b, ':person: curly hair:', '🧑‍🦱'); - Smilies::add($b, ':woman: white hair:', '👩‍🦳'); - Smilies::add($b, ':person: white hair:', '🧑‍🦳'); - Smilies::add($b, ':woman: bald:', '👩‍🦲'); - Smilies::add($b, ':bald::', '🧑‍🦲'); - Smilies::add($b, ':woman: blond hair:', '👱‍♀️'); - Smilies::add($b, ':man: blond hair:', '👱‍♂️'); - Smilies::add($b, ':older person:', '🧓'); - Smilies::add($b, ':old man:', '👴'); - Smilies::add($b, ':old woman:', '👵'); + Smilies::add($b, ':man: red hair:', '👨‍🦰'); + Smilies::add($b, ':man: curly hair:', '👨‍🦱'); + Smilies::add($b, ':man: white hair:', '👨‍🦳'); + Smilies::add($b, ':man: bald:', '👨‍🦲'); + Smilies::add($b, ':woman:', '👩'); + Smilies::add($b, ':woman: red hair:', '👩‍🦰'); + Smilies::add($b, ':person: red hair:', '🧑‍🦰'); + Smilies::add($b, ':woman: curly hair:', '👩‍🦱'); + Smilies::add($b, ':person: curly hair:', '🧑‍🦱'); + Smilies::add($b, ':woman: white hair:', '👩‍🦳'); + Smilies::add($b, ':person: white hair:', '🧑‍🦳'); + Smilies::add($b, ':woman: bald:', '👩‍🦲'); + Smilies::add($b, ':bald::', '🧑‍🦲'); + Smilies::add($b, ':woman: blond hair:', '👱‍♀️'); + Smilies::add($b, ':man: blond hair:', '👱‍♂️'); + Smilies::add($b, ':older person:', '🧓'); + Smilies::add($b, ':old man:', '👴'); + Smilies::add($b, ':old woman:', '👵'); Smilies::add($b, ':pregnant:', '🤰'); // person-gesture - Smilies::add($b, ':person frowning:', '🙍'); - Smilies::add($b, ':man frowning:', '🙍‍♂️'); - Smilies::add($b, ':woman frowning:', '🙍‍♀️'); - Smilies::add($b, ':person pouting:', '🙎'); - Smilies::add($b, ':man pouting:', '🙎‍♂️'); - Smilies::add($b, ':woman pouting:', '🙎‍♀️'); - Smilies::add($b, ':person gesturing NO:', '🙅'); - Smilies::add($b, ':man gesturing NO:', '🙅‍♂️'); - Smilies::add($b, ':woman gesturing NO:', '🙅‍♀️'); - Smilies::add($b, ':person gesturing OK:', '🙆'); - Smilies::add($b, ':man gesturing OK:', '🙆‍♂️'); - Smilies::add($b, ':woman gesturing OK:', '🙆‍♀️'); - Smilies::add($b, ':person tipping hand:', '💁'); - Smilies::add($b, ':man tipping hand:', '💁‍♂️'); - Smilies::add($b, ':woman tipping hand:', '💁‍♀️'); - Smilies::add($b, ':person raising hand:', '🙋'); - Smilies::add($b, ':man raising hand:', '🙋‍♂️'); - Smilies::add($b, ':woman raising hand', '🙋‍♀️'); -// Smilies::add($b, ':deaf person:', '🧏'); -// Smilies::add($b, ':deaf man:', '🧏‍♂️'); -// Smilies::add($b, ':deaf woman:', '🧏‍♀️'); - Smilies::add($b, ':person bowing:', '🙇'); + Smilies::add($b, ':person frowning:', '🙍'); + Smilies::add($b, ':man frowning:', '🙍‍♂️'); + Smilies::add($b, ':woman frowning:', '🙍‍♀️'); + Smilies::add($b, ':person pouting:', '🙎'); + Smilies::add($b, ':man pouting:', '🙎‍♂️'); + Smilies::add($b, ':woman pouting:', '🙎‍♀️'); + Smilies::add($b, ':person gesturing NO:', '🙅'); + Smilies::add($b, ':man gesturing NO:', '🙅‍♂️'); + Smilies::add($b, ':woman gesturing NO:', '🙅‍♀️'); + Smilies::add($b, ':person gesturing OK:', '🙆'); + Smilies::add($b, ':man gesturing OK:', '🙆‍♂️'); + Smilies::add($b, ':woman gesturing OK:', '🙆‍♀️'); + Smilies::add($b, ':person tipping hand:', '💁'); + Smilies::add($b, ':man tipping hand:', '💁‍♂️'); + Smilies::add($b, ':woman tipping hand:', '💁‍♀️'); + Smilies::add($b, ':person raising hand:', '🙋'); + Smilies::add($b, ':man raising hand:', '🙋‍♂️'); + Smilies::add($b, ':woman raising hand', '🙋‍♀️'); +// Smilies::add($b, ':deaf person:', '🧏'); +// Smilies::add($b, ':deaf man:', '🧏‍♂️'); +// Smilies::add($b, ':deaf woman:', '🧏‍♀️'); + Smilies::add($b, ':person bowing:', '🙇'); Smilies::add($b, ':bow:', '🙇'); - Smilies::add($b, ':man bowing:', '🙇‍♂️'); - Smilies::add($b, ':woman bowing:', '🙇‍♀️'); - Smilies::add($b, ':person facepalming:', '🤦'); + Smilies::add($b, ':man bowing:', '🙇‍♂️'); + Smilies::add($b, ':woman bowing:', '🙇‍♀️'); + Smilies::add($b, ':person facepalming:', '🤦'); Smilies::add($b, ':facepalm:', '🤦'); - Smilies::add($b, ':man facepalming:', '🤦‍♂️'); - Smilies::add($b, ':woman facepalming:', '🤦‍♀️'); - Smilies::add($b, ':person shrugging:', '🤷'); + Smilies::add($b, ':man facepalming:', '🤦‍♂️'); + Smilies::add($b, ':woman facepalming:', '🤦‍♀️'); + Smilies::add($b, ':person shrugging:', '🤷'); Smilies::add($b, ':shrug:', '🤷'); - Smilies::add($b, ':man shrugging:', '🤷‍♂️'); - Smilies::add($b, ':woman shrugging:', '🤷‍♀️'); + Smilies::add($b, ':man shrugging:', '🤷‍♂️'); + Smilies::add($b, ':woman shrugging:', '🤷‍♀️'); // person-role // person-fantasy - Smilies::add($b, ':baby angel:', '👼'); + Smilies::add($b, ':baby angel:', '👼'); Smilies::add($b, ':angel:', '👼'); Smilies::add($b, ':cherub:', '👼'); - Smilies::add($b, ':Santa Claus:', '🎅'); - Smilies::add($b, ':Mrs. Claus:', '🤶'); - Smilies::add($b, ':superhero:', '🦸'); - Smilies::add($b, ':man superhero:', '🦸‍♂️'); - Smilies::add($b, ':woman superhero:', '🦸‍♀️'); - Smilies::add($b, ':supervillain:', '🦹'); - Smilies::add($b, ':man supervillain:', '🦹‍♂️'); - Smilies::add($b, ':woman supervillain:', '🦹‍♀️'); - Smilies::add($b, ':mage:', '🧙'); - Smilies::add($b, ':man mage:', '🧙‍♂️'); - Smilies::add($b, ':woman mage:', '🧙‍♀️'); - Smilies::add($b, ':fairy:', '🧚'); - Smilies::add($b, ':man fairy:', '🧚‍♂️'); - Smilies::add($b, ':woman fairy:', '🧚‍♀️'); - Smilies::add($b, ':vampire:', '🧛'); - Smilies::add($b, ':man vampire:', '🧛‍♂️'); - Smilies::add($b, ':woman vampire:', '🧛‍♀️'); - Smilies::add($b, ':merperson:', '🧜'); - Smilies::add($b, ':merman:', '🧜‍♂️'); - Smilies::add($b, ':mermaid:', '🧜‍♀️'); - Smilies::add($b, ':elf:', '🧝'); - Smilies::add($b, ':man elf:', '🧝‍♂️'); - Smilies::add($b, ':woman elf:', '🧝‍♀️'); - Smilies::add($b, ':genie:', '🧞'); - Smilies::add($b, ':man genie:', '🧞‍♂️'); - Smilies::add($b, ':woman genie:', '🧞‍♀️'); - Smilies::add($b, ':zombie:', '🧟'); - Smilies::add($b, ':man zombie:', '🧟‍♂️'); - Smilies::add($b, ':woman zombie:', '🧟‍♀️'); + Smilies::add($b, ':Santa Claus:', '🎅'); + Smilies::add($b, ':Mrs. Claus:', '🤶'); + Smilies::add($b, ':superhero:', '🦸'); + Smilies::add($b, ':man superhero:', '🦸‍♂️'); + Smilies::add($b, ':woman superhero:', '🦸‍♀️'); + Smilies::add($b, ':supervillain:', '🦹'); + Smilies::add($b, ':man supervillain:', '🦹‍♂️'); + Smilies::add($b, ':woman supervillain:', '🦹‍♀️'); + Smilies::add($b, ':mage:', '🧙'); + Smilies::add($b, ':man mage:', '🧙‍♂️'); + Smilies::add($b, ':woman mage:', '🧙‍♀️'); + Smilies::add($b, ':fairy:', '🧚'); + Smilies::add($b, ':man fairy:', '🧚‍♂️'); + Smilies::add($b, ':woman fairy:', '🧚‍♀️'); + Smilies::add($b, ':vampire:', '🧛'); + Smilies::add($b, ':man vampire:', '🧛‍♂️'); + Smilies::add($b, ':woman vampire:', '🧛‍♀️'); + Smilies::add($b, ':merperson:', '🧜'); + Smilies::add($b, ':merman:', '🧜‍♂️'); + Smilies::add($b, ':mermaid:', '🧜‍♀️'); + Smilies::add($b, ':elf:', '🧝'); + Smilies::add($b, ':man elf:', '🧝‍♂️'); + Smilies::add($b, ':woman elf:', '🧝‍♀️'); + Smilies::add($b, ':genie:', '🧞'); + Smilies::add($b, ':man genie:', '🧞‍♂️'); + Smilies::add($b, ':woman genie:', '🧞‍♀️'); + Smilies::add($b, ':zombie:', '🧟'); + Smilies::add($b, ':man zombie:', '🧟‍♂️'); + Smilies::add($b, ':woman zombie:', '🧟‍♀️'); // person-activity @@ -411,83 +407,83 @@ function unicode_smilies_smilies(array &$b) // person-resting // family - Smilies::add($b, ':people holding hands:', '🧑‍🤝‍🧑'); - Smilies::add($b, ':women holding hands:', '👭'); - Smilies::add($b, ':woman and man holding hands:', '👫'); - Smilies::add($b, ':men holding hands:', '👬'); - Smilies::add($b, ':kiss:', '💏'); - Smilies::add($b, ':couple with heart:', '💑'); - Smilies::add($b, ':family:', '👪'); + Smilies::add($b, ':people holding hands:', '🧑‍🤝‍🧑'); + Smilies::add($b, ':women holding hands:', '👭'); + Smilies::add($b, ':woman and man holding hands:', '👫'); + Smilies::add($b, ':men holding hands:', '👬'); + Smilies::add($b, ':kiss:', '💏'); + Smilies::add($b, ':couple with heart:', '💑'); + Smilies::add($b, ':family:', '👪'); // person-symbol - Smilies::add($b, ':speaking head:', '🗣'); - Smilies::add($b, ':bust in silhouette:', '👤'); - Smilies::add($b, ':busts in silhouette:', '👥'); - Smilies::add($b, ':footprints:', '👣'); + Smilies::add($b, ':speaking head:', '🗣'); + Smilies::add($b, ':bust in silhouette:', '👤'); + Smilies::add($b, ':busts in silhouette:', '👥'); + Smilies::add($b, ':footprints:', '👣'); // Component // hair-style // Animals & Nature // animal-mammal - Smilies::add($b, ':monkey face:', '🐵'); - Smilies::add($b, ':monkey:', '🐒'); - Smilies::add($b, ':gorilla:', '🦍'); - Smilies::add($b, ':orangutan:', '🦧'); - Smilies::add($b, ':dog face:', '🐶'); - Smilies::add($b, ':dog:', '🐕'); - Smilies::add($b, ':guide dog:', '🦮'); - Smilies::add($b, ':poodle:', '🐩'); - Smilies::add($b, ':wolf:', '🐺'); - Smilies::add($b, ':fox:', '🦊'); - Smilies::add($b, ':raccoon:', '🦝'); - Smilies::add($b, ':cat face:', '🐱'); - Smilies::add($b, ':cat:', '🐈'); - Smilies::add($b, ':lion:', '🦁'); - Smilies::add($b, ':tiger face:', '🐯'); - Smilies::add($b, ':tiger:', '🐅'); - Smilies::add($b, ':leopard:', '🐆'); - Smilies::add($b, ':horse face:', '🐴'); - Smilies::add($b, ':horse:', '🐎'); - Smilies::add($b, ':unicorn:', '🦄'); - Smilies::add($b, ':zebra:', '🦓'); - Smilies::add($b, ':deer:', '🦌'); - Smilies::add($b, ':cow face:', '🐮'); - Smilies::add($b, ':ox:', '🐂'); - Smilies::add($b, ':water buffalo:', '🐃'); - Smilies::add($b, ':cow:', '🐄'); - Smilies::add($b, ':pig face:', '🐷'); - Smilies::add($b, ':pig:', '🐖'); + Smilies::add($b, ':monkey face:', '🐵'); + Smilies::add($b, ':monkey:', '🐒'); + Smilies::add($b, ':gorilla:', '🦍'); + Smilies::add($b, ':orangutan:', '🦧'); + Smilies::add($b, ':dog face:', '🐶'); + Smilies::add($b, ':dog:', '🐕'); + Smilies::add($b, ':guide dog:', '🦮'); + Smilies::add($b, ':poodle:', '🐩'); + Smilies::add($b, ':wolf:', '🐺'); + Smilies::add($b, ':fox:', '🦊'); + Smilies::add($b, ':raccoon:', '🦝'); + Smilies::add($b, ':cat face:', '🐱'); + Smilies::add($b, ':cat:', '🐈'); + Smilies::add($b, ':lion:', '🦁'); + Smilies::add($b, ':tiger face:', '🐯'); + Smilies::add($b, ':tiger:', '🐅'); + Smilies::add($b, ':leopard:', '🐆'); + Smilies::add($b, ':horse face:', '🐴'); + Smilies::add($b, ':horse:', '🐎'); + Smilies::add($b, ':unicorn:', '🦄'); + Smilies::add($b, ':zebra:', '🦓'); + Smilies::add($b, ':deer:', '🦌'); + Smilies::add($b, ':cow face:', '🐮'); + Smilies::add($b, ':ox:', '🐂'); + Smilies::add($b, ':water buffalo:', '🐃'); + Smilies::add($b, ':cow:', '🐄'); + Smilies::add($b, ':pig face:', '🐷'); + Smilies::add($b, ':pig:', '🐖'); Smilies::add($b, ':boar:', '🐗'); - Smilies::add($b, ':pig nose:', '🐽'); - Smilies::add($b, ':ram:', '🐏'); - Smilies::add($b, ':sheep:', '🐑'); - Smilies::add($b, ':goat:', '🐐'); + Smilies::add($b, ':pig nose:', '🐽'); + Smilies::add($b, ':ram:', '🐏'); + Smilies::add($b, ':sheep:', '🐑'); + Smilies::add($b, ':goat:', '🐐'); Smilies::add($b, ':camel:', '🐪'); - Smilies::add($b, ':two-hump camel:', '🐫'); - Smilies::add($b, ':llama:', '🦙'); - Smilies::add($b, ':giraffe:', '🦒'); - Smilies::add($b, ':elephant:', '🐘'); - Smilies::add($b, ':rhinoceros:', '🦏'); - Smilies::add($b, ':hippopotamus:', '🦛'); - Smilies::add($b, ':mouse face:', '🐭'); - Smilies::add($b, ':mouse:', '🐁'); - Smilies::add($b, ':rat:', '🐀'); - Smilies::add($b, ':hamster:', '🐹'); - Smilies::add($b, ':rabbit face:', '🐰'); - Smilies::add($b, ':rabbit:', '🐇'); - Smilies::add($b, ':chipmunk:', '🐿'); - Smilies::add($b, ':hedgehog:', '🦔'); - Smilies::add($b, ':bat:', '🦇'); - Smilies::add($b, ':bear:', '🐻'); - Smilies::add($b, ':koala:', '🐨'); - Smilies::add($b, ':panda:', '🐼'); - Smilies::add($b, ':sloth:', '🦥'); - Smilies::add($b, ':otter:', '🦦'); - Smilies::add($b, ':skunk:', '🦨'); - Smilies::add($b, ':kangaroo:', '🦘'); - Smilies::add($b, ':badger:', '🦡'); - Smilies::add($b, ':paw prints:', '🐾'); + Smilies::add($b, ':two-hump camel:', '🐫'); + Smilies::add($b, ':llama:', '🦙'); + Smilies::add($b, ':giraffe:', '🦒'); + Smilies::add($b, ':elephant:', '🐘'); + Smilies::add($b, ':rhinoceros:', '🦏'); + Smilies::add($b, ':hippopotamus:', '🦛'); + Smilies::add($b, ':mouse face:', '🐭'); + Smilies::add($b, ':mouse:', '🐁'); + Smilies::add($b, ':rat:', '🐀'); + Smilies::add($b, ':hamster:', '🐹'); + Smilies::add($b, ':rabbit face:', '🐰'); + Smilies::add($b, ':rabbit:', '🐇'); + Smilies::add($b, ':chipmunk:', '🐿'); + Smilies::add($b, ':hedgehog:', '🦔'); + Smilies::add($b, ':bat:', '🦇'); + Smilies::add($b, ':bear:', '🐻'); + Smilies::add($b, ':koala:', '🐨'); + Smilies::add($b, ':panda:', '🐼'); + Smilies::add($b, ':sloth:', '🦥'); + Smilies::add($b, ':otter:', '🦦'); + Smilies::add($b, ':skunk:', '🦨'); + Smilies::add($b, ':kangaroo:', '🦘'); + Smilies::add($b, ':badger:', '🦡'); + Smilies::add($b, ':paw prints:', '🐾'); // Smilies::add($b, ':bunnyflowers:', '&#x;'); Smilies::add($b, ':chick:', '🐤'); Smilies::add($b, ':ladybird:', '🐞'); @@ -495,957 +491,958 @@ function unicode_smilies_smilies(array &$b) // Smilies::add($b, ':dragonfly:', '&#x;'); // animal-bird - Smilies::add($b, ':turkey:', '🦃'); - Smilies::add($b, ':chicken:', '🐔'); - Smilies::add($b, ':rooster:', '🐓'); - Smilies::add($b, ':hatching chick:', '🐣'); - Smilies::add($b, ':baby chick:', '🐤'); - Smilies::add($b, ':front-facing baby chick:', '🐥'); - Smilies::add($b, ':bird:', '🐦'); - Smilies::add($b, ':tux:', '🐧'); - Smilies::add($b, ':dove:', '🕊'); - Smilies::add($b, ':eagle:', '🦅'); - Smilies::add($b, ':duck:', '🦆'); - Smilies::add($b, ':swan:', '🦢'); - Smilies::add($b, ':owl:', '🦉'); - Smilies::add($b, ':flamingo:', '🦩'); - Smilies::add($b, ':peacock:', '🦚'); - Smilies::add($b, ':parrot:', '🦜'); + Smilies::add($b, ':turkey:', '🦃'); + Smilies::add($b, ':chicken:', '🐔'); + Smilies::add($b, ':rooster:', '🐓'); + Smilies::add($b, ':hatching chick:', '🐣'); + Smilies::add($b, ':baby chick:', '🐤'); + Smilies::add($b, ':front-facing baby chick:', '🐥'); + Smilies::add($b, ':bird:', '🐦'); + Smilies::add($b, ':tux:', '🐧'); + Smilies::add($b, ':dove:', '🕊'); + Smilies::add($b, ':eagle:', '🦅'); + Smilies::add($b, ':duck:', '🦆'); + Smilies::add($b, ':swan:', '🦢'); + Smilies::add($b, ':owl:', '🦉'); + Smilies::add($b, ':flamingo:', '🦩'); + Smilies::add($b, ':peacock:', '🦚'); + Smilies::add($b, ':parrot:', '🦜'); // animal-amphibian - Smilies::add($b, ':frog:', '🐸'); + Smilies::add($b, ':frog:', '🐸'); // animal-reptile - Smilies::add($b, ':crocodile:', '🐊'); - Smilies::add($b, ':turtle:', '🐢'); - Smilies::add($b, ':lizard:', '🦎'); - Smilies::add($b, ':snake:', '🐍'); - Smilies::add($b, ':dragon face:', '🐲'); - Smilies::add($b, ':dragon:', '🐉'); + Smilies::add($b, ':crocodile:', '🐊'); + Smilies::add($b, ':turtle:', '🐢'); + Smilies::add($b, ':lizard:', '🦎'); + Smilies::add($b, ':snake:', '🐍'); + Smilies::add($b, ':dragon face:', '🐲'); + Smilies::add($b, ':dragon:', '🐉'); Smilies::add($b, ':draco:', '🐉'); - Smilies::add($b, ':sauropod:', '🦕'); - Smilies::add($b, ':T-Rex:', '🦖'); + Smilies::add($b, ':sauropod:', '🦕'); + Smilies::add($b, ':T-Rex:', '🦖'); // animal-marine - Smilies::add($b, ':spouting whale:', '🐳'); - Smilies::add($b, ':whale:', '🐋'); - Smilies::add($b, ':dolphin:', '🐬'); - Smilies::add($b, ':fish:', '🐟'); - Smilies::add($b, ':tropical fish:', '🐠'); - Smilies::add($b, ':blowfish:', '🐡'); - Smilies::add($b, ':shark:', '🦈'); - Smilies::add($b, ':octopus:', '🐙'); - Smilies::add($b, ':spiral shell:', '🐚'); + Smilies::add($b, ':spouting whale:', '🐳'); + Smilies::add($b, ':whale:', '🐋'); + Smilies::add($b, ':dolphin:', '🐬'); + Smilies::add($b, ':fish:', '🐟'); + Smilies::add($b, ':tropical fish:', '🐠'); + Smilies::add($b, ':blowfish:', '🐡'); + Smilies::add($b, ':shark:', '🦈'); + Smilies::add($b, ':octopus:', '🐙'); + Smilies::add($b, ':spiral shell:', '🐚'); // animal-bug - Smilies::add($b, ':snail:', '🐌'); - Smilies::add($b, ':butterfly:', '🦋'); - Smilies::add($b, ':bug:', '🐛'); - Smilies::add($b, ':ant:', '🐜'); - Smilies::add($b, ':honeybee:', '🐝'); - Smilies::add($b, ':lady beetle:', '🐞'); - Smilies::add($b, ':cricket:', '🦗'); - Smilies::add($b, ':spider:', '🕷'); - Smilies::add($b, ':spider web:', '🕸'); - Smilies::add($b, ':scorpion:', '🦂'); - Smilies::add($b, ':mosquito:', '🦟'); - Smilies::add($b, ':microbe:', '🦠'); + Smilies::add($b, ':snail:', '🐌'); + Smilies::add($b, ':butterfly:', '🦋'); + Smilies::add($b, ':bug:', '🐛'); + Smilies::add($b, ':ant:', '🐜'); + Smilies::add($b, ':honeybee:', '🐝'); + Smilies::add($b, ':lady beetle:', '🐞'); + Smilies::add($b, ':cricket:', '🦗'); + Smilies::add($b, ':spider:', '🕷'); + Smilies::add($b, ':spider web:', '🕸'); + Smilies::add($b, ':scorpion:', '🦂'); + Smilies::add($b, ':mosquito:', '🦟'); + Smilies::add($b, ':microbe:', '🦠'); // plant-flower - Smilies::add($b, ':bouquet:', '💐'); - Smilies::add($b, ':cherry blossom:', '🌸'); - Smilies::add($b, ':white flower:', '💮'); - Smilies::add($b, ':rosette:', '🏵'); - Smilies::add($b, ':rose:', '🌹'); - Smilies::add($b, ':wilted flower:', '🥀'); - Smilies::add($b, ':hibiscus:', '🌺'); - Smilies::add($b, ':sunflower:', '🌻'); - Smilies::add($b, ':blossom:', '🌼'); - Smilies::add($b, ':tulip:', '🌷'); + Smilies::add($b, ':bouquet:', '💐'); + Smilies::add($b, ':cherry blossom:', '🌸'); + Smilies::add($b, ':white flower:', '💮'); + Smilies::add($b, ':rosette:', '🏵'); + Smilies::add($b, ':rose:', '🌹'); + Smilies::add($b, ':wilted flower:', '🥀'); + Smilies::add($b, ':hibiscus:', '🌺'); + Smilies::add($b, ':sunflower:', '🌻'); + Smilies::add($b, ':blossom:', '🌼'); + Smilies::add($b, ':tulip:', '🌷'); // plant-other - Smilies::add($b, ':seedling:', '🌱'); - Smilies::add($b, ':evergreen tree:', '🌲'); - Smilies::add($b, ':deciduous tree:', '🌳'); - Smilies::add($b, ':palm tree:', '🌴'); - Smilies::add($b, ':cactus:', '🌵'); - Smilies::add($b, ':sheaf of rice:', '🌾'); - Smilies::add($b, ':herb:', '🌿'); - Smilies::add($b, ':shamrock:', '☘'); - Smilies::add($b, ':four leaf clover:', '🍀'); - Smilies::add($b, ':maple leaf:', '🍁'); - Smilies::add($b, ':fallen leaf:', '🍂'); - Smilies::add($b, ':leaf fluttering in wind:', '🍃'); + Smilies::add($b, ':seedling:', '🌱'); + Smilies::add($b, ':evergreen tree:', '🌲'); + Smilies::add($b, ':deciduous tree:', '🌳'); + Smilies::add($b, ':palm tree:', '🌴'); + Smilies::add($b, ':cactus:', '🌵'); + Smilies::add($b, ':sheaf of rice:', '🌾'); + Smilies::add($b, ':herb:', '🌿'); + Smilies::add($b, ':shamrock:', '☘'); + Smilies::add($b, ':four leaf clover:', '🍀'); + Smilies::add($b, ':maple leaf:', '🍁'); + Smilies::add($b, ':fallen leaf:', '🍂'); + Smilies::add($b, ':leaf fluttering in wind:', '🍃'); // Food & Drink // food-fruit - Smilies::add($b, ':grapes:', '🍇'); - Smilies::add($b, ':melon:', '🍈'); - Smilies::add($b, ':watermelon:', '🍉'); - Smilies::add($b, ':tangerine:', '🍊'); - Smilies::add($b, ':lemon:', '🍋'); - Smilies::add($b, ':banana:', '🍌'); - Smilies::add($b, ':pineapple:', '🍍'); - Smilies::add($b, ':mango:', '🥭'); - Smilies::add($b, ':red apple:', '🍎'); + Smilies::add($b, ':grapes:', '🍇'); + Smilies::add($b, ':melon:', '🍈'); + Smilies::add($b, ':watermelon:', '🍉'); + Smilies::add($b, ':tangerine:', '🍊'); + Smilies::add($b, ':lemon:', '🍋'); + Smilies::add($b, ':banana:', '🍌'); + Smilies::add($b, ':pineapple:', '🍍'); + Smilies::add($b, ':mango:', '🥭'); + Smilies::add($b, ':red apple:', '🍎'); Smilies::add($b, ':apple:', '🍎'); - Smilies::add($b, ':green apple:', '🍏'); - Smilies::add($b, ':pear:', '🍐'); - Smilies::add($b, ':peach:', '🍑'); - Smilies::add($b, ':cherries:', '🍒'); - Smilies::add($b, ':strawberry:', '🍓'); - Smilies::add($b, ':kiwi fruit:', '🥝'); - Smilies::add($b, ':tomato:', '🍅'); - Smilies::add($b, ':coconut:', '🥥'); + Smilies::add($b, ':green apple:', '🍏'); + Smilies::add($b, ':pear:', '🍐'); + Smilies::add($b, ':peach:', '🍑'); + Smilies::add($b, ':cherries:', '🍒'); + Smilies::add($b, ':strawberry:', '🍓'); + Smilies::add($b, ':kiwi fruit:', '🥝'); + Smilies::add($b, ':tomato:', '🍅'); + Smilies::add($b, ':coconut:', '🥥'); // food-vegetable - Smilies::add($b, ':avocado:', '🥑'); - Smilies::add($b, ':eggplant:', '🍆'); - Smilies::add($b, ':potato:', '🥔'); - Smilies::add($b, ':carrot:', '🥕'); - Smilies::add($b, ':ear of corn:', '🌽'); - Smilies::add($b, ':hot pepper:', '🌶'); - Smilies::add($b, ':cucumber:', '🥒'); - Smilies::add($b, ':leafy green:', '🥬'); - Smilies::add($b, ':broccoli:', '🥦'); - Smilies::add($b, ':garlic:', '🧄'); - Smilies::add($b, ':onion:', '🧅'); - Smilies::add($b, ':mushroom:', '🍄'); - Smilies::add($b, ':peanuts:', '🥜'); - Smilies::add($b, ':chestnut:', '🌰'); + Smilies::add($b, ':avocado:', '🥑'); + Smilies::add($b, ':eggplant:', '🍆'); + Smilies::add($b, ':potato:', '🥔'); + Smilies::add($b, ':carrot:', '🥕'); + Smilies::add($b, ':ear of corn:', '🌽'); + Smilies::add($b, ':hot pepper:', '🌶'); + Smilies::add($b, ':cucumber:', '🥒'); + Smilies::add($b, ':leafy green:', '🥬'); + Smilies::add($b, ':broccoli:', '🥦'); + Smilies::add($b, ':garlic:', '🧄'); + Smilies::add($b, ':onion:', '🧅'); + Smilies::add($b, ':mushroom:', '🍄'); + Smilies::add($b, ':peanuts:', '🥜'); + Smilies::add($b, ':chestnut:', '🌰'); // food-prepared - Smilies::add($b, ':bread:', '🍞'); - Smilies::add($b, ':croissant:', '🥐'); - Smilies::add($b, ':baguette bread:', '🥖'); - Smilies::add($b, ':pretzel:', '🥨'); - Smilies::add($b, ':bagel:', '🥯'); - Smilies::add($b, ':pancakes:', '🥞'); - Smilies::add($b, ':waffle:', '🧇'); - Smilies::add($b, ':cheese wedge:', '🧀'); - Smilies::add($b, ':meat on bone:', '🍖'); - Smilies::add($b, ':poultry leg:', '🍗'); - Smilies::add($b, ':cut of meat:', '🥩'); - Smilies::add($b, ':bacon:', '🥓'); - Smilies::add($b, ':hamburger:', '🍔'); - Smilies::add($b, ':french fries:', '🍟'); - Smilies::add($b, ':pizza:', '🍕'); - Smilies::add($b, ':hot dog:', '🌭'); - Smilies::add($b, ':sandwich:', '🥪'); - Smilies::add($b, ':taco:', '🌮'); - Smilies::add($b, ':burrito:', '🌯'); - Smilies::add($b, ':stuffed flatbread:', '🥙'); - Smilies::add($b, ':falafel:', '🧆'); - Smilies::add($b, ':egg:', '🥚'); - Smilies::add($b, ':cooking:', '🍳'); + Smilies::add($b, ':bread:', '🍞'); + Smilies::add($b, ':croissant:', '🥐'); + Smilies::add($b, ':baguette bread:', '🥖'); + Smilies::add($b, ':pretzel:', '🥨'); + Smilies::add($b, ':bagel:', '🥯'); + Smilies::add($b, ':pancakes:', '🥞'); + Smilies::add($b, ':waffle:', '🧇'); + Smilies::add($b, ':cheese wedge:', '🧀'); + Smilies::add($b, ':meat on bone:', '🍖'); + Smilies::add($b, ':poultry leg:', '🍗'); + Smilies::add($b, ':cut of meat:', '🥩'); + Smilies::add($b, ':bacon:', '🥓'); + Smilies::add($b, ':hamburger:', '🍔'); + Smilies::add($b, ':french fries:', '🍟'); + Smilies::add($b, ':pizza:', '🍕'); + Smilies::add($b, ':hot dog:', '🌭'); + Smilies::add($b, ':sandwich:', '🥪'); + Smilies::add($b, ':taco:', '🌮'); + Smilies::add($b, ':burrito:', '🌯'); + Smilies::add($b, ':stuffed flatbread:', '🥙'); + Smilies::add($b, ':falafel:', '🧆'); + Smilies::add($b, ':egg:', '🥚'); + Smilies::add($b, ':cooking:', '🍳'); Smilies::add($b, ':fryegg:', '🍳'); - Smilies::add($b, ':shallow pan of food:', '🥘'); - Smilies::add($b, ':pot of food:', '🍲'); - Smilies::add($b, ':bowl with spoon:', '🥣'); - Smilies::add($b, ':green salad:', '🥗'); - Smilies::add($b, ':popcorn:', '🍿'); - Smilies::add($b, ':butter:', '🧈'); - Smilies::add($b, ':salt:', '🧂'); - Smilies::add($b, ':canned food:', '🥫'); + Smilies::add($b, ':shallow pan of food:', '🥘'); + Smilies::add($b, ':pot of food:', '🍲'); + Smilies::add($b, ':bowl with spoon:', '🥣'); + Smilies::add($b, ':green salad:', '🥗'); + Smilies::add($b, ':popcorn:', '🍿'); + Smilies::add($b, ':butter:', '🧈'); + Smilies::add($b, ':salt:', '🧂'); + Smilies::add($b, ':canned food:', '🥫'); // food-asian - Smilies::add($b, ':bento box:', '🍱'); - Smilies::add($b, ':rice cracker:', '🍘'); - Smilies::add($b, ':rice ball:', '🍙'); - Smilies::add($b, ':cooked rice:', '🍚'); - Smilies::add($b, ':curry rice:', '🍛'); - Smilies::add($b, ':steaming bowl:', '🍜'); - Smilies::add($b, ':spaghetti:', '🍝'); - Smilies::add($b, ':roasted sweet potato:', '🍠'); - Smilies::add($b, ':oden:', '🍢'); - Smilies::add($b, ':sushi:', '🍣'); - Smilies::add($b, ':fried shrimp:', '🍤'); - Smilies::add($b, ':fish cake with swirl:', '🍥'); - Smilies::add($b, ':moon cake:', '🥮'); - Smilies::add($b, ':dango:', '🍡'); - Smilies::add($b, ':dumpling:', '🥟'); - Smilies::add($b, ':fortune cookie:', '🥠'); - Smilies::add($b, ':takeout box:', '🥡'); + Smilies::add($b, ':bento box:', '🍱'); + Smilies::add($b, ':rice cracker:', '🍘'); + Smilies::add($b, ':rice ball:', '🍙'); + Smilies::add($b, ':cooked rice:', '🍚'); + Smilies::add($b, ':curry rice:', '🍛'); + Smilies::add($b, ':steaming bowl:', '🍜'); + Smilies::add($b, ':spaghetti:', '🍝'); + Smilies::add($b, ':roasted sweet potato:', '🍠'); + Smilies::add($b, ':oden:', '🍢'); + Smilies::add($b, ':sushi:', '🍣'); + Smilies::add($b, ':fried shrimp:', '🍤'); + Smilies::add($b, ':fish cake with swirl:', '🍥'); + Smilies::add($b, ':moon cake:', '🥮'); + Smilies::add($b, ':dango:', '🍡'); + Smilies::add($b, ':dumpling:', '🥟'); + Smilies::add($b, ':fortune cookie:', '🥠'); + Smilies::add($b, ':takeout box:', '🥡'); // food-marine - Smilies::add($b, ':crab:', '🦀'); - Smilies::add($b, ':lobster:', '🦞'); - Smilies::add($b, ':shrimp:', '🦐'); - Smilies::add($b, ':squid:', '🦑'); -// Smilies::add($b, ':oyster:', '🦪'); + Smilies::add($b, ':crab:', '🦀'); + Smilies::add($b, ':lobster:', '🦞'); + Smilies::add($b, ':shrimp:', '🦐'); + Smilies::add($b, ':squid:', '🦑'); +// Smilies::add($b, ':oyster:', '🦪'); // food-sweet - Smilies::add($b, ':soft ice cream:', '🍦'); - Smilies::add($b, ':shaved ice:', '🍧'); - Smilies::add($b, ':ice cream:', '🍨'); - Smilies::add($b, ':doughnut:', '🍩'); - Smilies::add($b, ':cookie:', '🍪'); - Smilies::add($b, ':birthday cake:', '🎂'); - Smilies::add($b, ':shortcake:', '🍰'); + Smilies::add($b, ':soft ice cream:', '🍦'); + Smilies::add($b, ':shaved ice:', '🍧'); + Smilies::add($b, ':ice cream:', '🍨'); + Smilies::add($b, ':doughnut:', '🍩'); + Smilies::add($b, ':cookie:', '🍪'); + Smilies::add($b, ':birthday cake:', '🎂'); + Smilies::add($b, ':shortcake:', '🍰'); Smilies::add($b, ':cake:', '🍰'); - Smilies::add($b, ':cupcake:', '🧁'); - Smilies::add($b, ':pie:', '🥧'); - Smilies::add($b, ':chocolate bar:', '🍫'); - Smilies::add($b, ':candy:', '🍬'); - Smilies::add($b, ':lollipop:', '🍭'); - Smilies::add($b, ':custard:', '🍮'); - Smilies::add($b, ':honey pot:', '🍯'); + Smilies::add($b, ':cupcake:', '🧁'); + Smilies::add($b, ':pie:', '🥧'); + Smilies::add($b, ':chocolate bar:', '🍫'); + Smilies::add($b, ':candy:', '🍬'); + Smilies::add($b, ':lollipop:', '🍭'); + Smilies::add($b, ':custard:', '🍮'); + Smilies::add($b, ':honey pot:', '🍯'); -// drink - Smilies::add($b, ':baby bottle:', '🍼'); - Smilies::add($b, ':glass of milk:', '🥛'); - Smilies::add($b, ':hot beverage:', '☕'); +// drink + Smilies::add($b, ':baby bottle:', '🍼'); + Smilies::add($b, ':glass of milk:', '🥛'); + Smilies::add($b, ':hot beverage:', '☕'); Smilies::add($b, ':coffee:', '☕'); Smilies::add($b, ':tea:', '☕'); Smilies::add($b, ':tee:', '☕'); - Smilies::add($b, ':teacup without handle:', '🍵'); - Smilies::add($b, ':sake:', '🍶'); - Smilies::add($b, ':bottle with popping cork:', '🍾'); - Smilies::add($b, ':wine glass:', '🍷'); - Smilies::add($b, ':cocktail glass:', '🍸'); - Smilies::add($b, ':tropical drink:', '🍹'); - Smilies::add($b, ':beer mug:', '🍺'); + Smilies::add($b, ':teacup without handle:', '🍵'); + Smilies::add($b, ':sake:', '🍶'); + Smilies::add($b, ':bottle with popping cork:', '🍾'); + Smilies::add($b, ':wine glass:', '🍷'); + Smilies::add($b, ':cocktail glass:', '🍸'); + Smilies::add($b, ':tropical drink:', '🍹'); + Smilies::add($b, ':beer mug:', '🍺'); Smilies::add($b, ':beer:', '🍺'); Smilies::add($b, ':homebrew:', '🍺'); - Smilies::add($b, ':clinking beer mugs:', '🍻'); - Smilies::add($b, ':clinking glasses:', '🥂'); - Smilies::add($b, ':tumbler glass:', '🥃'); - Smilies::add($b, ':cup with straw:', '🥤'); -// Smilies::add($b, ':beverage box:', '🧃'); - Smilies::add($b, ':mate:', '🧉'); - Smilies::add($b, ':ice:', '🧊'); + Smilies::add($b, ':clinking beer mugs:', '🍻'); + Smilies::add($b, ':clinking glasses:', '🥂'); + Smilies::add($b, ':tumbler glass:', '🥃'); + Smilies::add($b, ':cup with straw:', '🥤'); +// Smilies::add($b, ':beverage box:', '🧃'); + Smilies::add($b, ':mate:', '🧉'); + Smilies::add($b, ':ice:', '🧊'); // dishware - Smilies::add($b, ':chopsticks:', '🥢'); - Smilies::add($b, ':fork and knife with plate:', '🍽'); - Smilies::add($b, ':fork and knife:', '🍴'); - Smilies::add($b, ':spoon:', '🥄'); - Smilies::add($b, ':kitchen knife:', '🔪'); - Smilies::add($b, ':amphora:', '🏺'); + Smilies::add($b, ':chopsticks:', '🥢'); + Smilies::add($b, ':fork and knife with plate:', '🍽'); + Smilies::add($b, ':fork and knife:', '🍴'); + Smilies::add($b, ':spoon:', '🥄'); + Smilies::add($b, ':kitchen knife:', '🔪'); + Smilies::add($b, ':amphora:', '🏺'); // Travel & Places // place-map - Smilies::add($b, ':globe showing Europe-Africa:', '🌍'); - Smilies::add($b, ':globe showing Americas:', '🌎'); - Smilies::add($b, ':globe showing Asia-Australia:', '🌏'); - Smilies::add($b, ':globe with meridians:', '🌐'); - Smilies::add($b, ':world map:', '🗺'); - Smilies::add($b, ':map of Japan:', '🗾'); - Smilies::add($b, ':compass:', '🧭'); + Smilies::add($b, ':globe showing Europe-Africa:', '🌍'); + Smilies::add($b, ':globe showing Americas:', '🌎'); + Smilies::add($b, ':globe showing Asia-Australia:', '🌏'); + Smilies::add($b, ':globe with meridians:', '🌐'); + Smilies::add($b, ':world map:', '🗺'); + Smilies::add($b, ':map of Japan:', '🗾'); + Smilies::add($b, ':compass:', '🧭'); // place-geographic - Smilies::add($b, ':snow-capped mountain:', '🏔'); - Smilies::add($b, ':mountain:', '⛰'); - Smilies::add($b, ':volcano:', '🌋'); - Smilies::add($b, ':mount fuji:', '🗻'); - Smilies::add($b, ':camping:', '🏕'); - Smilies::add($b, ':beach with umbrella:', '🏖'); - Smilies::add($b, ':desert:', '🏜'); - Smilies::add($b, ':desert island:', '🏝'); - Smilies::add($b, ':national park:', '🏞'); + Smilies::add($b, ':snow-capped mountain:', '🏔'); + Smilies::add($b, ':mountain:', '⛰'); + Smilies::add($b, ':volcano:', '🌋'); + Smilies::add($b, ':mount fuji:', '🗻'); + Smilies::add($b, ':camping:', '🏕'); + Smilies::add($b, ':beach with umbrella:', '🏖'); + Smilies::add($b, ':desert:', '🏜'); + Smilies::add($b, ':desert island:', '🏝'); + Smilies::add($b, ':national park:', '🏞'); // place-building - Smilies::add($b, ':stadium:', '🏟'); - Smilies::add($b, ':classical building:', '🏛'); - Smilies::add($b, ':building construction:', '🏗'); - Smilies::add($b, ':brick:', '🧱'); - Smilies::add($b, ':houses:', '🏘'); - Smilies::add($b, ':derelict house:', '🏚'); - Smilies::add($b, ':house:', '🏠'); - Smilies::add($b, ':house with garden:', '🏡'); - Smilies::add($b, ':office building:', '🏢'); - Smilies::add($b, ':Japanese post office:', '🏣'); - Smilies::add($b, ':post office:', '🏤'); - Smilies::add($b, ':hospital:', '🏥'); - Smilies::add($b, ':bank:', '🏦'); - Smilies::add($b, ':hotel:', '🏨'); - Smilies::add($b, ':love hotel:', '🏩'); - Smilies::add($b, ':convenience store:', '🏪'); - Smilies::add($b, ':school:', '🏫'); - Smilies::add($b, ':department store:', '🏬'); - Smilies::add($b, ':factory:', '🏭'); - Smilies::add($b, ':Japanese castle:', '🏯'); - Smilies::add($b, ':castle:', '🏰'); - Smilies::add($b, ':wedding:', '💒'); - Smilies::add($b, ':Tokyo tower:', '🗼'); - Smilies::add($b, ':Statue of Liberty:', '🗽'); - + Smilies::add($b, ':stadium:', '🏟'); + Smilies::add($b, ':classical building:', '🏛'); + Smilies::add($b, ':building construction:', '🏗'); + Smilies::add($b, ':brick:', '🧱'); + Smilies::add($b, ':houses:', '🏘'); + Smilies::add($b, ':derelict house:', '🏚'); + Smilies::add($b, ':house:', '🏠'); + Smilies::add($b, ':house with garden:', '🏡'); + Smilies::add($b, ':office building:', '🏢'); + Smilies::add($b, ':Japanese post office:', '🏣'); + Smilies::add($b, ':post office:', '🏤'); + Smilies::add($b, ':hospital:', '🏥'); + Smilies::add($b, ':bank:', '🏦'); + Smilies::add($b, ':hotel:', '🏨'); + Smilies::add($b, ':love hotel:', '🏩'); + Smilies::add($b, ':convenience store:', '🏪'); + Smilies::add($b, ':school:', '🏫'); + Smilies::add($b, ':department store:', '🏬'); + Smilies::add($b, ':factory:', '🏭'); + Smilies::add($b, ':Japanese castle:', '🏯'); + Smilies::add($b, ':castle:', '🏰'); + Smilies::add($b, ':wedding:', '💒'); + Smilies::add($b, ':Tokyo tower:', '🗼'); + Smilies::add($b, ':Statue of Liberty:', '🗽'); // place-religious - Smilies::add($b, ':church:', '⛪'); - Smilies::add($b, ':mosque:', '🕌'); -// Smilies::add($b, ':hindu temple:', '🛕'); - Smilies::add($b, ':synagogue:', '🕍'); - Smilies::add($b, ':shinto shrine:', '⛩'); - Smilies::add($b, ':kaaba:', '🕋'); + Smilies::add($b, ':church:', '⛪'); + Smilies::add($b, ':mosque:', '🕌'); +// Smilies::add($b, ':hindu temple:', '🛕'); + Smilies::add($b, ':synagogue:', '🕍'); + Smilies::add($b, ':shinto shrine:', '⛩'); + Smilies::add($b, ':kaaba:', '🕋'); // place-other - Smilies::add($b, ':fountain:', '⛲'); - Smilies::add($b, ':tent:', '⛺'); - Smilies::add($b, ':foggy:', '🌁'); - Smilies::add($b, ':night with stars:', '🌃'); - Smilies::add($b, ':cityscape:', '🏙'); - Smilies::add($b, ':sunrise over mountains:', '🌄'); - Smilies::add($b, ':sunrise:', '🌅'); - Smilies::add($b, ':cityscape at dusk:', '🌆'); - Smilies::add($b, ':sunset:', '🌇'); - Smilies::add($b, ':bridge at night:', '🌉'); - Smilies::add($b, ':hot springs:', '♨'); - Smilies::add($b, ':carousel horse:', '🎠'); - Smilies::add($b, ':ferris wheel:', '🎡'); - Smilies::add($b, ':roller coaster:', '🎢'); - Smilies::add($b, ':barber pole:', '💈'); - Smilies::add($b, ':circus tent:', '🎪'); + Smilies::add($b, ':fountain:', '⛲'); + Smilies::add($b, ':tent:', '⛺'); + Smilies::add($b, ':foggy:', '🌁'); + Smilies::add($b, ':night with stars:', '🌃'); + Smilies::add($b, ':cityscape:', '🏙'); + Smilies::add($b, ':sunrise over mountains:', '🌄'); + Smilies::add($b, ':sunrise:', '🌅'); + Smilies::add($b, ':cityscape at dusk:', '🌆'); + Smilies::add($b, ':sunset:', '🌇'); + Smilies::add($b, ':bridge at night:', '🌉'); + Smilies::add($b, ':hot springs:', '♨'); + Smilies::add($b, ':carousel horse:', '🎠'); + Smilies::add($b, ':ferris wheel:', '🎡'); + Smilies::add($b, ':roller coaster:', '🎢'); + Smilies::add($b, ':barber pole:', '💈'); + Smilies::add($b, ':circus tent:', '🎪'); // transport-ground - Smilies::add($b, ':locomotive:', '🚂'); - Smilies::add($b, ':railway car:', '🚃'); - Smilies::add($b, ':high-speed train:', '🚄'); - Smilies::add($b, ':bullet train:', '🚅'); - Smilies::add($b, ':train:', '🚆'); - Smilies::add($b, ':metro:', '🚇'); - Smilies::add($b, ':light rail:', '🚈'); - Smilies::add($b, ':station:', '🚉'); - Smilies::add($b, ':tram:', '🚊'); - Smilies::add($b, ':monorail:', '🚝'); - Smilies::add($b, ':mountain railway:', '🚞'); - Smilies::add($b, ':tram car:', '🚋'); - Smilies::add($b, ':bus:', '🚌'); - Smilies::add($b, ':oncoming bus:', '🚍'); - Smilies::add($b, ':trolleybus:', '🚎'); - Smilies::add($b, ':minibus:', '🚐'); - Smilies::add($b, ':ambulance:', '🚑'); - Smilies::add($b, ':fire engine:', '🚒'); - Smilies::add($b, ':police car:', '🚓'); - Smilies::add($b, ':oncoming police car:', '🚔'); - Smilies::add($b, ':taxi:', '🚕'); - Smilies::add($b, ':oncoming taxi:', '🚖'); - Smilies::add($b, ':automobile:', '🚗'); - Smilies::add($b, ':oncoming automobile:', '🚘'); - Smilies::add($b, ':sport utility vehicle:', '🚙'); - Smilies::add($b, ':delivery truck:', '🚚'); - Smilies::add($b, ':articulated lorry:', '🚛'); - Smilies::add($b, ':tractor:', '🚜'); - Smilies::add($b, ':racing car:', '🏎'); - Smilies::add($b, ':motorcycle:', '🏍'); - Smilies::add($b, ':motor scooter:', '🛵'); -// Smilies::add($b, ':manual wheelchair:', '🦽'); -// Smilies::add($b, ':motorized wheelchair:', '🦼'); -// Smilies::add($b, ':auto rickshaw:', '🛺'); - Smilies::add($b, ':bicycle:', '🚲'); - Smilies::add($b, ':kick scooter:', '🛴'); - Smilies::add($b, ':skateboard:', '🛹'); - Smilies::add($b, ':bus stop:', '🚏'); - Smilies::add($b, ':motorway:', '🛣'); - Smilies::add($b, ':railway track:', '🛤'); - Smilies::add($b, ':oil drum:', '🛢'); - Smilies::add($b, ':fuel pump:', '⛽'); - Smilies::add($b, ':police car light:', '🚨'); - Smilies::add($b, ':horizontal traffic light:', '🚥'); - Smilies::add($b, ':vertical traffic light:', '🚦'); - Smilies::add($b, ':stop sign:', '🛑'); - Smilies::add($b, ':construction:', '🚧'); + Smilies::add($b, ':locomotive:', '🚂'); + Smilies::add($b, ':railway car:', '🚃'); + Smilies::add($b, ':high-speed train:', '🚄'); + Smilies::add($b, ':bullet train:', '🚅'); + Smilies::add($b, ':train:', '🚆'); + Smilies::add($b, ':metro:', '🚇'); + Smilies::add($b, ':light rail:', '🚈'); + Smilies::add($b, ':station:', '🚉'); + Smilies::add($b, ':tram:', '🚊'); + Smilies::add($b, ':monorail:', '🚝'); + Smilies::add($b, ':mountain railway:', '🚞'); + Smilies::add($b, ':tram car:', '🚋'); + Smilies::add($b, ':bus:', '🚌'); + Smilies::add($b, ':oncoming bus:', '🚍'); + Smilies::add($b, ':trolleybus:', '🚎'); + Smilies::add($b, ':minibus:', '🚐'); + Smilies::add($b, ':ambulance:', '🚑'); + Smilies::add($b, ':fire engine:', '🚒'); + Smilies::add($b, ':police car:', '🚓'); + Smilies::add($b, ':oncoming police car:', '🚔'); + Smilies::add($b, ':taxi:', '🚕'); + Smilies::add($b, ':oncoming taxi:', '🚖'); + Smilies::add($b, ':automobile:', '🚗'); + Smilies::add($b, ':oncoming automobile:', '🚘'); + Smilies::add($b, ':sport utility vehicle:', '🚙'); + Smilies::add($b, ':delivery truck:', '🚚'); + Smilies::add($b, ':articulated lorry:', '🚛'); + Smilies::add($b, ':tractor:', '🚜'); + Smilies::add($b, ':racing car:', '🏎'); + Smilies::add($b, ':motorcycle:', '🏍'); + Smilies::add($b, ':motor scooter:', '🛵'); +// Smilies::add($b, ':manual wheelchair:', '🦽'); +// Smilies::add($b, ':motorized wheelchair:', '🦼'); +// Smilies::add($b, ':auto rickshaw:', '🛺'); + Smilies::add($b, ':bicycle:', '🚲'); + Smilies::add($b, ':kick scooter:', '🛴'); + Smilies::add($b, ':skateboard:', '🛹'); + Smilies::add($b, ':bus stop:', '🚏'); + Smilies::add($b, ':motorway:', '🛣'); + Smilies::add($b, ':railway track:', '🛤'); + Smilies::add($b, ':oil drum:', '🛢'); + Smilies::add($b, ':fuel pump:', '⛽'); + Smilies::add($b, ':police car light:', '🚨'); + Smilies::add($b, ':horizontal traffic light:', '🚥'); + Smilies::add($b, ':vertical traffic light:', '🚦'); + Smilies::add($b, ':stop sign:', '🛑'); + Smilies::add($b, ':construction:', '🚧'); // transport-water - Smilies::add($b, ':anchor:', '⚓'); - Smilies::add($b, ':sailboat:', '⛵'); - Smilies::add($b, ':canoe:', '🛶'); - Smilies::add($b, ':speedboat:', '🚤'); - Smilies::add($b, ':passenger ship:', '🛳'); - Smilies::add($b, ':ferry:', '⛴'); - Smilies::add($b, ':motor boat:', '🛥'); - Smilies::add($b, ':ship:', '🚢'); + Smilies::add($b, ':anchor:', '⚓'); + Smilies::add($b, ':sailboat:', '⛵'); + Smilies::add($b, ':canoe:', '🛶'); + Smilies::add($b, ':speedboat:', '🚤'); + Smilies::add($b, ':passenger ship:', '🛳'); + Smilies::add($b, ':ferry:', '⛴'); + Smilies::add($b, ':motor boat:', '🛥'); + Smilies::add($b, ':ship:', '🚢'); // transport-air - Smilies::add($b, ':airplane:', '✈'); - Smilies::add($b, ':small airplane:', '🛩'); - Smilies::add($b, ':airplane departure:', '🛫'); - Smilies::add($b, ':airplane arrival:', '🛬'); - Smilies::add($b, ':parachute:', '🪂'); - Smilies::add($b, ':seat:', '💺'); - Smilies::add($b, ':helicopter:', '🚁'); - Smilies::add($b, ':suspension railway:', '🚟'); - Smilies::add($b, ':mountain cableway:', '🚠'); - Smilies::add($b, ':aerial tramway:', '🚡'); - Smilies::add($b, ':satellite:', '🛰'); - Smilies::add($b, ':rocket:', '🚀'); - Smilies::add($b, ':flying saucer:', '🛸'); + Smilies::add($b, ':airplane:', '✈'); + Smilies::add($b, ':small airplane:', '🛩'); + Smilies::add($b, ':airplane departure:', '🛫'); + Smilies::add($b, ':airplane arrival:', '🛬'); + Smilies::add($b, ':parachute:', '🪂'); + Smilies::add($b, ':seat:', '💺'); + Smilies::add($b, ':helicopter:', '🚁'); + Smilies::add($b, ':suspension railway:', '🚟'); + Smilies::add($b, ':mountain cableway:', '🚠'); + Smilies::add($b, ':aerial tramway:', '🚡'); + Smilies::add($b, ':satellite:', '🛰'); + Smilies::add($b, ':rocket:', '🚀'); + Smilies::add($b, ':flying saucer:', '🛸'); // hotel - Smilies::add($b, ':bellhop bell:', '🛎'); - Smilies::add($b, ':luggage:', '🧳'); + Smilies::add($b, ':bellhop bell:', '🛎'); + Smilies::add($b, ':luggage:', '🧳'); // time - Smilies::add($b, ':hourglass done:', '⌛'); - Smilies::add($b, ':hourglass not done:', '⏳'); - Smilies::add($b, ':watch:', '⌚'); - Smilies::add($b, ':alarm clock:', '⏰'); - Smilies::add($b, ':stopwatch:', '⏱'); - Smilies::add($b, ':timer clock:', '⏲'); - Smilies::add($b, ':mantelpiece clock:', '🕰'); - Smilies::add($b, ':twelve o’clock:', '🕛'); - Smilies::add($b, ':twelve-thirty:', '🕧'); - Smilies::add($b, ':one o’clock:', '🕐'); - Smilies::add($b, ':one-thirty:', '🕜'); - Smilies::add($b, ':two o’clock:', '🕑'); - Smilies::add($b, ':two-thirty:', '🕝'); - Smilies::add($b, ':three o’clock:', '🕒'); - Smilies::add($b, ':three-thirty:', '🕞'); - Smilies::add($b, ':four o’clock:', '🕓'); - Smilies::add($b, ':four-thirty:', '🕟'); - Smilies::add($b, ':five o’clock:', '🕔'); - Smilies::add($b, ':five-thirty:', '🕠'); - Smilies::add($b, ':six o’clock:', '🕕'); - Smilies::add($b, ':six-thirty:', '🕡'); - Smilies::add($b, ':seven o’clock:', '🕖'); - Smilies::add($b, ':seven-thirty:', '🕢'); - Smilies::add($b, ':eight o’clock:', '🕗'); - Smilies::add($b, ':eight-thirty:', '🕣'); - Smilies::add($b, ':nine o’clock:', '🕘'); - Smilies::add($b, ':nine-thirty:', '🕤'); - Smilies::add($b, ':ten o’clock:', '🕙'); - Smilies::add($b, ':ten-thirty:', '🕥'); - Smilies::add($b, ':eleven o’clock:', '🕚'); - Smilies::add($b, ':eleven-thirty:', '🕦'); + Smilies::add($b, ':hourglass done:', '⌛'); + Smilies::add($b, ':hourglass not done:', '⏳'); + Smilies::add($b, ':watch:', '⌚'); + Smilies::add($b, ':alarm clock:', '⏰'); + Smilies::add($b, ':stopwatch:', '⏱'); + Smilies::add($b, ':timer clock:', '⏲'); + Smilies::add($b, ':mantelpiece clock:', '🕰'); + Smilies::add($b, ':twelve o’clock:', '🕛'); + Smilies::add($b, ':twelve-thirty:', '🕧'); + Smilies::add($b, ':one o’clock:', '🕐'); + Smilies::add($b, ':one-thirty:', '🕜'); + Smilies::add($b, ':two o’clock:', '🕑'); + Smilies::add($b, ':two-thirty:', '🕝'); + Smilies::add($b, ':three o’clock:', '🕒'); + Smilies::add($b, ':three-thirty:', '🕞'); + Smilies::add($b, ':four o’clock:', '🕓'); + Smilies::add($b, ':four-thirty:', '🕟'); + Smilies::add($b, ':five o’clock:', '🕔'); + Smilies::add($b, ':five-thirty:', '🕠'); + Smilies::add($b, ':six o’clock:', '🕕'); + Smilies::add($b, ':six-thirty:', '🕡'); + Smilies::add($b, ':seven o’clock:', '🕖'); + Smilies::add($b, ':seven-thirty:', '🕢'); + Smilies::add($b, ':eight o’clock:', '🕗'); + Smilies::add($b, ':eight-thirty:', '🕣'); + Smilies::add($b, ':nine o’clock:', '🕘'); + Smilies::add($b, ':nine-thirty:', '🕤'); + Smilies::add($b, ':ten o’clock:', '🕙'); + Smilies::add($b, ':ten-thirty:', '🕥'); + Smilies::add($b, ':eleven o’clock:', '🕚'); + Smilies::add($b, ':eleven-thirty:', '🕦'); // sky & weather - Smilies::add($b, ':new moon:', '🌑'); - Smilies::add($b, ':waxing crescent moon:', '🌒'); - Smilies::add($b, ':first quarter moon:', '🌓'); - Smilies::add($b, ':waxing gibbous moon:', '🌔'); - Smilies::add($b, ':full moon:', '🌕'); - Smilies::add($b, ':waning gibbous moon:', '🌖'); - Smilies::add($b, ':last quarter moon:', '🌗'); - Smilies::add($b, ':waning crescent moon:', '🌘'); - Smilies::add($b, ':crescent moon:', '🌙'); - Smilies::add($b, ':new moon face:', '🌚'); - Smilies::add($b, ':first quarter moon face:', '🌛'); - Smilies::add($b, ':last quarter moon face:', '🌜'); - Smilies::add($b, ':thermometer:', '🌡'); - Smilies::add($b, ':sun:', '☀'); - Smilies::add($b, ':full moon face:', '🌝'); - Smilies::add($b, ':sun with face:', '🌞'); - Smilies::add($b, ':ringed planet:', '🪐'); - Smilies::add($b, ':star:', '⭐'); - Smilies::add($b, ':glowing star:', '🌟'); - Smilies::add($b, ':shooting star:', '🌠'); - Smilies::add($b, ':milky way:', '🌌'); - Smilies::add($b, ':cloud:', '☁'); - Smilies::add($b, ':sun behind cloud:', '⛅'); - Smilies::add($b, ':cloud with lightning and rain:', '⛈'); - Smilies::add($b, ':sun behind small cloud:', '🌤'); - Smilies::add($b, ':sun behind large cloud:', '🌥'); - Smilies::add($b, ':sun behind rain cloud:', '🌦'); - Smilies::add($b, ':cloud with rain:', '🌧'); - Smilies::add($b, ':cloud with snow:', '🌨'); - Smilies::add($b, ':cloud with lightning:', '🌩'); - Smilies::add($b, ':tornado:', '🌪'); - Smilies::add($b, ':fog:', '🌫'); - Smilies::add($b, ':wind face:', '🌬'); - Smilies::add($b, ':cyclone:', '🌀'); - Smilies::add($b, ':rainbow:', '🌈'); - Smilies::add($b, ':closed umbrella:', '🌂'); - Smilies::add($b, ':umbrella:', '☂'); - Smilies::add($b, ':umbrella with rain drops:', '☔'); - Smilies::add($b, ':umbrella on ground:', '⛱'); - Smilies::add($b, ':high voltage:', '⚡'); - Smilies::add($b, ':snowflake:', '❄'); - Smilies::add($b, ':snowman:', '☃'); - Smilies::add($b, ':snowman without snow:', '⛄'); - Smilies::add($b, ':comet:', '☄'); - Smilies::add($b, ':fire:', '🔥'); - Smilies::add($b, ':droplet:', '💧'); - Smilies::add($b, ':water wave:', '🌊'); + Smilies::add($b, ':new moon:', '🌑'); + Smilies::add($b, ':waxing crescent moon:', '🌒'); + Smilies::add($b, ':first quarter moon:', '🌓'); + Smilies::add($b, ':waxing gibbous moon:', '🌔'); + Smilies::add($b, ':full moon:', '🌕'); + Smilies::add($b, ':waning gibbous moon:', '🌖'); + Smilies::add($b, ':last quarter moon:', '🌗'); + Smilies::add($b, ':waning crescent moon:', '🌘'); + Smilies::add($b, ':crescent moon:', '🌙'); + Smilies::add($b, ':new moon face:', '🌚'); + Smilies::add($b, ':first quarter moon face:', '🌛'); + Smilies::add($b, ':last quarter moon face:', '🌜'); + Smilies::add($b, ':thermometer:', '🌡'); + Smilies::add($b, ':sun:', '☀'); + Smilies::add($b, ':full moon face:', '🌝'); + Smilies::add($b, ':sun with face:', '🌞'); + Smilies::add($b, ':ringed planet:', '🪐'); + Smilies::add($b, ':star:', '⭐'); + Smilies::add($b, ':glowing star:', '🌟'); + Smilies::add($b, ':shooting star:', '🌠'); + Smilies::add($b, ':milky way:', '🌌'); + Smilies::add($b, ':cloud:', '☁'); + Smilies::add($b, ':sun behind cloud:', '⛅'); + Smilies::add($b, ':cloud with lightning and rain:', '⛈'); + Smilies::add($b, ':sun behind small cloud:', '🌤'); + Smilies::add($b, ':sun behind large cloud:', '🌥'); + Smilies::add($b, ':sun behind rain cloud:', '🌦'); + Smilies::add($b, ':cloud with rain:', '🌧'); + Smilies::add($b, ':cloud with snow:', '🌨'); + Smilies::add($b, ':cloud with lightning:', '🌩'); + Smilies::add($b, ':tornado:', '🌪'); + Smilies::add($b, ':fog:', '🌫'); + Smilies::add($b, ':wind face:', '🌬'); + Smilies::add($b, ':cyclone:', '🌀'); + Smilies::add($b, ':rainbow:', '🌈'); + Smilies::add($b, ':closed umbrella:', '🌂'); + Smilies::add($b, ':umbrella:', '☂'); + Smilies::add($b, ':umbrella with rain drops:', '☔'); + Smilies::add($b, ':umbrella on ground:', '⛱'); + Smilies::add($b, ':high voltage:', '⚡'); + Smilies::add($b, ':snowflake:', '❄'); + Smilies::add($b, ':snowman:', '☃'); + Smilies::add($b, ':snowman without snow:', '⛄'); + Smilies::add($b, ':comet:', '☄'); + Smilies::add($b, ':fire:', '🔥'); + Smilies::add($b, ':droplet:', '💧'); + Smilies::add($b, ':water wave:', '🌊'); // Activities // event - Smilies::add($b, ':jack-o-lantern:', '🎃'); - Smilies::add($b, ':Christmas tree:', '🎄'); - Smilies::add($b, ':fireworks:', '🎆'); - Smilies::add($b, ':sparkler:', '🎇'); - Smilies::add($b, ':firecracker:', '🧨'); - Smilies::add($b, ':sparkles:', '✨'); - Smilies::add($b, ':balloon:', '🎈'); - Smilies::add($b, ':party popper:', '🎉'); - Smilies::add($b, ':confetti ball:', '🎊'); - Smilies::add($b, ':tanabata tree:', '🎋'); - Smilies::add($b, ':pine decoration:', '🎍'); - Smilies::add($b, ':Japanese dolls:', '🎎'); - Smilies::add($b, ':carp streamer:', '🎏'); - Smilies::add($b, ':wind chime:', '🎐'); - Smilies::add($b, ':moon viewing ceremony:', '🎑'); - Smilies::add($b, ':red envelope:', '🧧'); - Smilies::add($b, ':ribbon:', '🎀'); - Smilies::add($b, ':wrapped gift:', '🎁'); - Smilies::add($b, ':reminder ribbon:', '🎗'); - Smilies::add($b, ':admission tickets:', '🎟'); - Smilies::add($b, ':ticket:', '🎫'); + Smilies::add($b, ':jack-o-lantern:', '🎃'); + Smilies::add($b, ':Christmas tree:', '🎄'); + Smilies::add($b, ':fireworks:', '🎆'); + Smilies::add($b, ':sparkler:', '🎇'); + Smilies::add($b, ':firecracker:', '🧨'); + Smilies::add($b, ':sparkles:', '✨'); + Smilies::add($b, ':balloon:', '🎈'); + Smilies::add($b, ':party popper:', '🎉'); + Smilies::add($b, ':confetti ball:', '🎊'); + Smilies::add($b, ':tanabata tree:', '🎋'); + Smilies::add($b, ':pine decoration:', '🎍'); + Smilies::add($b, ':Japanese dolls:', '🎎'); + Smilies::add($b, ':carp streamer:', '🎏'); + Smilies::add($b, ':wind chime:', '🎐'); + Smilies::add($b, ':moon viewing ceremony:', '🎑'); + Smilies::add($b, ':red envelope:', '🧧'); + Smilies::add($b, ':ribbon:', '🎀'); + Smilies::add($b, ':wrapped gift:', '🎁'); + Smilies::add($b, ':reminder ribbon:', '🎗'); + Smilies::add($b, ':admission tickets:', '🎟'); + Smilies::add($b, ':ticket:', '🎫'); // award-medal - Smilies::add($b, ':military medal:', '🎖'); - Smilies::add($b, ':trophy:', '🏆'); - Smilies::add($b, ':sports medal:', '🏅'); - Smilies::add($b, ':1st place medal:', '🥇'); - Smilies::add($b, ':2nd place medal:', '🥈'); - Smilies::add($b, ':3rd place medal:', '🥉'); + Smilies::add($b, ':military medal:', '🎖'); + Smilies::add($b, ':trophy:', '🏆'); + Smilies::add($b, ':sports medal:', '🏅'); + Smilies::add($b, ':1st place medal:', '🥇'); + Smilies::add($b, ':2nd place medal:', '🥈'); + Smilies::add($b, ':3rd place medal:', '🥉'); // sport - Smilies::add($b, ':soccer ball:', '⚽'); - Smilies::add($b, ':baseball:', '⚾'); - Smilies::add($b, ':softball:', '🥎'); - Smilies::add($b, ':basketball:', '🏀'); - Smilies::add($b, ':volleyball:', '🏐'); - Smilies::add($b, ':american football:', '🏈'); + Smilies::add($b, ':soccer ball:', '⚽'); + Smilies::add($b, ':baseball:', '⚾'); + Smilies::add($b, ':softball:', '🥎'); + Smilies::add($b, ':basketball:', '🏀'); + Smilies::add($b, ':volleyball:', '🏐'); + Smilies::add($b, ':american football:', '🏈'); Smilies::add($b, ':football:', '🏈'); - Smilies::add($b, ':rugby football:', '🏉'); - Smilies::add($b, ':tennis:', '🎾'); - Smilies::add($b, ':flying disc:', '🥏'); - Smilies::add($b, ':bowling:', '🎳'); - Smilies::add($b, ':cricket game:', '🏏'); - Smilies::add($b, ':field hockey:', '🏑'); - Smilies::add($b, ':ice hockey:', '🏒'); - Smilies::add($b, ':lacrosse:', '🥍'); - Smilies::add($b, ':ping pong:', '🏓'); - Smilies::add($b, ':badminton:', '🏸'); - Smilies::add($b, ':boxing glove:', '🥊'); - Smilies::add($b, ':martial arts uniform:', '🥋'); - Smilies::add($b, ':goal net:', '🥅'); - Smilies::add($b, ':flag in hole:', '⛳'); - Smilies::add($b, ':ice skate:', '⛸'); - Smilies::add($b, ':fishing pole:', '🎣'); -// Smilies::add($b, ':diving mask:', '🤿'); - Smilies::add($b, ':running shirt:', '🎽'); - Smilies::add($b, ':skis:', '🎿'); - Smilies::add($b, ':sled:', '🛷'); - Smilies::add($b, ':curling stone:', '🥌'); + Smilies::add($b, ':rugby football:', '🏉'); + Smilies::add($b, ':tennis:', '🎾'); + Smilies::add($b, ':flying disc:', '🥏'); + Smilies::add($b, ':bowling:', '🎳'); + Smilies::add($b, ':cricket game:', '🏏'); + Smilies::add($b, ':field hockey:', '🏑'); + Smilies::add($b, ':ice hockey:', '🏒'); + Smilies::add($b, ':lacrosse:', '🥍'); + Smilies::add($b, ':ping pong:', '🏓'); + Smilies::add($b, ':badminton:', '🏸'); + Smilies::add($b, ':boxing glove:', '🥊'); + Smilies::add($b, ':martial arts uniform:', '🥋'); + Smilies::add($b, ':goal net:', '🥅'); + Smilies::add($b, ':flag in hole:', '⛳'); + Smilies::add($b, ':ice skate:', '⛸'); + Smilies::add($b, ':fishing pole:', '🎣'); +// Smilies::add($b, ':diving mask:', '🤿'); + Smilies::add($b, ':running shirt:', '🎽'); + Smilies::add($b, ':skis:', '🎿'); + Smilies::add($b, ':sled:', '🛷'); + Smilies::add($b, ':curling stone:', '🥌'); Smilies::add($b, ':cycling:', '🚴'); Smilies::add($b, ':darts:', '🎯'); Smilies::add($b, ':fencing:', '🤺'); Smilies::add($b, ':juggling:', '🤹'); -// Smilies::add($b, ':skipping:', '&#x;'); -// Smilies::add($b, ':archery:', '&#x;'); +// Smilies::add($b, ':skipping:', '&#x;'); +// Smilies::add($b, ':archery:', '&#x;'); Smilies::add($b, ':surfing:', '🏄'); Smilies::add($b, ':snooker:', '🎱'); Smilies::add($b, ':horseriding:', '🏇'); // game - Smilies::add($b, ':direct hit:', '🎯'); - Smilies::add($b, ':yo-yo:', '🪀'); - Smilies::add($b, ':kite:', '🪁'); - Smilies::add($b, ':pool 8 ball:', '🎱'); - Smilies::add($b, ':crystal ball:', '🔮'); - Smilies::add($b, ':nazar amulet:', '🧿'); - Smilies::add($b, ':video game:', '🎮'); - Smilies::add($b, ':joystick:', '🕹'); - Smilies::add($b, ':slot machine:', '🎰'); - Smilies::add($b, ':game die:', '🎲'); - Smilies::add($b, ':puzzle piece:', '🧩'); - Smilies::add($b, ':teddy bear:', '🧸'); - Smilies::add($b, ':spade suit:', '♠'); - Smilies::add($b, ':heart suit:', '♥'); - Smilies::add($b, ':diamond suit:', '♦'); - Smilies::add($b, ':club suit:', '♣'); - Smilies::add($b, ':chess pawn:', '♟'); - Smilies::add($b, ':joker:', '🃏'); - Smilies::add($b, ':mahjong red dragon:', '🀄'); - Smilies::add($b, ':flower playing cards:', '🎴'); + Smilies::add($b, ':direct hit:', '🎯'); + Smilies::add($b, ':yo-yo:', '🪀'); + Smilies::add($b, ':kite:', '🪁'); + Smilies::add($b, ':pool 8 ball:', '🎱'); + Smilies::add($b, ':crystal ball:', '🔮'); + Smilies::add($b, ':nazar amulet:', '🧿'); + Smilies::add($b, ':video game:', '🎮'); + Smilies::add($b, ':joystick:', '🕹'); + Smilies::add($b, ':slot machine:', '🎰'); + Smilies::add($b, ':game die:', '🎲'); + Smilies::add($b, ':puzzle piece:', '🧩'); + Smilies::add($b, ':teddy bear:', '🧸'); + Smilies::add($b, ':spade suit:', '♠'); + Smilies::add($b, ':heart suit:', '♥'); + Smilies::add($b, ':diamond suit:', '♦'); + Smilies::add($b, ':club suit:', '♣'); + Smilies::add($b, ':chess pawn:', '♟'); + Smilies::add($b, ':joker:', '🃏'); + Smilies::add($b, ':mahjong red dragon:', '🀄'); + Smilies::add($b, ':flower playing cards:', '🎴'); // arts & crafts - Smilies::add($b, ':performing arts:', '🎭'); - Smilies::add($b, ':framed picture:', '🖼'); - Smilies::add($b, ':artist palette:', '🎨'); - Smilies::add($b, ':thread:', '🧵'); - Smilies::add($b, ':yarn:', '🧶'); + Smilies::add($b, ':performing arts:', '🎭'); + Smilies::add($b, ':framed picture:', '🖼'); + Smilies::add($b, ':artist palette:', '🎨'); + Smilies::add($b, ':thread:', '🧵'); + Smilies::add($b, ':yarn:', '🧶'); // Objects // clothing - Smilies::add($b, ':glasses:', '👓'); - Smilies::add($b, ':sunglasses:', '🕶'); - Smilies::add($b, ':goggles:', '🥽'); - Smilies::add($b, ':lab coat:', '🥼'); - Smilies::add($b, ':safety vest:', '🦺'); - Smilies::add($b, ':necktie:', '👔'); - Smilies::add($b, ':t-shirt:', '👕'); - Smilies::add($b, ':jeans:', '👖'); - Smilies::add($b, ':scarf:', '🧣'); - Smilies::add($b, ':gloves:', '🧤'); - Smilies::add($b, ':coat:', '🧥'); - Smilies::add($b, ':socks:', '🧦'); - Smilies::add($b, ':dress:', '👗'); - Smilies::add($b, ':kimono:', '👘'); - Smilies::add($b, ':sari:', '🥻'); - Smilies::add($b, ':one-piece swimsuit:', '🩱'); - Smilies::add($b, ':briefs:', '🩲'); - Smilies::add($b, ':shorts:', '🩳'); - Smilies::add($b, ':bikini:', '👙'); - Smilies::add($b, ':woman’s clothes:', '👚'); - Smilies::add($b, ':purse:', '👛'); - Smilies::add($b, ':handbag:', '👜'); - Smilies::add($b, ':clutch bag:', '👝'); - Smilies::add($b, ':shopping bags:', '🛍'); - Smilies::add($b, ':backpack:', '🎒'); - Smilies::add($b, ':man’s shoe:', '👞'); - Smilies::add($b, ':running shoe:', '👟'); - Smilies::add($b, ':hiking boot:', '🥾'); - Smilies::add($b, ':flat shoe:', '🥿'); - Smilies::add($b, ':high-heeled shoe:', '👠'); - Smilies::add($b, ':woman’s sandal:', '👡'); -// Smilies::add($b, ':ballet shoes:', '🩰'); - Smilies::add($b, ':woman’s boot:', '👢'); - Smilies::add($b, ':crown:', '👑'); - Smilies::add($b, ':woman’s hat:', '👒'); - Smilies::add($b, ':top hat:', '🎩'); - Smilies::add($b, ':graduation cap:', '🎓'); - Smilies::add($b, ':billed cap:', '🧢'); - Smilies::add($b, ':rescue worker’s helmet:', '⛑'); - Smilies::add($b, ':prayer beads:', '📿'); - Smilies::add($b, ':lipstick:', '💄'); - Smilies::add($b, ':ring:', '💍'); - Smilies::add($b, ':gem stone:', '💎'); + Smilies::add($b, ':glasses:', '👓'); + Smilies::add($b, ':sunglasses:', '🕶'); + Smilies::add($b, ':goggles:', '🥽'); + Smilies::add($b, ':lab coat:', '🥼'); + Smilies::add($b, ':safety vest:', '🦺'); + Smilies::add($b, ':necktie:', '👔'); + Smilies::add($b, ':t-shirt:', '👕'); + Smilies::add($b, ':jeans:', '👖'); + Smilies::add($b, ':scarf:', '🧣'); + Smilies::add($b, ':gloves:', '🧤'); + Smilies::add($b, ':coat:', '🧥'); + Smilies::add($b, ':socks:', '🧦'); + Smilies::add($b, ':dress:', '👗'); + Smilies::add($b, ':kimono:', '👘'); + Smilies::add($b, ':sari:', '🥻'); + Smilies::add($b, ':one-piece swimsuit:', '🩱'); + Smilies::add($b, ':briefs:', '🩲'); + Smilies::add($b, ':shorts:', '🩳'); + Smilies::add($b, ':bikini:', '👙'); + Smilies::add($b, ':woman’s clothes:', '👚'); + Smilies::add($b, ':purse:', '👛'); + Smilies::add($b, ':handbag:', '👜'); + Smilies::add($b, ':clutch bag:', '👝'); + Smilies::add($b, ':shopping bags:', '🛍'); + Smilies::add($b, ':backpack:', '🎒'); + Smilies::add($b, ':man’s shoe:', '👞'); + Smilies::add($b, ':running shoe:', '👟'); + Smilies::add($b, ':hiking boot:', '🥾'); + Smilies::add($b, ':flat shoe:', '🥿'); + Smilies::add($b, ':high-heeled shoe:', '👠'); + Smilies::add($b, ':woman’s sandal:', '👡'); +// Smilies::add($b, ':ballet shoes:', '🩰'); + Smilies::add($b, ':woman’s boot:', '👢'); + Smilies::add($b, ':crown:', '👑'); + Smilies::add($b, ':woman’s hat:', '👒'); + Smilies::add($b, ':top hat:', '🎩'); + Smilies::add($b, ':graduation cap:', '🎓'); + Smilies::add($b, ':billed cap:', '🧢'); + Smilies::add($b, ':rescue worker’s helmet:', '⛑'); + Smilies::add($b, ':prayer beads:', '📿'); + Smilies::add($b, ':lipstick:', '💄'); + Smilies::add($b, ':ring:', '💍'); + Smilies::add($b, ':gem stone:', '💎'); // sound - Smilies::add($b, ':muted speaker:', '🔇'); - Smilies::add($b, ':speaker low volume:', '🔈'); - Smilies::add($b, ':speaker medium volume:', '🔉'); - Smilies::add($b, ':speaker high volume:', '🔊'); - Smilies::add($b, ':loudspeaker:', '📢'); - Smilies::add($b, ':megaphone:', '📣'); - Smilies::add($b, ':postal horn:', '📯'); - Smilies::add($b, ':bell:', '🔔'); - Smilies::add($b, ':bell with slash:', '🔕'); + Smilies::add($b, ':muted speaker:', '🔇'); + Smilies::add($b, ':speaker low volume:', '🔈'); + Smilies::add($b, ':speaker medium volume:', '🔉'); + Smilies::add($b, ':speaker high volume:', '🔊'); + Smilies::add($b, ':loudspeaker:', '📢'); + Smilies::add($b, ':megaphone:', '📣'); + Smilies::add($b, ':postal horn:', '📯'); + Smilies::add($b, ':bell:', '🔔'); + Smilies::add($b, ':bell with slash:', '🔕'); // musik - Smilies::add($b, ':musical score:', '🎼'); - Smilies::add($b, ':musical note:', '🎵'); - Smilies::add($b, ':musical notes:', '🎶'); - Smilies::add($b, ':studio microphone:', '🎙'); - Smilies::add($b, ':level slider:', '🎚'); - Smilies::add($b, ':control knobs:', '🎛'); - Smilies::add($b, ':microphone:', '🎤'); - Smilies::add($b, ':headphone:', '🎧'); - Smilies::add($b, ':radio:', '📻'); + Smilies::add($b, ':musical score:', '🎼'); + Smilies::add($b, ':musical note:', '🎵'); + Smilies::add($b, ':musical notes:', '🎶'); + Smilies::add($b, ':studio microphone:', '🎙'); + Smilies::add($b, ':level slider:', '🎚'); + Smilies::add($b, ':control knobs:', '🎛'); + Smilies::add($b, ':microphone:', '🎤'); + Smilies::add($b, ':headphone:', '🎧'); + Smilies::add($b, ':radio:', '📻'); // musical-instrument - Smilies::add($b, ':saxophone:', '🎷'); - Smilies::add($b, ':guitar:', '🎸'); - Smilies::add($b, ':musical keyboard:', '🎹'); - Smilies::add($b, ':trumpet:', '🎺'); - Smilies::add($b, ':violin:', '🎻'); -// Smilies::add($b, ':banjo:', '🪕'); - Smilies::add($b, ':drum:', '🥁'); + Smilies::add($b, ':saxophone:', '🎷'); + Smilies::add($b, ':guitar:', '🎸'); + Smilies::add($b, ':musical keyboard:', '🎹'); + Smilies::add($b, ':trumpet:', '🎺'); + Smilies::add($b, ':violin:', '🎻'); +// Smilies::add($b, ':banjo:', '🪕'); + Smilies::add($b, ':drum:', '🥁'); // phone - Smilies::add($b, ':mobile phone:', '📱'); - Smilies::add($b, ':mobile phone with arrow:', '📲'); - Smilies::add($b, ':telephone:', '☎'); - Smilies::add($b, ':telephone receiver:', '📞'); - Smilies::add($b, ':pager:', '📟'); - Smilies::add($b, ':fax machine:', '📠'); + Smilies::add($b, ':mobile phone:', '📱'); + Smilies::add($b, ':mobile phone with arrow:', '📲'); + Smilies::add($b, ':telephone:', '☎'); + Smilies::add($b, ':telephone receiver:', '📞'); + Smilies::add($b, ':pager:', '📟'); + Smilies::add($b, ':fax machine:', '📠'); // computer - Smilies::add($b, ':battery:', '🔋'); - Smilies::add($b, ':electric plug:', '🔌'); - Smilies::add($b, ':laptop:', '💻'); - Smilies::add($b, ':desktop computer:', '🖥'); - Smilies::add($b, ':printer:', '🖨'); - Smilies::add($b, ':keyboard:', '⌨'); - Smilies::add($b, ':computer mouse:', '🖱'); - Smilies::add($b, ':trackball:', '🖲'); - Smilies::add($b, ':computer disk:', '💽'); - Smilies::add($b, ':floppy disk:', '💾'); - Smilies::add($b, ':optical disk:', '💿'); - Smilies::add($b, ':dvd:', '📀'); - Smilies::add($b, ':abacus:', '🧮'); + Smilies::add($b, ':battery:', '🔋'); + Smilies::add($b, ':electric plug:', '🔌'); + Smilies::add($b, ':laptop:', '💻'); + Smilies::add($b, ':desktop computer:', '🖥'); + Smilies::add($b, ':printer:', '🖨'); + Smilies::add($b, ':keyboard:', '⌨'); + Smilies::add($b, ':computer mouse:', '🖱'); + Smilies::add($b, ':trackball:', '🖲'); + Smilies::add($b, ':computer disk:', '💽'); + Smilies::add($b, ':floppy disk:', '💾'); + Smilies::add($b, ':optical disk:', '💿'); + Smilies::add($b, ':dvd:', '📀'); + Smilies::add($b, ':abacus:', '🧮'); // light & video - Smilies::add($b, ':movie camera:', '🎥'); - Smilies::add($b, ':film frames:', '🎞'); - Smilies::add($b, ':film projector:', '📽'); - Smilies::add($b, ':clapper board:', '🎬'); - Smilies::add($b, ':television:', '📺'); - Smilies::add($b, ':camera:', '📷'); - Smilies::add($b, ':camera with flash:', '📸'); - Smilies::add($b, ':video camera:', '📹'); - Smilies::add($b, ':videocassette:', '📼'); - Smilies::add($b, ':magnifying glass tilted left:', '🔍'); - Smilies::add($b, ':magnifying glass tilted right:', '🔎'); - Smilies::add($b, ':candle:', '🕯'); - Smilies::add($b, ':light bulb:', '💡'); - Smilies::add($b, ':flashlight:', '🔦'); - Smilies::add($b, ':red paper lantern:', '🏮'); -// Smilies::add($b, ':diya lamp:', '🪔'); + Smilies::add($b, ':movie camera:', '🎥'); + Smilies::add($b, ':film frames:', '🎞'); + Smilies::add($b, ':film projector:', '📽'); + Smilies::add($b, ':clapper board:', '🎬'); + Smilies::add($b, ':television:', '📺'); + Smilies::add($b, ':camera:', '📷'); + Smilies::add($b, ':camera with flash:', '📸'); + Smilies::add($b, ':video camera:', '📹'); + Smilies::add($b, ':videocassette:', '📼'); + Smilies::add($b, ':magnifying glass tilted left:', '🔍'); + Smilies::add($b, ':magnifying glass tilted right:', '🔎'); + Smilies::add($b, ':candle:', '🕯'); + Smilies::add($b, ':light bulb:', '💡'); + Smilies::add($b, ':flashlight:', '🔦'); + Smilies::add($b, ':red paper lantern:', '🏮'); +// Smilies::add($b, ':diya lamp:', '🪔'); // book-paper - Smilies::add($b, ':notebook with decorative cover:', '📔'); - Smilies::add($b, ':closed book:', '📕'); - Smilies::add($b, ':open book:', '📖'); - Smilies::add($b, ':green book:', '📗'); - Smilies::add($b, ':blue book:', '📘'); - Smilies::add($b, ':orange book:', '📙'); - Smilies::add($b, ':books:', '📚'); - Smilies::add($b, ':notebook:', '📓'); - Smilies::add($b, ':ledger:', '📒'); - Smilies::add($b, ':page with curl:', '📃'); - Smilies::add($b, ':scroll:', '📜'); - Smilies::add($b, ':page facing up:', '📄'); - Smilies::add($b, ':newspaper:', '📰'); - Smilies::add($b, ':rolled-up newspaper:', '🗞'); - Smilies::add($b, ':bookmark tabs:', '📑'); - Smilies::add($b, ':bookmark:', '🔖'); - Smilies::add($b, ':label:', '🏷'); + Smilies::add($b, ':notebook with decorative cover:', '📔'); + Smilies::add($b, ':closed book:', '📕'); + Smilies::add($b, ':open book:', '📖'); + Smilies::add($b, ':green book:', '📗'); + Smilies::add($b, ':blue book:', '📘'); + Smilies::add($b, ':orange book:', '📙'); + Smilies::add($b, ':books:', '📚'); + Smilies::add($b, ':notebook:', '📓'); + Smilies::add($b, ':ledger:', '📒'); + Smilies::add($b, ':page with curl:', '📃'); + Smilies::add($b, ':scroll:', '📜'); + Smilies::add($b, ':page facing up:', '📄'); + Smilies::add($b, ':newspaper:', '📰'); + Smilies::add($b, ':rolled-up newspaper:', '🗞'); + Smilies::add($b, ':bookmark tabs:', '📑'); + Smilies::add($b, ':bookmark:', '🔖'); + Smilies::add($b, ':label:', '🏷'); // money - Smilies::add($b, ':money bag:', '💰'); - Smilies::add($b, ':yen banknote:', '💴'); - Smilies::add($b, ':dollar banknote:', '💵'); - Smilies::add($b, ':euro banknote:', '💶'); - Smilies::add($b, ':pound banknote:', '💷'); - Smilies::add($b, ':money with wings:', '💸'); - Smilies::add($b, ':credit card:', '💳'); - Smilies::add($b, ':receipt:', '🧾'); - Smilies::add($b, ':chart increasing with yen:', '💹'); + Smilies::add($b, ':money bag:', '💰'); + Smilies::add($b, ':yen banknote:', '💴'); + Smilies::add($b, ':dollar banknote:', '💵'); + Smilies::add($b, ':euro banknote:', '💶'); + Smilies::add($b, ':pound banknote:', '💷'); + Smilies::add($b, ':money with wings:', '💸'); + Smilies::add($b, ':credit card:', '💳'); + Smilies::add($b, ':receipt:', '🧾'); + Smilies::add($b, ':chart increasing with yen:', '💹'); // mail - Smilies::add($b, ':envelope:', '✉'); - Smilies::add($b, ':e-mail:', '📧'); - Smilies::add($b, ':incoming envelope:', '📨'); - Smilies::add($b, ':envelope with arrow:', '📩'); - Smilies::add($b, ':outbox tray:', '📤'); - Smilies::add($b, ':inbox tray:', '📥'); - Smilies::add($b, ':package:', '📦'); - Smilies::add($b, ':closed mailbox with raised flag:', '📫'); - Smilies::add($b, ':closed mailbox with lowered flag:', '📪'); - Smilies::add($b, ':open mailbox with raised flag:', '📬'); - Smilies::add($b, ':open mailbox with lowered flag:', '📭'); - Smilies::add($b, ':postbox:', '📮'); - Smilies::add($b, ':ballot box with ballot:', '🗳'); + Smilies::add($b, ':envelope:', '✉'); + Smilies::add($b, ':e-mail:', '📧'); + Smilies::add($b, ':incoming envelope:', '📨'); + Smilies::add($b, ':envelope with arrow:', '📩'); + Smilies::add($b, ':outbox tray:', '📤'); + Smilies::add($b, ':inbox tray:', '📥'); + Smilies::add($b, ':package:', '📦'); + Smilies::add($b, ':closed mailbox with raised flag:', '📫'); + Smilies::add($b, ':closed mailbox with lowered flag:', '📪'); + Smilies::add($b, ':open mailbox with raised flag:', '📬'); + Smilies::add($b, ':open mailbox with lowered flag:', '📭'); + Smilies::add($b, ':postbox:', '📮'); + Smilies::add($b, ':ballot box with ballot:', '🗳'); // writing - Smilies::add($b, ':pencil:', '✏'); - Smilies::add($b, ':black nib:', '✒'); - Smilies::add($b, ':fountain pen:', '🖋'); - Smilies::add($b, ':pen:', '🖊'); - Smilies::add($b, ':paintbrush:', '🖌'); - Smilies::add($b, ':crayon:', '🖍'); - Smilies::add($b, ':memo:', '📝'); + Smilies::add($b, ':pencil:', '✏'); + Smilies::add($b, ':black nib:', '✒'); + Smilies::add($b, ':fountain pen:', '🖋'); + Smilies::add($b, ':pen:', '🖊'); + Smilies::add($b, ':paintbrush:', '🖌'); + Smilies::add($b, ':crayon:', '🖍'); + Smilies::add($b, ':memo:', '📝'); // office - Smilies::add($b, ':briefcase:', '💼'); - Smilies::add($b, ':file folder:', '📁'); - Smilies::add($b, ':open file folder:', '📂'); - Smilies::add($b, ':card index dividers:', '🗂'); - Smilies::add($b, ':calendar:', '📅'); - Smilies::add($b, ':tear-off calendar:', '📆'); - Smilies::add($b, ':spiral notepad:', '🗒'); - Smilies::add($b, ':spiral calendar:', '🗓'); - Smilies::add($b, ':card index:', '📇'); - Smilies::add($b, ':chart increasing:', '📈'); - Smilies::add($b, ':chart decreasing:', '📉'); - Smilies::add($b, ':bar chart:', '📊'); - Smilies::add($b, ':clipboard:', '📋'); - Smilies::add($b, ':pushpin:', '📌'); - Smilies::add($b, ':round pushpin:', '📍'); - Smilies::add($b, ':paperclip:', '📎'); - Smilies::add($b, ':linked paperclips:', '🖇'); - Smilies::add($b, ':straight ruler:', '📏'); - Smilies::add($b, ':triangular ruler:', '📐'); - Smilies::add($b, ':scissors:', '✂'); - Smilies::add($b, ':card file box:', '🗃'); - Smilies::add($b, ':file cabinet:', '🗄'); - Smilies::add($b, ':wastebasket:', '🗑'); + Smilies::add($b, ':briefcase:', '💼'); + Smilies::add($b, ':file folder:', '📁'); + Smilies::add($b, ':open file folder:', '📂'); + Smilies::add($b, ':card index dividers:', '🗂'); + Smilies::add($b, ':calendar:', '📅'); + Smilies::add($b, ':tear-off calendar:', '📆'); + Smilies::add($b, ':spiral notepad:', '🗒'); + Smilies::add($b, ':spiral calendar:', '🗓'); + Smilies::add($b, ':card index:', '📇'); + Smilies::add($b, ':chart increasing:', '📈'); + Smilies::add($b, ':chart decreasing:', '📉'); + Smilies::add($b, ':bar chart:', '📊'); + Smilies::add($b, ':clipboard:', '📋'); + Smilies::add($b, ':pushpin:', '📌'); + Smilies::add($b, ':round pushpin:', '📍'); + Smilies::add($b, ':paperclip:', '📎'); + Smilies::add($b, ':linked paperclips:', '🖇'); + Smilies::add($b, ':straight ruler:', '📏'); + Smilies::add($b, ':triangular ruler:', '📐'); + Smilies::add($b, ':scissors:', '✂'); + Smilies::add($b, ':card file box:', '🗃'); + Smilies::add($b, ':file cabinet:', '🗄'); + Smilies::add($b, ':wastebasket:', '🗑'); // lock - Smilies::add($b, ':locked:', '🔒'); - Smilies::add($b, ':unlocked:', '🔓'); - Smilies::add($b, ':locked with pen:', '🔏'); - Smilies::add($b, ':locked with key:', '🔐'); - Smilies::add($b, ':key:', '🔑'); - Smilies::add($b, ':old key:', '🗝'); + Smilies::add($b, ':locked:', '🔒'); + Smilies::add($b, ':unlocked:', '🔓'); + Smilies::add($b, ':locked with pen:', '🔏'); + Smilies::add($b, ':locked with key:', '🔐'); + Smilies::add($b, ':key:', '🔑'); + Smilies::add($b, ':old key:', '🗝'); // tool - Smilies::add($b, ':hammer:', '🔨'); -// Smilies::add($b, ':axe:', '🪓'); - Smilies::add($b, ':pick:', '⛏'); - Smilies::add($b, ':hammer and pick:', '⚒'); - Smilies::add($b, ':hammer and wrench:', '🛠'); - Smilies::add($b, ':dagger:', '🗡'); + Smilies::add($b, ':hammer:', '🔨'); +// Smilies::add($b, ':axe:', '🪓'); + Smilies::add($b, ':pick:', '⛏'); + Smilies::add($b, ':hammer and pick:', '⚒'); + Smilies::add($b, ':hammer and wrench:', '🛠'); + Smilies::add($b, ':dagger:', '🗡'); Smilies::add($b, ':sabre:', '🗡'); - Smilies::add($b, ':crossed swords:', '⚔'); - Smilies::add($b, ':pistol:', '🔫'); - Smilies::add($b, ':bow and arrow:', '🏹'); - Smilies::add($b, ':shield:', '🛡'); - Smilies::add($b, ':wrench:', '🔧'); - Smilies::add($b, ':nut and bolt:', '🔩'); - Smilies::add($b, ':gear:', '⚙'); - Smilies::add($b, ':clamp:', '🗜'); - Smilies::add($b, ':balance scale:', '⚖'); - Smilies::add($b, ':white cane:', '🦯'); - Smilies::add($b, ':link:', '🔗'); - Smilies::add($b, ':chains:', '⛓'); - Smilies::add($b, ':toolbox:', '🧰'); - Smilies::add($b, ':magnet:', '🧲'); + Smilies::add($b, ':crossed swords:', '⚔'); + Smilies::add($b, ':pistol:', '🔫'); + Smilies::add($b, ':bow and arrow:', '🏹'); + Smilies::add($b, ':shield:', '🛡'); + Smilies::add($b, ':wrench:', '🔧'); + Smilies::add($b, ':nut and bolt:', '🔩'); + Smilies::add($b, ':gear:', '⚙'); + Smilies::add($b, ':clamp:', '🗜'); + Smilies::add($b, ':balance scale:', '⚖'); + Smilies::add($b, ':white cane:', '🦯'); + Smilies::add($b, ':link:', '🔗'); + Smilies::add($b, ':chains:', '⛓'); + Smilies::add($b, ':toolbox:', '🧰'); + Smilies::add($b, ':magnet:', '🧲'); // science - Smilies::add($b, ':alembic:', '⚗'); - Smilies::add($b, ':test tube:', '🧪'); - Smilies::add($b, ':petri dish:', '🧫'); - Smilies::add($b, ':dna:', '🧬'); - Smilies::add($b, ':microscope:', '🔬'); - Smilies::add($b, ':telescope:', '🔭'); - Smilies::add($b, ':satellite antenna:', '📡'); + Smilies::add($b, ':alembic:', '⚗'); + Smilies::add($b, ':test tube:', '🧪'); + Smilies::add($b, ':petri dish:', '🧫'); + Smilies::add($b, ':dna:', '🧬'); + Smilies::add($b, ':microscope:', '🔬'); + Smilies::add($b, ':telescope:', '🔭'); + Smilies::add($b, ':satellite antenna:', '📡'); + Smilies::add($b, ':asterism:', '⁂'); + Smilies::add($b, ':outlines white star:', '颅'); // medical - Smilies::add($b, ':syringe:', '💉'); - Smilies::add($b, ':drop of blood:', '🩸'); - Smilies::add($b, ':pill:', '💊'); - Smilies::add($b, ':adhesive bandage:', '🩹'); - Smilies::add($b, ':stethoscope:', '🩺'); + Smilies::add($b, ':syringe:', '💉'); + Smilies::add($b, ':drop of blood:', '🩸'); + Smilies::add($b, ':pill:', '💊'); + Smilies::add($b, ':adhesive bandage:', '🩹'); + Smilies::add($b, ':stethoscope:', '🩺'); // household - Smilies::add($b, ':door:', '🚪'); - Smilies::add($b, ':bed:', '🛏'); - Smilies::add($b, ':couch and lamp:', '🛋'); -// Smilies::add($b, ':chair:', '🪑'); - Smilies::add($b, ':toilet:', '🚽'); - Smilies::add($b, ':shower:', '🚿'); - Smilies::add($b, ':bathtub:', '🛁'); - Smilies::add($b, ':razor:', '🪒'); - Smilies::add($b, ':lotion bottle:', '🧴'); - Smilies::add($b, ':safety pin:', '🧷'); - Smilies::add($b, ':broom:', '🧹'); - Smilies::add($b, ':basket:', '🧺'); - Smilies::add($b, ':roll of paper:', '🧻'); - Smilies::add($b, ':soap:', '🧼'); - Smilies::add($b, ':sponge:', '🧽'); - Smilies::add($b, ':fire extinguisher:', '🧯'); - Smilies::add($b, ':shopping cart:', '🛒'); + Smilies::add($b, ':door:', '🚪'); + Smilies::add($b, ':bed:', '🛏'); + Smilies::add($b, ':couch and lamp:', '🛋'); +// Smilies::add($b, ':chair:', '🪑'); + Smilies::add($b, ':toilet:', '🚽'); + Smilies::add($b, ':shower:', '🚿'); + Smilies::add($b, ':bathtub:', '🛁'); + Smilies::add($b, ':razor:', '🪒'); + Smilies::add($b, ':lotion bottle:', '🧴'); + Smilies::add($b, ':safety pin:', '🧷'); + Smilies::add($b, ':broom:', '🧹'); + Smilies::add($b, ':basket:', '🧺'); + Smilies::add($b, ':roll of paper:', '🧻'); + Smilies::add($b, ':soap:', '🧼'); + Smilies::add($b, ':sponge:', '🧽'); + Smilies::add($b, ':fire extinguisher:', '🧯'); + Smilies::add($b, ':shopping cart:', '🛒'); // other-object - Smilies::add($b, ':cigarette:', '🚬'); - Smilies::add($b, ':coffin:', '⚰'); - Smilies::add($b, ':funeral urn:', '⚱'); - Smilies::add($b, ':moai:', '🗿'); + Smilies::add($b, ':cigarette:', '🚬'); + Smilies::add($b, ':coffin:', '⚰'); + Smilies::add($b, ':funeral urn:', '⚱'); + Smilies::add($b, ':moai:', '🗿'); // Symbols // transport-sign - Smilies::add($b, ':atm sign:', '🏧'); - Smilies::add($b, ':litter in bin sign:', '🚮'); - Smilies::add($b, ':potable water:', '🚰'); - Smilies::add($b, ':wheelchair symbol:', '♿'); - Smilies::add($b, ':men’s room:', '🚹'); - Smilies::add($b, ':women’s room:', '🚺'); - Smilies::add($b, ':restroom:', '🚻'); - Smilies::add($b, ':baby symbol:', '🚼'); - Smilies::add($b, ':water closet:', '🚾'); - Smilies::add($b, ':passport control:', '🛂'); - Smilies::add($b, ':customs:', '🛃'); - Smilies::add($b, ':baggage claim:', '🛄'); - Smilies::add($b, ':left luggage:', '🛅'); + Smilies::add($b, ':atm sign:', '🏧'); + Smilies::add($b, ':litter in bin sign:', '🚮'); + Smilies::add($b, ':potable water:', '🚰'); + Smilies::add($b, ':wheelchair symbol:', '♿'); + Smilies::add($b, ':men’s room:', '🚹'); + Smilies::add($b, ':women’s room:', '🚺'); + Smilies::add($b, ':restroom:', '🚻'); + Smilies::add($b, ':baby symbol:', '🚼'); + Smilies::add($b, ':water closet:', '🚾'); + Smilies::add($b, ':passport control:', '🛂'); + Smilies::add($b, ':customs:', '🛃'); + Smilies::add($b, ':baggage claim:', '🛄'); + Smilies::add($b, ':left luggage:', '🛅'); // warning - Smilies::add($b, ':warning:', '⚠'); - Smilies::add($b, ':children crossing:', '🚸'); - Smilies::add($b, ':no entry:', '⛔'); - Smilies::add($b, ':prohibited:', '🚫'); - Smilies::add($b, ':no bicycles:', '🚳'); - Smilies::add($b, ':no smoking:', '🚭'); - Smilies::add($b, ':no littering:', '🚯'); - Smilies::add($b, ':non-potable water:', '🚱'); - Smilies::add($b, ':no pedestrians:', '🚷'); - Smilies::add($b, ':no mobile phones:', '📵'); - Smilies::add($b, ':no one under eighteen:', '🔞'); - Smilies::add($b, ':radioactive:', '☢'); - Smilies::add($b, ':biohazard:', '☣'); + Smilies::add($b, ':warning:', '⚠'); + Smilies::add($b, ':children crossing:', '🚸'); + Smilies::add($b, ':no entry:', '⛔'); + Smilies::add($b, ':prohibited:', '🚫'); + Smilies::add($b, ':no bicycles:', '🚳'); + Smilies::add($b, ':no smoking:', '🚭'); + Smilies::add($b, ':no littering:', '🚯'); + Smilies::add($b, ':non-potable water:', '🚱'); + Smilies::add($b, ':no pedestrians:', '🚷'); + Smilies::add($b, ':no mobile phones:', '📵'); + Smilies::add($b, ':no one under eighteen:', '🔞'); + Smilies::add($b, ':radioactive:', '☢'); + Smilies::add($b, ':biohazard:', '☣'); Smilies::add($b, ':army:', '🪖'); // arrow - Smilies::add($b, ':up arrow:', '⬆'); - Smilies::add($b, ':up-right arrow:', '↗'); - Smilies::add($b, ':right arrow:', '➡'); - Smilies::add($b, ':down-right arrow:', '↘'); - Smilies::add($b, ':down arrow:', '⬇'); - Smilies::add($b, ':down-left arrow:', '↙'); - Smilies::add($b, ':left arrow:', '⬅'); - Smilies::add($b, ':up-left arrow:', '↖'); - Smilies::add($b, ':up-down arrow:', '↕'); - Smilies::add($b, ':left-right arrow:', '↔'); - Smilies::add($b, ':right arrow curving left:', '↩'); - Smilies::add($b, ':left arrow curving right:', '↪'); - Smilies::add($b, ':right arrow curving up:', '⤴'); - Smilies::add($b, ':right arrow curving down:', '⤵'); - Smilies::add($b, ':clockwise vertical arrows:', '🔃'); - Smilies::add($b, ':counterclockwise arrows button:', '🔄'); - Smilies::add($b, ':BACK arrow:', '🔙'); - Smilies::add($b, ':END arrow:', '🔚'); - Smilies::add($b, ':ON! arrow:', '🔛'); - Smilies::add($b, ':SOON arrow:', '🔜'); - Smilies::add($b, ':TOP arrow:', '🔝'); + Smilies::add($b, ':up arrow:', '⬆'); + Smilies::add($b, ':up-right arrow:', '↗'); + Smilies::add($b, ':right arrow:', '➡'); + Smilies::add($b, ':down-right arrow:', '↘'); + Smilies::add($b, ':down arrow:', '⬇'); + Smilies::add($b, ':down-left arrow:', '↙'); + Smilies::add($b, ':left arrow:', '⬅'); + Smilies::add($b, ':up-left arrow:', '↖'); + Smilies::add($b, ':up-down arrow:', '↕'); + Smilies::add($b, ':left-right arrow:', '↔'); + Smilies::add($b, ':right arrow curving left:', '↩'); + Smilies::add($b, ':left arrow curving right:', '↪'); + Smilies::add($b, ':right arrow curving up:', '⤴'); + Smilies::add($b, ':right arrow curving down:', '⤵'); + Smilies::add($b, ':clockwise vertical arrows:', '🔃'); + Smilies::add($b, ':counterclockwise arrows button:', '🔄'); + Smilies::add($b, ':BACK arrow:', '🔙'); + Smilies::add($b, ':END arrow:', '🔚'); + Smilies::add($b, ':ON! arrow:', '🔛'); + Smilies::add($b, ':SOON arrow:', '🔜'); + Smilies::add($b, ':TOP arrow:', '🔝'); // religion - Smilies::add($b, ':place of worship:', '🛐'); - Smilies::add($b, ':atom symbol:', '⚛'); - Smilies::add($b, ':om:', '🕉'); - Smilies::add($b, ':star of David:', '✡'); - Smilies::add($b, ':wheel of dharma:', '☸'); - Smilies::add($b, ':yin yang:', '☯'); - Smilies::add($b, ':latin cross:', '✝'); - Smilies::add($b, ':orthodox cross:', '☦'); - Smilies::add($b, ':star and crescent:', '☪'); - Smilies::add($b, ':peace symbol:', '☮'); - Smilies::add($b, ':menorah:', '🕎'); - Smilies::add($b, ':dotted six-pointed star:', '🔯'); + Smilies::add($b, ':place of worship:', '🛐'); + Smilies::add($b, ':atom symbol:', '⚛'); + Smilies::add($b, ':om:', '🕉'); + Smilies::add($b, ':star of David:', '✡'); + Smilies::add($b, ':wheel of dharma:', '☸'); + Smilies::add($b, ':yin yang:', '☯'); + Smilies::add($b, ':latin cross:', '✝'); + Smilies::add($b, ':orthodox cross:', '☦'); + Smilies::add($b, ':star and crescent:', '☪'); + Smilies::add($b, ':peace symbol:', '☮'); + Smilies::add($b, ':menorah:', '🕎'); + Smilies::add($b, ':dotted six-pointed star:', '🔯'); // zodiac - Smilies::add($b, ':Aries:', '♈'); - Smilies::add($b, ':Taurus:', '♉'); - Smilies::add($b, ':Gemini:', '♊'); - Smilies::add($b, ':Cancer:', '♋'); - Smilies::add($b, ':Leo:', '♌'); - Smilies::add($b, ':Virgo:', '♍'); - Smilies::add($b, ':Libra:', '♎'); - Smilies::add($b, ':Scorpio:', '♏'); - Smilies::add($b, ':Sagittarius:', '♐'); - Smilies::add($b, ':Capricorn:', '♑'); - Smilies::add($b, ':Aquarius:', '♒'); - Smilies::add($b, ':Pisces:', '♓'); - Smilies::add($b, ':Ophiuchus:', '⛎'); + Smilies::add($b, ':Aries:', '♈'); + Smilies::add($b, ':Taurus:', '♉'); + Smilies::add($b, ':Gemini:', '♊'); + Smilies::add($b, ':Cancer:', '♋'); + Smilies::add($b, ':Leo:', '♌'); + Smilies::add($b, ':Virgo:', '♍'); + Smilies::add($b, ':Libra:', '♎'); + Smilies::add($b, ':Scorpio:', '♏'); + Smilies::add($b, ':Sagittarius:', '♐'); + Smilies::add($b, ':Capricorn:', '♑'); + Smilies::add($b, ':Aquarius:', '♒'); + Smilies::add($b, ':Pisces:', '♓'); + Smilies::add($b, ':Ophiuchus:', '⛎'); // av-symbol - Smilies::add($b, ':shuffle tracks button:', '🔀'); - Smilies::add($b, ':repeat button:', '🔁'); - Smilies::add($b, ':repeat single button:', '🔂'); - Smilies::add($b, ':play button:', '▶'); - Smilies::add($b, ':fast-forward button:', '⏩'); - Smilies::add($b, ':next track button:', '⏭'); - Smilies::add($b, ':play or pause button:', '⏯'); - Smilies::add($b, ':reverse button:', '◀'); - Smilies::add($b, ':fast reverse button:', '⏪'); - Smilies::add($b, ':last track button:', '⏮'); - Smilies::add($b, ':upwards button:', '🔼'); - Smilies::add($b, ':fast up button:', '⏫'); - Smilies::add($b, ':downwards button:', '🔽'); - Smilies::add($b, ':fast down button:', '⏬'); - Smilies::add($b, ':pause button:', '⏸'); - Smilies::add($b, ':stop button:', '⏹'); - Smilies::add($b, ':record button:', '⏺'); - Smilies::add($b, ':eject button:', '⏏'); - Smilies::add($b, ':cinema:', '🎦'); - Smilies::add($b, ':dim button:', '🔅'); - Smilies::add($b, ':bright button:', '🔆'); - Smilies::add($b, ':antenna bars:', '📶'); - Smilies::add($b, ':vibration mode:', '📳'); - Smilies::add($b, ':mobile phone off:', '📴'); + Smilies::add($b, ':shuffle tracks button:', '🔀'); + Smilies::add($b, ':repeat button:', '🔁'); + Smilies::add($b, ':repeat single button:', '🔂'); + Smilies::add($b, ':play button:', '▶'); + Smilies::add($b, ':fast-forward button:', '⏩'); + Smilies::add($b, ':next track button:', '⏭'); + Smilies::add($b, ':play or pause button:', '⏯'); + Smilies::add($b, ':reverse button:', '◀'); + Smilies::add($b, ':fast reverse button:', '⏪'); + Smilies::add($b, ':last track button:', '⏮'); + Smilies::add($b, ':upwards button:', '🔼'); + Smilies::add($b, ':fast up button:', '⏫'); + Smilies::add($b, ':downwards button:', '🔽'); + Smilies::add($b, ':fast down button:', '⏬'); + Smilies::add($b, ':pause button:', '⏸'); + Smilies::add($b, ':stop button:', '⏹'); + Smilies::add($b, ':record button:', '⏺'); + Smilies::add($b, ':eject button:', '⏏'); + Smilies::add($b, ':cinema:', '🎦'); + Smilies::add($b, ':dim button:', '🔅'); + Smilies::add($b, ':bright button:', '🔆'); + Smilies::add($b, ':antenna bars:', '📶'); + Smilies::add($b, ':vibration mode:', '📳'); + Smilies::add($b, ':mobile phone off:', '📴'); // gender - Smilies::add($b, ':female sign:', '♀'); - Smilies::add($b, ':male sign:', '♂'); + Smilies::add($b, ':female sign:', '♀'); + Smilies::add($b, ':male sign:', '♂'); // math - Smilies::add($b, ':multiply:', '✖'); - Smilies::add($b, ':plus:', '➕'); - Smilies::add($b, ':minus:', '➖'); - Smilies::add($b, ':divide:', '➗'); - Smilies::add($b, ':infinity:', '♾'); + Smilies::add($b, ':multiply:', '✖'); + Smilies::add($b, ':plus:', '➕'); + Smilies::add($b, ':minus:', '➖'); + Smilies::add($b, ':divide:', '➗'); + Smilies::add($b, ':infinity:', '♾'); Smilies::add($b, ':kreisoperator:', '∘'); Smilies::add($b, ':leere menge:', '∅'); Smilies::add($b, ':rundung:', '≈'); @@ -1456,407 +1453,408 @@ function unicode_smilies_smilies(array &$b) Smilies::add($b, ':prozent:', '%'); // punctuation - Smilies::add($b, ':double exclamation mark:', '‼'); - Smilies::add($b, ':exclamation question mark:', '⁉'); - Smilies::add($b, ':question mark:', '❓'); - Smilies::add($b, ':white question mark:', '❔'); - Smilies::add($b, ':white exclamation mark:', '❕'); - Smilies::add($b, ':exclamation mark:', '❗'); - Smilies::add($b, ':wavy dash:', '〰'); + Smilies::add($b, ':double exclamation mark:', '‼'); + Smilies::add($b, ':exclamation question mark:', '⁉'); + Smilies::add($b, ':question mark:', '❓'); + Smilies::add($b, ':white question mark:', '❔'); + Smilies::add($b, ':white exclamation mark:', '❕'); + Smilies::add($b, ':exclamation mark:', '❗'); + Smilies::add($b, ':wavy dash:', '〰'); // currency - Smilies::add($b, ':currency exchange:', '💱'); - Smilies::add($b, ':heavy dollar sign:', '💲'); + Smilies::add($b, ':currency exchange:', '💱'); + Smilies::add($b, ':heavy dollar sign:', '💲'); // other-symbol - Smilies::add($b, ':medical symbol:', '⚕'); - Smilies::add($b, ':recycling symbol:', '♻'); - Smilies::add($b, ':fleur-de-lis:', '⚜'); - Smilies::add($b, ':trident emblem:', '🔱'); - Smilies::add($b, ':name badge:', '📛'); - Smilies::add($b, ':Japanese symbol for beginner:', '🔰'); - Smilies::add($b, ':hollow red circle:', '⭕'); - Smilies::add($b, ':check mark button:', '✅'); - Smilies::add($b, ':check box with check:', '☑'); - Smilies::add($b, ':check mark:', '✔'); - Smilies::add($b, ':cross mark:', '❌'); - Smilies::add($b, ':cross mark button:', '❎'); - Smilies::add($b, ':curly loop:', '➰'); - Smilies::add($b, ':double curly loop:', '➿'); - Smilies::add($b, ':part alternation mark:', '〽'); - Smilies::add($b, ':eight-spoked asterisk:', '✳'); - Smilies::add($b, ':eight-pointed star:', '✴'); - Smilies::add($b, ':sparkle:', '❇'); - Smilies::add($b, ':copyright:', '©'); - Smilies::add($b, ':registered:', '®'); - Smilies::add($b, ':trade mark:', '™'); + Smilies::add($b, ':medical symbol:', '⚕'); + Smilies::add($b, ':recycling symbol:', '♻'); + Smilies::add($b, ':fleur-de-lis:', '⚜'); + Smilies::add($b, ':trident emblem:', '🔱'); + Smilies::add($b, ':name badge:', '📛'); + Smilies::add($b, ':Japanese symbol for beginner:', '🔰'); + Smilies::add($b, ':hollow red circle:', '⭕'); + Smilies::add($b, ':check mark button:', '✅'); + Smilies::add($b, ':check box with check:', '☑'); + Smilies::add($b, ':check mark:', '✔'); + Smilies::add($b, ':cross mark:', '❌'); + Smilies::add($b, ':cross mark button:', '❎'); + Smilies::add($b, ':curly loop:', '➰'); + Smilies::add($b, ':double curly loop:', '➿'); + Smilies::add($b, ':part alternation mark:', '〽'); + Smilies::add($b, ':eight-spoked asterisk:', '✳'); + Smilies::add($b, ':eight-pointed star:', '✴'); + Smilies::add($b, ':sparkle:', '❇'); + Smilies::add($b, ':copyright:', '©'); + Smilies::add($b, ':registered:', '®'); + Smilies::add($b, ':trade mark:', '™'); // keycap - Smilies::add($b, ':keycap: #:', '#️⃣'); - Smilies::add($b, ':keycap: *:', '*️⃣'); - Smilies::add($b, ':keycap: 0:', '0️⃣'); - Smilies::add($b, ':keycap: 1:', '1️⃣'); - Smilies::add($b, ':keycap: 2:', '2️⃣'); - Smilies::add($b, ':keycap: 3:', '3️⃣'); - Smilies::add($b, ':keycap: 4:', '4️⃣'); - Smilies::add($b, ':keycap: 5:', '5️⃣'); - Smilies::add($b, ':keycap: 6:', '6️⃣'); - Smilies::add($b, ':keycap: 7:', '7️⃣'); - Smilies::add($b, ':keycap: 8:', '8️⃣'); - Smilies::add($b, ':keycap: 9:', '9️⃣'); - Smilies::add($b, ':keycap: 10:', '🔟'); + Smilies::add($b, ':keycap: #:', '#️⃣'); + Smilies::add($b, ':keycap: *:', '*️⃣'); + Smilies::add($b, ':keycap: 0:', '0️⃣'); + Smilies::add($b, ':keycap: 1:', '1️⃣'); + Smilies::add($b, ':keycap: 2:', '2️⃣'); + Smilies::add($b, ':keycap: 3:', '3️⃣'); + Smilies::add($b, ':keycap: 4:', '4️⃣'); + Smilies::add($b, ':keycap: 5:', '5️⃣'); + Smilies::add($b, ':keycap: 6:', '6️⃣'); + Smilies::add($b, ':keycap: 7:', '7️⃣'); + Smilies::add($b, ':keycap: 8:', '8️⃣'); + Smilies::add($b, ':keycap: 9:', '9️⃣'); + Smilies::add($b, ':keycap: 10:', '🔟'); // alphanum - Smilies::add($b, ':input latin uppercase:', '🔠'); - Smilies::add($b, ':input latin lowercase:', '🔡'); - Smilies::add($b, ':input numbers:', '🔢'); - Smilies::add($b, ':input symbols:', '🔣'); - Smilies::add($b, ':input latin letters:', '🔤'); - Smilies::add($b, ':A button (blood type):', '🅰'); - Smilies::add($b, ':AB button (blood type):', '🆎'); - Smilies::add($b, ':B button (blood type):', '🅱'); - Smilies::add($b, ':CL button:', '🆑'); - Smilies::add($b, ':COOL button:', '🆒'); + Smilies::add($b, ':input latin uppercase:', '🔠'); + Smilies::add($b, ':input latin lowercase:', '🔡'); + Smilies::add($b, ':input numbers:', '🔢'); + Smilies::add($b, ':input symbols:', '🔣'); + Smilies::add($b, ':input latin letters:', '🔤'); + Smilies::add($b, ':A button (blood type):', '🅰'); + Smilies::add($b, ':AB button (blood type):', '🆎'); + Smilies::add($b, ':B button (blood type):', '🅱'); + Smilies::add($b, ':CL button:', '🆑'); + Smilies::add($b, ':COOL button:', '🆒'); Smilies::add($b, ':cool:', '🆒'); - Smilies::add($b, ':FREE button:', '🆓'); - Smilies::add($b, ':information:', 'ℹ'); - Smilies::add($b, ':ID button:', '🆔'); - Smilies::add($b, ':circled M:', 'Ⓜ'); - Smilies::add($b, ':NEW button:', '🆕'); - Smilies::add($b, ':NG button:', '🆖'); - Smilies::add($b, ':O button (blood type):', '🅾'); - Smilies::add($b, ':OK button:', '🆗'); - Smilies::add($b, ':P button:', '🅿'); - Smilies::add($b, ':SOS button:', '🆘'); - Smilies::add($b, ':UP! button:', '🆙'); - Smilies::add($b, ':VS button:', '🆚'); - Smilies::add($b, ':Japanese “here” button:', '🈁'); - Smilies::add($b, ':Japanese “service charge” button:', '🈂'); - Smilies::add($b, ':Japanese “monthly amount” button:', '🈷'); - Smilies::add($b, ':Japanese “not free of charge” button:', '🈶'); - Smilies::add($b, ':Japanese “reserved” button:', '🈯'); - Smilies::add($b, ':Japanese “bargain” button:', '🉐'); - Smilies::add($b, ':Japanese “discount” button:', '🈹'); - Smilies::add($b, ':Japanese “free of charge” button:', '🈚'); - Smilies::add($b, ':Japanese “prohibited” button:', '🈲'); - Smilies::add($b, ':Japanese “acceptable” button:', '🉑'); - Smilies::add($b, ':Japanese “application” button:', '🈸'); - Smilies::add($b, ':Japanese “passing grade” button:', '🈴'); - Smilies::add($b, ':Japanese “vacancy” button:', '🈳'); - Smilies::add($b, ':Japanese “congratulations” button:', '㊗'); - Smilies::add($b, ':Japanese “secret” button:', '㊙'); - Smilies::add($b, ':Japanese “open for business” button:', '🈺'); - Smilies::add($b, ':Japanese “no vacancy” button:', '🈵'); + Smilies::add($b, ':FREE button:', '🆓'); + Smilies::add($b, ':information:', 'ℹ'); + Smilies::add($b, ':ID button:', '🆔'); + Smilies::add($b, ':circled M:', 'Ⓜ'); + Smilies::add($b, ':NEW button:', '🆕'); + Smilies::add($b, ':NG button:', '🆖'); + Smilies::add($b, ':O button (blood type):', '🅾'); + Smilies::add($b, ':OK button:', '🆗'); + Smilies::add($b, ':P button:', '🅿'); + Smilies::add($b, ':SOS button:', '🆘'); + Smilies::add($b, ':UP! button:', '🆙'); + Smilies::add($b, ':VS button:', '🆚'); + Smilies::add($b, ':Japanese “here” button:', '🈁'); + Smilies::add($b, ':Japanese “service charge” button:', '🈂'); + Smilies::add($b, ':Japanese “monthly amount” button:', '🈷'); + Smilies::add($b, ':Japanese “not free of charge” button:', '🈶'); + Smilies::add($b, ':Japanese “reserved” button:', '🈯'); + Smilies::add($b, ':Japanese “bargain” button:', '🉐'); + Smilies::add($b, ':Japanese “discount” button:', '🈹'); + Smilies::add($b, ':Japanese “free of charge” button:', '🈚'); + Smilies::add($b, ':Japanese “prohibited” button:', '🈲'); + Smilies::add($b, ':Japanese “acceptable” button:', '🉑'); + Smilies::add($b, ':Japanese “application” button:', '🈸'); + Smilies::add($b, ':Japanese “passing grade” button:', '🈴'); + Smilies::add($b, ':Japanese “vacancy” button:', '🈳'); + Smilies::add($b, ':Japanese “congratulations” button:', '㊗'); + Smilies::add($b, ':Japanese “secret” button:', '㊙'); + Smilies::add($b, ':Japanese “open for business” button:', '🈺'); + Smilies::add($b, ':Japanese “no vacancy” button:', '🈵'); // geometric - Smilies::add($b, ':red circle:', '🔴'); -// Smilies::add($b, ':orange circle:', '🟠'); -// Smilies::add($b, ':yellow circle:', '🟡'); -// Smilies::add($b, ':green circle:', '🟢'); - Smilies::add($b, ':blue circle:', '🔵'); -// Smilies::add($b, ':purple circle:', '🟣'); -// Smilies::add($b, ':brown circle:', '🟤'); - Smilies::add($b, ':black circle:', '⚫'); - Smilies::add($b, ':white circle:', '⚪'); -// Smilies::add($b, ':red square:', '🟥'); -// Smilies::add($b, ':orange square:', '🟧'); -// Smilies::add($b, ':yellow square:', '🟨'); -// Smilies::add($b, ':green square:', '🟩'); -// Smilies::add($b, ':blue square:', '🟦'); -// Smilies::add($b, ':purple square:', '🟪'); -// Smilies::add($b, ':brown square:', '🟫'); - Smilies::add($b, ':black large square:', '⬛'); - Smilies::add($b, ':white large square:', '⬜'); - Smilies::add($b, ':black medium square:', '◼'); - Smilies::add($b, ':white medium square:', '◻'); - Smilies::add($b, ':black medium-small square:', '◾'); - Smilies::add($b, ':white medium-small square:', '◽'); - Smilies::add($b, ':black small square:', '▪'); - Smilies::add($b, ':white small square:', '▫'); - Smilies::add($b, ':large orange diamond:', '🔶'); - Smilies::add($b, ':large blue diamond:', '🔷'); - Smilies::add($b, ':small orange diamond:', '🔸'); - Smilies::add($b, ':small blue diamond:', '🔹'); - Smilies::add($b, ':red triangle pointed up:', '🔺'); - Smilies::add($b, ':red triangle pointed down:', '🔻'); - Smilies::add($b, ':diamond with a dot:', '💠'); - Smilies::add($b, ':radio button:', '🔘'); - Smilies::add($b, ':white square button:', '🔳'); - Smilies::add($b, ':black square button:', '🔲'); + Smilies::add($b, ':red circle:', '🔴'); +// Smilies::add($b, ':orange circle:', '🟠'); +// Smilies::add($b, ':yellow circle:', '🟡'); +// Smilies::add($b, ':green circle:', '🟢'); + Smilies::add($b, ':blue circle:', '🔵'); +// Smilies::add($b, ':purple circle:', '🟣'); +// Smilies::add($b, ':brown circle:', '🟤'); + Smilies::add($b, ':black circle:', '⚫'); + Smilies::add($b, ':white circle:', '⚪'); +// Smilies::add($b, ':red square:', '🟥'); +// Smilies::add($b, ':orange square:', '🟧'); +// Smilies::add($b, ':yellow square:', '🟨'); +// Smilies::add($b, ':green square:', '🟩'); +// Smilies::add($b, ':blue square:', '🟦'); +// Smilies::add($b, ':purple square:', '🟪'); +// Smilies::add($b, ':brown square:', '🟫'); + Smilies::add($b, ':black large square:', '⬛'); + Smilies::add($b, ':white large square:', '⬜'); + Smilies::add($b, ':black medium square:', '◼'); + Smilies::add($b, ':white medium square:', '◻'); + Smilies::add($b, ':black medium-small square:', '◾'); + Smilies::add($b, ':white medium-small square:', '◽'); + Smilies::add($b, ':black small square:', '▪'); + Smilies::add($b, ':white small square:', '▫'); + Smilies::add($b, ':large orange diamond:', '🔶'); + Smilies::add($b, ':large blue diamond:', '🔷'); + Smilies::add($b, ':small orange diamond:', '🔸'); + Smilies::add($b, ':small blue diamond:', '🔹'); + Smilies::add($b, ':red triangle pointed up:', '🔺'); + Smilies::add($b, ':red triangle pointed down:', '🔻'); + Smilies::add($b, ':diamond with a dot:', '💠'); + Smilies::add($b, ':radio button:', '🔘'); + Smilies::add($b, ':white square button:', '🔳'); + Smilies::add($b, ':black square button:', '🔲'); // Flags // flag - Smilies::add($b, ':chequered flag:', '🏁'); - Smilies::add($b, ':triangular flag:', '🚩'); - Smilies::add($b, ':crossed flags:', '🎌'); - Smilies::add($b, ':black flag:', '🏴'); - Smilies::add($b, ':white flag:', '🏳'); - Smilies::add($b, ':rainbow flag:', '🏳️‍🌈'); - Smilies::add($b, ':pirate flag:', '🏴‍☠️'); + Smilies::add($b, ':chequered flag:', '🏁'); + Smilies::add($b, ':triangular flag:', '🚩'); + Smilies::add($b, ':crossed flags:', '🎌'); + Smilies::add($b, ':black flag:', '🏴'); + Smilies::add($b, ':white flag:', '🏳'); + Smilies::add($b, ':rainbow flag:', '🏳️‍🌈'); + Smilies::add($b, ':pirate flag:', '🏴‍☠️'); // country-flag - Smilies::add($b, ':ascension island:', '🇦🇨'); - Smilies::add($b, ':andorra:', '🇦🇩'); - Smilies::add($b, ':united arab emirates:', '🇦🇪'); - Smilies::add($b, ':afghanistan:', '🇦🇫'); - Smilies::add($b, ':antigua & barbuda:', '🇦🇬'); - Smilies::add($b, ':anguilla:', '🇦🇮'); - Smilies::add($b, ':albania:', '🇦🇱'); - Smilies::add($b, ':armenia:', '🇦🇲'); - Smilies::add($b, ':angola:', '🇦🇴'); - Smilies::add($b, ':antarctica:', '🇦🇶'); - Smilies::add($b, ':argentina:', '🇦🇷'); - Smilies::add($b, ':americansamoa:', '🇦🇸'); - Smilies::add($b, ':austria:', '🇦🇹'); - Smilies::add($b, ':australia:', '🇦🇺'); - Smilies::add($b, ':aruba:', '🇦🇼'); - Smilies::add($b, ':ålandislands:', '🇦🇽'); - Smilies::add($b, ':azerbaijan:', '🇦🇿'); - Smilies::add($b, ':bosnia&herzegovina:', '🇧🇦'); - Smilies::add($b, ':barbados:', '🇧🇧'); - Smilies::add($b, ':bangladesh:', '🇧🇩'); - Smilies::add($b, ':belgium:', '🇧🇪'); - Smilies::add($b, ':burkinafaso:', '🇧🇫'); - Smilies::add($b, ':bulgaria:', '🇧🇬'); - Smilies::add($b, ':bahrain:', '🇧🇭'); - Smilies::add($b, ':burundi:', '🇧🇮'); - Smilies::add($b, ':benin:', '🇧🇯'); - Smilies::add($b, ':st.barthélemy:', '🇧🇱'); - Smilies::add($b, ':bermuda:', '🇧🇲'); - Smilies::add($b, ':brunei:', '🇧🇳'); - Smilies::add($b, ':bolivia:', '🇧🇴'); - Smilies::add($b, ':caribbeannetherlands:', '🇧🇶'); - Smilies::add($b, ':brazil:', '🇧🇷'); - Smilies::add($b, ':bahamas:', '🇧🇸'); - Smilies::add($b, ':bhutan:', '🇧🇹'); - Smilies::add($b, ':bouvetisland:', '🇧🇻'); - Smilies::add($b, ':botswana:', '🇧🇼'); - Smilies::add($b, ':belarus:', '🇧🇾'); - Smilies::add($b, ':belize:', '🇧🇿'); - Smilies::add($b, ':canada:', '🇨🇦'); - Smilies::add($b, ':cocos(keeling)islands:', '🇨🇨'); - Smilies::add($b, ':congo-kinshasa:', '🇨🇩'); - Smilies::add($b, ':centralafricanrepublic:', '🇨🇫'); - Smilies::add($b, ':congo-brazzaville:', '🇨🇬'); - Smilies::add($b, ':switzerland:', '🇨🇭'); - Smilies::add($b, ':côted’ivoire:', '🇨🇮'); - Smilies::add($b, ':cookislands:', '🇨🇰'); - Smilies::add($b, ':chile:', '🇨🇱'); - Smilies::add($b, ':cameroon:', '🇨🇲'); - Smilies::add($b, ':china:', '🇨🇳'); - Smilies::add($b, ':colombia:', '🇨🇴'); - Smilies::add($b, ':clippertonisland:', '🇨🇵'); - Smilies::add($b, ':costarica:', '🇨🇷'); - Smilies::add($b, ':cuba:', '🇨🇺'); - Smilies::add($b, ':capeverde:', '🇨🇻'); - Smilies::add($b, ':curaçao:', '🇨🇼'); - Smilies::add($b, ':christmasisland:', '🇨🇽'); - Smilies::add($b, ':cyprus:', '🇨🇾'); - Smilies::add($b, ':czechia:', '🇨🇿'); - Smilies::add($b, ':germany:', '🇩🇪'); - Smilies::add($b, ':diegogarcia:', '🇩🇬'); - Smilies::add($b, ':djibouti:', '🇩🇯'); - Smilies::add($b, ':denmark:', '🇩🇰'); - Smilies::add($b, ':dominica:', '🇩🇲'); - Smilies::add($b, ':dominicanrepublic:', '🇩🇴'); - Smilies::add($b, ':algeria:', '🇩🇿'); - Smilies::add($b, ':ceuta&melilla:', '🇪🇦'); - Smilies::add($b, ':ecuador:', '🇪🇨'); - Smilies::add($b, ':estonia:', '🇪🇪'); - Smilies::add($b, ':egypt:', '🇪🇬'); - Smilies::add($b, ':westernsahara:', '🇪🇭'); - Smilies::add($b, ':eritrea:', '🇪🇷'); - Smilies::add($b, ':spain:', '🇪🇸'); - Smilies::add($b, ':ethiopia:', '🇪🇹'); - Smilies::add($b, ':europeanunion:', '🇪🇺'); - Smilies::add($b, ':finland:', '🇫🇮'); - Smilies::add($b, ':fiji:', '🇫🇯'); - Smilies::add($b, ':falklandislands:', '🇫🇰'); - Smilies::add($b, ':micronesia:', '🇫🇲'); - Smilies::add($b, ':faroeislands:', '🇫🇴'); - Smilies::add($b, ':france:', '🇫🇷'); - Smilies::add($b, ':gabon:', '🇬🇦'); - Smilies::add($b, ':unitedkingdom:', '🇬🇧'); - Smilies::add($b, ':grenada:', '🇬🇩'); - Smilies::add($b, ':georgia:', '🇬🇪'); - Smilies::add($b, ':frenchguiana:', '🇬🇫'); - Smilies::add($b, ':guernsey:', '🇬🇬'); - Smilies::add($b, ':ghana:', '🇬🇭'); - Smilies::add($b, ':gibraltar:', '🇬🇮'); - Smilies::add($b, ':greenland:', '🇬🇱'); - Smilies::add($b, ':gambia:', '🇬🇲'); - Smilies::add($b, ':guinea:', '🇬🇳'); - Smilies::add($b, ':guadeloupe:', '🇬🇵'); - Smilies::add($b, ':equatorialguinea:', '🇬🇶'); - Smilies::add($b, ':greece:', '🇬🇷'); - Smilies::add($b, ':southgeorgia&southsandwichislands:', '🇬🇸'); - Smilies::add($b, ':guatemala:', '🇬🇹'); - Smilies::add($b, ':guam:', '🇬🇺'); - Smilies::add($b, ':guinea-bissau:', '🇬🇼'); - Smilies::add($b, ':guyana:', '🇬🇾'); - Smilies::add($b, ':hongkongsarchina:', '🇭🇰'); - Smilies::add($b, ':heard&mcdonaldislands:', '🇭🇲'); - Smilies::add($b, ':honduras:', '🇭🇳'); - Smilies::add($b, ':croatia:', '🇭🇷'); - Smilies::add($b, ':haiti:', '🇭🇹'); - Smilies::add($b, ':hungary:', '🇭🇺'); - Smilies::add($b, ':canaryislands:', '🇮🇨'); - Smilies::add($b, ':indonesia:', '🇮🇩'); - Smilies::add($b, ':ireland:', '🇮🇪'); - Smilies::add($b, ':israel:', '🇮🇱'); - Smilies::add($b, ':isleofman:', '🇮🇲'); - Smilies::add($b, ':india:', '🇮🇳'); - Smilies::add($b, ':britishindianoceanterritory:', '🇮🇴'); - Smilies::add($b, ':iraq:', '🇮🇶'); - Smilies::add($b, ':iran:', '🇮🇷'); - Smilies::add($b, ':iceland:', '🇮🇸'); - Smilies::add($b, ':italy:', '🇮🇹'); - Smilies::add($b, ':jersey:', '🇯🇪'); - Smilies::add($b, ':jamaica:', '🇯🇲'); - Smilies::add($b, ':jordan:', '🇯🇴'); - Smilies::add($b, ':japan:', '🇯🇵'); - Smilies::add($b, ':kenya:', '🇰🇪'); - Smilies::add($b, ':kyrgyzstan:', '🇰🇬'); - Smilies::add($b, ':cambodia:', '🇰🇭'); - Smilies::add($b, ':kiribati:', '🇰🇮'); - Smilies::add($b, ':comoros:', '🇰🇲'); - Smilies::add($b, ':st.kitts&nevis:', '🇰🇳'); - Smilies::add($b, ':northkorea:', '🇰🇵'); - Smilies::add($b, ':southkorea:', '🇰🇷'); - Smilies::add($b, ':kuwait:', '🇰🇼'); - Smilies::add($b, ':caymanislands:', '🇰🇾'); - Smilies::add($b, ':kazakhstan:', '🇰🇿'); - Smilies::add($b, ':laos:', '🇱🇦'); - Smilies::add($b, ':lebanon:', '🇱🇧'); - Smilies::add($b, ':st.lucia:', '🇱🇨'); - Smilies::add($b, ':liechtenstein:', '🇱🇮'); - Smilies::add($b, ':srilanka:', '🇱🇰'); - Smilies::add($b, ':liberia:', '🇱🇷'); - Smilies::add($b, ':lesotho:', '🇱🇸'); - Smilies::add($b, ':lithuania:', '🇱🇹'); - Smilies::add($b, ':luxembourg:', '🇱🇺'); - Smilies::add($b, ':latvia:', '🇱🇻'); - Smilies::add($b, ':libya:', '🇱🇾'); - Smilies::add($b, ':morocco:', '🇲🇦'); - Smilies::add($b, ':monaco:', '🇲🇨'); - Smilies::add($b, ':moldova:', '🇲🇩'); - Smilies::add($b, ':montenegro:', '🇲🇪'); - Smilies::add($b, ':st.martin:', '🇲🇫'); - Smilies::add($b, ':madagascar:', '🇲🇬'); - Smilies::add($b, ':marshallislands:', '🇲🇭'); - Smilies::add($b, ':northmacedonia:', '🇲🇰'); - Smilies::add($b, ':mali:', '🇲🇱'); - Smilies::add($b, ':myanmar(burma):', '🇲🇲'); - Smilies::add($b, ':mongolia:', '🇲🇳'); - Smilies::add($b, ':macaosarchina:', '🇲🇴'); - Smilies::add($b, ':northernmarianaislands:', '🇲🇵'); - Smilies::add($b, ':martinique:', '🇲🇶'); - Smilies::add($b, ':mauritania:', '🇲🇷'); - Smilies::add($b, ':montserrat:', '🇲🇸'); - Smilies::add($b, ':malta:', '🇲🇹'); - Smilies::add($b, ':mauritius:', '🇲🇺'); - Smilies::add($b, ':maldives:', '🇲🇻'); - Smilies::add($b, ':malawi:', '🇲🇼'); - Smilies::add($b, ':mexico:', '🇲🇽'); - Smilies::add($b, ':malaysia:', '🇲🇾'); - Smilies::add($b, ':mozambique:', '🇲🇿'); - Smilies::add($b, ':namibia:', '🇳🇦'); - Smilies::add($b, ':newcaledonia:', '🇳🇨'); - Smilies::add($b, ':niger:', '🇳🇪'); - Smilies::add($b, ':norfolkisland:', '🇳🇫'); - Smilies::add($b, ':nigeria:', '🇳🇬'); - Smilies::add($b, ':nicaragua:', '🇳🇮'); - Smilies::add($b, ':netherlands:', '🇳🇱'); - Smilies::add($b, ':norway:', '🇳🇴'); - Smilies::add($b, ':nepal:', '🇳🇵'); - Smilies::add($b, ':nauru:', '🇳🇷'); - Smilies::add($b, ':niue:', '🇳🇺'); - Smilies::add($b, ':newzealand:', '🇳🇿'); - Smilies::add($b, ':oman:', '🇴🇲'); - Smilies::add($b, ':panama:', '🇵🇦'); - Smilies::add($b, ':peru:', '🇵🇪'); - Smilies::add($b, ':frenchpolynesia:', '🇵🇫'); - Smilies::add($b, ':papuanewguinea:', '🇵🇬'); - Smilies::add($b, ':philippines:', '🇵🇭'); - Smilies::add($b, ':pakistan:', '🇵🇰'); - Smilies::add($b, ':poland:', '🇵🇱'); - Smilies::add($b, ':st.pierre&miquelon:', '🇵🇲'); - Smilies::add($b, ':pitcairnislands:', '🇵🇳'); - Smilies::add($b, ':puertorico:', '🇵🇷'); - Smilies::add($b, ':palestinianterritories:', '🇵🇸'); - Smilies::add($b, ':portugal:', '🇵🇹'); - Smilies::add($b, ':palau:', '🇵🇼'); - Smilies::add($b, ':paraguay:', '🇵🇾'); - Smilies::add($b, ':qatar:', '🇶🇦'); - Smilies::add($b, ':réunion:', '🇷🇪'); - Smilies::add($b, ':romania:', '🇷🇴'); - Smilies::add($b, ':serbia:', '🇷🇸'); - Smilies::add($b, ':russia:', '🇷🇺'); - Smilies::add($b, ':rwanda:', '🇷🇼'); - Smilies::add($b, ':saudiarabia:', '🇸🇦'); - Smilies::add($b, ':solomonislands:', '🇸🇧'); - Smilies::add($b, ':seychelles:', '🇸🇨'); - Smilies::add($b, ':sudan:', '🇸🇩'); - Smilies::add($b, ':sweden:', '🇸🇪'); - Smilies::add($b, ':singapore:', '🇸🇬'); - Smilies::add($b, ':st.helena:', '🇸🇭'); - Smilies::add($b, ':slovenia:', '🇸🇮'); - Smilies::add($b, ':svalbard&janmayen:', '🇸🇯'); - Smilies::add($b, ':slovakia:', '🇸🇰'); - Smilies::add($b, ':sierraleone:', '🇸🇱'); - Smilies::add($b, ':sanmarino:', '🇸🇲'); - Smilies::add($b, ':senegal:', '🇸🇳'); - Smilies::add($b, ':somalia:', '🇸🇴'); - Smilies::add($b, ':suriname:', '🇸🇷'); - Smilies::add($b, ':southsudan:', '🇸🇸'); - Smilies::add($b, ':sãotomé&príncipe:', '🇸🇹'); - Smilies::add($b, ':elsalvador:', '🇸🇻'); - Smilies::add($b, ':sintmaarten:', '🇸🇽'); - Smilies::add($b, ':syria:', '🇸🇾'); - Smilies::add($b, ':eswatini:', '🇸🇿'); - Smilies::add($b, ':tristandacunha:', '🇹🇦'); - Smilies::add($b, ':turks&caicosislands:', '🇹🇨'); - Smilies::add($b, ':chad:', '🇹🇩'); - Smilies::add($b, ':frenchsouthernterritories:', '🇹🇫'); - Smilies::add($b, ':togo:', '🇹🇬'); - Smilies::add($b, ':thailand:', '🇹🇭'); - Smilies::add($b, ':tajikistan:', '🇹🇯'); - Smilies::add($b, ':tokelau:', '🇹🇰'); - Smilies::add($b, ':timor-leste:', '🇹🇱'); - Smilies::add($b, ':turkmenistan:', '🇹🇲'); - Smilies::add($b, ':tunisia:', '🇹🇳'); - Smilies::add($b, ':tonga:', '🇹🇴'); - Smilies::add($b, ':turkey:', '🇹🇷'); - Smilies::add($b, ':trinidad&tobago:', '🇹🇹'); - Smilies::add($b, ':tuvalu:', '🇹🇻'); - Smilies::add($b, ':taiwan:', '🇹🇼'); - Smilies::add($b, ':tanzania:', '🇹🇿'); - Smilies::add($b, ':ukraine:', '🇺🇦'); - Smilies::add($b, ':uganda:', '🇺🇬'); - Smilies::add($b, ':u.s.outlyingislands:', '🇺🇲'); - Smilies::add($b, ':unitednations:', '🇺🇳'); - Smilies::add($b, ':unitedstates:', '🇺🇸'); - Smilies::add($b, ':uruguay:', '🇺🇾'); - Smilies::add($b, ':uzbekistan:', '🇺🇿'); - Smilies::add($b, ':vaticancity:', '🇻🇦'); - Smilies::add($b, ':st.vincent&grenadines:', '🇻🇨'); - Smilies::add($b, ':venezuela:', '🇻🇪'); - Smilies::add($b, ':britishvirginislands:', '🇻🇬'); - Smilies::add($b, ':u.s.virginislands:', '🇻🇮'); - Smilies::add($b, ':vietnam:', '🇻🇳'); - Smilies::add($b, ':vanuatu:', '🇻🇺'); - Smilies::add($b, ':wallis&futuna:', '🇼🇫'); - Smilies::add($b, ':samoa:', '🇼🇸'); - Smilies::add($b, ':kosovo:', '🇽🇰'); - Smilies::add($b, ':yemen:', '🇾🇪'); - Smilies::add($b, ':mayotte:', '🇾🇹'); - Smilies::add($b, ':southafrica:', '🇿🇦'); - Smilies::add($b, ':zambia:', '🇿🇲'); - Smilies::add($b, ':zimbabwe:', '🇿🇼'); + Smilies::add($b, ':ascension island:', '🇦🇨'); + Smilies::add($b, ':andorra:', '🇦🇩'); + Smilies::add($b, ':united arab emirates:', '🇦🇪'); + Smilies::add($b, ':afghanistan:', '🇦🇫'); + Smilies::add($b, ':antigua & barbuda:', '🇦🇬'); + Smilies::add($b, ':anguilla:', '🇦🇮'); + Smilies::add($b, ':albania:', '🇦🇱'); + Smilies::add($b, ':armenia:', '🇦🇲'); + Smilies::add($b, ':angola:', '🇦🇴'); + Smilies::add($b, ':antarctica:', '🇦🇶'); + Smilies::add($b, ':argentina:', '🇦🇷'); + Smilies::add($b, ':americansamoa:', '🇦🇸'); + Smilies::add($b, ':austria:', '🇦🇹'); + Smilies::add($b, ':australia:', '🇦🇺'); + Smilies::add($b, ':aruba:', '🇦🇼'); + Smilies::add($b, ':ålandislands:', '🇦🇽'); + Smilies::add($b, ':azerbaijan:', '🇦🇿'); + Smilies::add($b, ':bosnia&herzegovina:', '🇧🇦'); + Smilies::add($b, ':barbados:', '🇧🇧'); + Smilies::add($b, ':bangladesh:', '🇧🇩'); + Smilies::add($b, ':belgium:', '🇧🇪'); + Smilies::add($b, ':burkinafaso:', '🇧🇫'); + Smilies::add($b, ':bulgaria:', '🇧🇬'); + Smilies::add($b, ':bahrain:', '🇧🇭'); + Smilies::add($b, ':burundi:', '🇧🇮'); + Smilies::add($b, ':benin:', '🇧🇯'); + Smilies::add($b, ':st.barthélemy:', '🇧🇱'); + Smilies::add($b, ':bermuda:', '🇧🇲'); + Smilies::add($b, ':brunei:', '🇧🇳'); + Smilies::add($b, ':bolivia:', '🇧🇴'); + Smilies::add($b, ':caribbeannetherlands:', '🇧🇶'); + Smilies::add($b, ':brazil:', '🇧🇷'); + Smilies::add($b, ':bahamas:', '🇧🇸'); + Smilies::add($b, ':bhutan:', '🇧🇹'); + Smilies::add($b, ':bouvetisland:', '🇧🇻'); + Smilies::add($b, ':botswana:', '🇧🇼'); + Smilies::add($b, ':belarus:', '🇧🇾'); + Smilies::add($b, ':belize:', '🇧🇿'); + Smilies::add($b, ':canada:', '🇨🇦'); + Smilies::add($b, ':cocos(keeling)islands:', '🇨🇨'); + Smilies::add($b, ':congo-kinshasa:', '🇨🇩'); + Smilies::add($b, ':centralafricanrepublic:', '🇨🇫'); + Smilies::add($b, ':congo-brazzaville:', '🇨🇬'); + Smilies::add($b, ':switzerland:', '🇨🇭'); + Smilies::add($b, ':côted’ivoire:', '🇨🇮'); + Smilies::add($b, ':cookislands:', '🇨🇰'); + Smilies::add($b, ':chile:', '🇨🇱'); + Smilies::add($b, ':cameroon:', '🇨🇲'); + Smilies::add($b, ':china:', '🇨🇳'); + Smilies::add($b, ':colombia:', '🇨🇴'); + Smilies::add($b, ':clippertonisland:', '🇨🇵'); + Smilies::add($b, ':costarica:', '🇨🇷'); + Smilies::add($b, ':cuba:', '🇨🇺'); + Smilies::add($b, ':capeverde:', '🇨🇻'); + Smilies::add($b, ':curaçao:', '🇨🇼'); + Smilies::add($b, ':christmasisland:', '🇨🇽'); + Smilies::add($b, ':cyprus:', '🇨🇾'); + Smilies::add($b, ':czechia:', '🇨🇿'); + Smilies::add($b, ':germany:', '🇩🇪'); + Smilies::add($b, ':diegogarcia:', '🇩🇬'); + Smilies::add($b, ':djibouti:', '🇩🇯'); + Smilies::add($b, ':denmark:', '🇩🇰'); + Smilies::add($b, ':dominica:', '🇩🇲'); + Smilies::add($b, ':dominicanrepublic:', '🇩🇴'); + Smilies::add($b, ':algeria:', '🇩🇿'); + Smilies::add($b, ':ceuta&melilla:', '🇪🇦'); + Smilies::add($b, ':ecuador:', '🇪🇨'); + Smilies::add($b, ':estonia:', '🇪🇪'); + Smilies::add($b, ':egypt:', '🇪🇬'); + Smilies::add($b, ':westernsahara:', '🇪🇭'); + Smilies::add($b, ':eritrea:', '🇪🇷'); + Smilies::add($b, ':spain:', '🇪🇸'); + Smilies::add($b, ':ethiopia:', '🇪🇹'); + Smilies::add($b, ':europeanunion:', '🇪🇺'); + Smilies::add($b, ':finland:', '🇫🇮'); + Smilies::add($b, ':fiji:', '🇫🇯'); + Smilies::add($b, ':falklandislands:', '🇫🇰'); + Smilies::add($b, ':micronesia:', '🇫🇲'); + Smilies::add($b, ':faroeislands:', '🇫🇴'); + Smilies::add($b, ':france:', '🇫🇷'); + Smilies::add($b, ':gabon:', '🇬🇦'); + Smilies::add($b, ':unitedkingdom:', '🇬🇧'); + Smilies::add($b, ':grenada:', '🇬🇩'); + Smilies::add($b, ':georgia:', '🇬🇪'); + Smilies::add($b, ':frenchguiana:', '🇬🇫'); + Smilies::add($b, ':guernsey:', '🇬🇬'); + Smilies::add($b, ':ghana:', '🇬🇭'); + Smilies::add($b, ':gibraltar:', '🇬🇮'); + Smilies::add($b, ':greenland:', '🇬🇱'); + Smilies::add($b, ':gambia:', '🇬🇲'); + Smilies::add($b, ':guinea:', '🇬🇳'); + Smilies::add($b, ':guadeloupe:', '🇬🇵'); + Smilies::add($b, ':equatorialguinea:', '🇬🇶'); + Smilies::add($b, ':greece:', '🇬,;🇷'); + Smilies::add($b, ':southgeorgia&southsandwichislands:', '🇬🇸'); + Smilies::add($b, ':guatemala:', '🇬🇹'); + Smilies::add($b, ':guam:', '🇬🇺'); + Smilies::add($b, ':guinea-bissau:', '🇬🇼'); + Smilies::add($b, ':guyana:', '🇬🇾'); + Smilies::add($b, ':hongkongsarchina:', '🇭🇰'); + Smilies::add($b, ':heard&mcdonaldislands:', '🇭🇲'); + Smilies::add($b, ':honduras:', '🇭🇳'); + Smilies::add($b, ':croatia:', '🇭🇷'); + Smilies::add($b, ':haiti:', '🇭🇹'); + Smilies::add($b, ':hungary:', '🇭🇺'); + Smilies::add($b, ':canaryislands:', '🇮🇨'); + Smilies::add($b, ':indonesia:', '🇮🇩'); + Smilies::add($b, ':ireland:', '🇮🇪'); + Smilies::add($b, ':israel:', '🇮🇱'); + Smilies::add($b, ':isleofman:', '🇮🇲'); + Smilies::add($b, ':india:', '🇮🇳'); + Smilies::add($b, ':britishindianoceanterritory:', '🇮🇴'); + Smilies::add($b, ':iraq:', '🇮🇶'); + Smilies::add($b, ':iran:', '🇮🇷'); + Smilies::add($b, ':iceland:', '🇮🇸'); + Smilies::add($b, ':italy:', '🇮🇹'); + Smilies::add($b, ':jersey:', '🇯🇪'); + Smilies::add($b, ':jamaica:', '🇯🇲'); + Smilies::add($b, ':jordan:', '🇯🇴'); + Smilies::add($b, ':japan:', '🇯🇵'); + Smilies::add($b, ':kenya:', '🇰🇪'); + Smilies::add($b, ':kyrgyzstan:', '🇰🇬'); + Smilies::add($b, ':cambodia:', '🇰🇭'); + Smilies::add($b, ':kiribati:', '🇰🇮'); + Smilies::add($b, ':comoros:', '🇰🇲'); + Smilies::add($b, ':st.kitts&nevis:', '🇰🇳'); + Smilies::add($b, ':northkorea:', '🇰🇵'); + Smilies::add($b, ':southkorea:', '🇰🇷'); + Smilies::add($b, ':kuwait:', '🇰🇼'); + Smilies::add($b, ':caymanislands:', '🇰🇾'); + Smilies::add($b, ':kazakhstan:', '🇰🇿'); + Smilies::add($b, ':laos:', '🇱🇦'); + Smilies::add($b, ':lebanon:', '🇱🇧'); + Smilies::add($b, ':st.lucia:', '🇱🇨'); + Smilies::add($b, ':liechtenstein:', '🇱🇮'); + Smilies::add($b, ':srilanka:', '🇱🇰'); + Smilies::add($b, ':liberia:', '🇱🇷'); + Smilies::add($b, ':lesotho:', '🇱🇸'); + Smilies::add($b, ':lithuania:', '🇱🇹'); + Smilies::add($b, ':luxembourg:', '🇱🇺'); + Smilies::add($b, ':latvia:', '🇱🇻'); + Smilies::add($b, ':libya:', '🇱🇾'); + Smilies::add($b, ':morocco:', '🇲🇦'); + Smilies::add($b, ':monaco:', '🇲🇨'); + Smilies::add($b, ':moldova:', '🇲🇩'); + Smilies::add($b, ':montenegro:', '🇲🇪'); + Smilies::add($b, ':st.martin:', '🇲🇫'); + Smilies::add($b, ':madagascar:', '🇲🇬'); + Smilies::add($b, ':marshallislands:', '🇲🇭'); + Smilies::add($b, ':northmacedonia:', '🇲🇰'); + Smilies::add($b, ':mali:', '🇲🇱'); + Smilies::add($b, ':myanmar(burma):', '🇲🇲'); + Smilies::add($b, ':mongolia:', '🇲🇳'); + Smilies::add($b, ':macaosarchina:', '🇲🇴'); + Smilies::add($b, ':northernmarianaislands:', '🇲🇵'); + Smilies::add($b, ':martinique:', '🇲🇶'); + Smilies::add($b, ':mauritania:', '🇲🇷'); + Smilies::add($b, ':montserrat:', '🇲🇸'); + Smilies::add($b, ':malta:', '🇲🇹'); + Smilies::add($b, ':mauritius:', '🇲🇺'); + Smilies::add($b, ':maldives:', '🇲🇻'); + Smilies::add($b, ':malawi:', '🇲🇼'); + Smilies::add($b, ':mexico:', '🇲🇽'); + Smilies::add($b, ':malaysia:', '🇲🇾'); + Smilies::add($b, ':mozambique:', '🇲🇿'); + Smilies::add($b, ':namibia:', '🇳🇦'); + Smilies::add($b, ':newcaledonia:', '🇳🇨'); + Smilies::add($b, ':niger:', '🇳🇪'); + Smilies::add($b, ':norfolkisland:', '🇳🇫'); + Smilies::add($b, ':nigeria:', '🇳🇬'); + Smilies::add($b, ':nicaragua:', '🇳🇮'); + Smilies::add($b, ':netherlands:', '🇳🇱'); + Smilies::add($b, ':norway:', '🇳🇴'); + Smilies::add($b, ':nepal:', '🇳🇵'); + Smilies::add($b, ':nauru:', '🇳🇷'); + Smilies::add($b, ':niue:', '🇳🇺'); + Smilies::add($b, ':newzealand:', '🇳🇿'); + Smilies::add($b, ':oman:', '🇴🇲'); + Smilies::add($b, ':panama:', '🇵🇦'); + Smilies::add($b, ':peru:', '🇵🇪'); + Smilies::add($b, ':frenchpolynesia:', '🇵🇫'); + Smilies::add($b, ':papuanewguinea:', '🇵🇬'); + Smilies::add($b, ':philippines:', '🇵🇭'); + Smilies::add($b, ':pakistan:', '🇵🇰'); + Smilies::add($b, ':poland:', '🇵🇱'); + Smilies::add($b, ':st.pierre&miquelon:', '🇵🇲'); + Smilies::add($b, ':pitcairnislands:', '🇵🇳'); + Smilies::add($b, ':puertorico:', '🇵🇷'); + Smilies::add($b, ':palestinianterritories:', '🇵🇸'); + Smilies::add($b, ':portugal:', '🇵🇹'); + Smilies::add($b, ':palau:', '🇵🇼'); + Smilies::add($b, ':paraguay:', '🇵🇾'); + Smilies::add($b, ':qatar:', '🇶🇦'); + Smilies::add($b, ':réunion:', '🇷🇪'); + Smilies::add($b, ':romania:', '🇷🇴'); + Smilies::add($b, ':serbia:', '🇷🇸'); + Smilies::add($b, ':russia:', '🇷🇺'); + Smilies::add($b, ':rwanda:', '🇷🇼'); + Smilies::add($b, ':saudiarabia:', '🇸🇦'); + Smilies::add($b, ':solomonislands:', '🇸🇧'); + Smilies::add($b, ':seychelles:', '🇸🇨'); + Smilies::add($b, ':sudan:', '🇸🇩'); + Smilies::add($b, ':sweden:', '🇸🇪'); + Smilies::add($b, ':singapore:', '🇸🇬'); + Smilies::add($b, ':st.helena:', '🇸🇭'); + Smilies::add($b, ':slovenia:', '🇸🇮'); + Smilies::add($b, ':svalbard&janmayen:', '🇸🇯'); + Smilies::add($b, ':slovakia:', '🇸🇰'); + Smilies::add($b, ':sierraleone:', '🇸🇱'); + Smilies::add($b, ':sanmarino:', '🇸🇲'); + Smilies::add($b, ':senegal:', '🇸🇳'); + Smilies::add($b, ':somalia:', '🇸🇴'); + Smilies::add($b, ':suriname:', '🇸🇷'); + Smilies::add($b, ':southsudan:', '🇸🇸'); + Smilies::add($b, ':sãotomé&príncipe:', '🇸🇹'); + Smilies::add($b, ':elsalvador:', '🇸🇻'); + Smilies::add($b, ':sintmaarten:', '🇸🇽'); + Smilies::add($b, ':syria:', '🇸🇾'); + Smilies::add($b, ':eswatini:', '🇸🇿'); + Smilies::add($b, ':tristandacunha:', '🇹🇦'); + Smilies::add($b, ':turks&caicosislands:', '🇹🇨'); + Smilies::add($b, ':chad:', '🇹🇩'); + Smilies::add($b, ':frenchsouthernterritories:', '🇹🇫'); + Smilies::add($b, ':togo:', '🇹🇬'); + Smilies::add($b, ':thailand:', '🇹🇭'); + Smilies::add($b, ':tajikistan:', '🇹🇯'); + Smilies::add($b, ':tokelau:', '🇹🇰'); + Smilies::add($b, ':timor-leste:', '🇹🇱'); + Smilies::add($b, ':turkmenistan:', '🇹🇲'); + Smilies::add($b, ':tunisia:', '🇹🇳'); + Smilies::add($b, ':tonga:', '🇹🇴'); + Smilies::add($b, ':turkey:', '🇹🇷'); + Smilies::add($b, ':trinidad&tobago:', '🇹🇹'); + Smilies::add($b, ':tuvalu:', '🇹🇻'); + Smilies::add($b, ':taiwan:', '🇹🇼'); + Smilies::add($b, ':tanzania:', '🇹🇿'); + Smilies::add($b, ':ukraine:', '🇺🇦'); + Smilies::add($b, ':uganda:', '🇺🇬'); + Smilies::add($b, ':u.s.outlyingislands:', '🇺🇲'); + Smilies::add($b, ':unitednations:', '🇺🇳'); + Smilies::add($b, ':unitedstates:', '🇺🇸'); + Smilies::add($b, ':uruguay:', '🇺🇾'); + Smilies::add($b, ':uzbekistan:', '🇺🇿'); + Smilies::add($b, ':vaticancity:', '🇻🇦'); + Smilies::add($b, ':st.vincent&grenadines:', '🇻🇨'); + Smilies::add($b, ':venezuela:', '🇻🇪'); + Smilies::add($b, ':britishvirginislands:', '🇻🇬'); + Smilies::add($b, ':u.s.virginislands:', '🇻🇮'); + Smilies::add($b, ':vietnam:', '🇻🇳'); + Smilies::add($b, ':vanuatu:', '🇻🇺'); + Smilies::add($b, ':wallis&futuna:', '🇼🇫'); + Smilies::add($b, ':samoa:', '🇼🇸'); + Smilies::add($b, ':kosovo:', '🇽🇰'); + Smilies::add($b, ':yemen:', '🇾🇪'); + Smilies::add($b, ':mayotte:', '🇾🇹'); + Smilies::add($b, ':southafrica:', '🇿🇦'); + Smilies::add($b, ':zambia:', '🇿🇲'); + Smilies::add($b, ':zimbabwe:', '🇿🇼'); // subdivision-flag - Smilies::add($b, ':england:', '🏴󠁧󠁢󠁥󠁮󠁧󠁿'); - Smilies::add($b, ':scotland:', '🏴󠁧󠁢󠁳󠁴󠁿'); - Smilies::add($b, ':wales:', '🏴󠁧󠁢󠁷󠁬󠁳󠁿'); + Smilies::add($b, ':england:', '🏴󠁧󠁢󠁥󠁮󠁧󠁿'); + Smilies::add($b, ':scotland:', '🏴󠁧󠁢󠁳󠁴󠁿'); + Smilies::add($b, ':wales:', '🏴󠁧󠁢󠁷󠁬󠁳󠁿'); } + diff --git a/viewsrc/viewsrc.php b/viewsrc/viewsrc.php index c4d21ccb..bd07b541 100644 --- a/viewsrc/viewsrc.php +++ b/viewsrc/viewsrc.php @@ -7,7 +7,6 @@ * */ -use Friendica\App; use Friendica\Core\Hook; use Friendica\DI; diff --git a/webdav_storage/src/WebDavConfig.php b/webdav_storage/src/WebDavConfig.php index 2236e97a..320b06a2 100644 --- a/webdav_storage/src/WebDavConfig.php +++ b/webdav_storage/src/WebDavConfig.php @@ -52,7 +52,7 @@ class WebDavConfig implements ICanConfigureStorage $this->config = $config; $this->client = $client; - $this->authOptions = null; + $this->authOptions = []; if (!empty($this->config->get('webdav', 'username'))) { $this->authOptions = [ diff --git a/webdav_storage/webdav_storage.php b/webdav_storage/webdav_storage.php index adcbea29..fd2eb0d9 100644 --- a/webdav_storage/webdav_storage.php +++ b/webdav_storage/webdav_storage.php @@ -8,11 +8,10 @@ use Friendica\Addon\webdav_storage\src\WebDav; use Friendica\Addon\webdav_storage\src\WebDavConfig; -use Friendica\App; use Friendica\Core\Hook; use Friendica\DI; -function webdav_storage_install($a) +function webdav_storage_install() { Hook::register('storage_instance' , __FILE__, 'webdav_storage_instance'); Hook::register('storage_config' , __FILE__, 'webdav_storage_config'); diff --git a/webrtc/webrtc.php b/webrtc/webrtc.php index e142b374..e5d4ce6e 100644 --- a/webrtc/webrtc.php +++ b/webrtc/webrtc.php @@ -7,7 +7,6 @@ * Author: Tobias Diekershoff */ -use Friendica\App; use Friendica\Core\Hook; use Friendica\Core\Renderer; use Friendica\DI; diff --git a/wppost/wppost.php b/wppost/wppost.php index e27079aa..de216806 100644 --- a/wppost/wppost.php +++ b/wppost/wppost.php @@ -9,7 +9,6 @@ use Friendica\Content\Text\BBCode; use Friendica\Content\Text\HTML; use Friendica\Core\Hook; -use Friendica\Core\Logger; use Friendica\Core\Renderer; use Friendica\Database\DBA; use Friendica\DI; @@ -108,8 +107,8 @@ function wppost_hook_fork(array &$b) $post = $b['data']; if ( - $post['deleted'] || $post['private'] || ($post['created'] !== $post['edited']) || - !strstr($post['postopts'] ?? '', 'wppost') || ($post['parent'] != $post['id']) + $post['deleted'] || ($post['private'] == Item::PRIVATE) || ($post['created'] !== $post['edited']) || + !strstr($post['postopts'] ?? '', 'wppost') || ($post['gravity'] != Item::GRAVITY_PARENT) ) { $b['execute'] = false; return; @@ -118,18 +117,12 @@ function wppost_hook_fork(array &$b) function wppost_post_local(array &$b) { - - // This can probably be changed to allow editing by pointing to a different API endpoint - - if ($b['edit']) { - return; - } - if (!DI::userSession()->getLocalUserId() || (DI::userSession()->getLocalUserId() != $b['uid'])) { return; } - if ($b['private'] || $b['parent']) { + // This can probably be changed to allow editing by pointing to a different API endpoint + if ($b['edit'] || ($b['private'] == Item::PRIVATE) || ($b['gravity'] != Item::GRAVITY_PARENT)) { return; } @@ -152,12 +145,9 @@ function wppost_post_local(array &$b) $b['postopts'] .= 'wppost'; } - - - function wppost_send(array &$b) { - if ($b['deleted'] || $b['private'] || ($b['created'] !== $b['edited'])) { + if ($b['deleted'] || ($b['private'] == Item::PRIVATE) || ($b['created'] !== $b['edited'])) { return; } @@ -266,11 +256,13 @@ function wppost_send(array &$b) EOT; - Logger::debug('wppost: data: ' . $xml); + DI::logger()->debug('wppost: data: ' . $xml); + + $x = ''; if ($wp_blog !== 'test') { $x = DI::httpClient()->post($wp_blog, $xml)->getBodyString(); } - Logger::info('posted to wordpress: ' . (($x) ? $x : '')); + DI::logger()->info('posted to wordpress: ' . $x); } }