diff --git a/.woodpecker/.code_standards_check.yml b/.woodpecker/.code_standards_check.yml index 60a1bd2a..8e0f7dc7 100644 --- a/.woodpecker/.code_standards_check.yml +++ b/.woodpecker/.code_standards_check.yml @@ -1,12 +1,9 @@ skip_clone: true -steps: +pipeline: 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: @@ -56,10 +53,6 @@ steps: - /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 d6d8a22a..d1202978 100644 --- a/.woodpecker/.continuous-deployment.yml +++ b/.woodpecker/.continuous-deployment.yml @@ -5,13 +5,10 @@ labels: skip_clone: true -steps: +pipeline: 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: @@ -48,7 +45,7 @@ steps: branch: [ develop, '*-rc' ] event: push composer_install: - image: friendicaci/php8.2:php8.2.28 + image: friendicaci/php8.2:php8.2.16 commands: - export COMPOSER_HOME=.composer - composer validate diff --git a/.woodpecker/.messages.po_check.yml b/.woodpecker/.messages.po_check.yml index e0239dcd..ea9fa4d5 100644 --- a/.woodpecker/.messages.po_check.yml +++ b/.woodpecker/.messages.po_check.yml @@ -1,12 +1,9 @@ skip_clone: true -steps: +pipeline: 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: diff --git a/.woodpecker/.phpunit.yml b/.woodpecker/.phpunit.yml index b0745ad0..0c25a2bd 100644 --- a/.woodpecker/.phpunit.yml +++ b/.woodpecker/.phpunit.yml @@ -5,13 +5,11 @@ matrix: - PHP_MAJOR_VERSION: 8.0 PHP_VERSION: 8.0.30 - PHP_MAJOR_VERSION: 8.1 - PHP_VERSION: 8.1.31 + PHP_VERSION: 8.1.27 - PHP_MAJOR_VERSION: 8.2 - PHP_VERSION: 8.2.28 + PHP_VERSION: 8.2.16 - PHP_MAJOR_VERSION: 8.3 - PHP_VERSION: 8.3.17 - - PHP_MAJOR_VERSION: 8.4 - PHP_VERSION: 8.4.5 + PHP_VERSION: 8.3.3 # This forces PHP Unit executions at the "opensocial" labeled location (because of much more power...) labels: @@ -19,13 +17,10 @@ labels: skip_clone: true -steps: +pipeline: 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: @@ -100,9 +95,9 @@ steps: - friendica/friendica-addons commands: - codecov -R '.' -Z -f 'clover.xml' - environment: - CODECOV_TOKEN: - from_secret: codecov-token + secrets: + - source: codecov-token + target: codecov_token services: mariadb: diff --git a/.woodpecker/.releaser.yml b/.woodpecker/.releaser.yml index 7407f2bc..68bdfb21 100644 --- a/.woodpecker/.releaser.yml +++ b/.woodpecker/.releaser.yml @@ -5,13 +5,10 @@ labels: skip_clone: true -steps: +pipeline: 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: @@ -45,7 +42,7 @@ steps: repo: friendica/friendica-addons event: tag composer_install: - image: friendicaci/php8.2:php8.2.28 + image: friendicaci/php8.2:php8.2.16 commands: - export COMPOSER_HOME=.composer - composer validate diff --git a/advancedcontentfilter/advancedcontentfilter.php b/advancedcontentfilter/advancedcontentfilter.php index 53cb9ebe..418b253e 100644 --- a/advancedcontentfilter/advancedcontentfilter.php +++ b/advancedcontentfilter/advancedcontentfilter.php @@ -33,13 +33,16 @@ * */ +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; @@ -61,7 +64,7 @@ function advancedcontentfilter_install() Hook::add('dbstructure_definition' , __FILE__, 'advancedcontentfilter_dbstructure_definition'); DBStructure::performUpdate(); - DI::logger()->notice('installed advancedcontentfilter'); + Logger::notice('installed advancedcontentfilter'); } /* @@ -120,22 +123,21 @@ function advancedcontentfilter_prepare_body_content_filter(&$hook_data) $expressionLanguage = new ExpressionLanguage\ExpressionLanguage(); } - $uid = $hook_data['uid'] ?? DI::userSession()->getLocalUserId(); - if (!$uid) { + if (!DI::userSession()->getLocalUserId()) { return; } $vars = advancedcontentfilter_get_filter_fields($hook_data['item']); - $rules = DI::cache()->get('rules_' . $uid); + $rules = DI::cache()->get('rules_' . DI::userSession()->getLocalUserId()); if (!isset($rules)) { $rules = DBA::toArray(DBA::select( 'advancedcontentfilter_rules', ['name', 'expression', 'serialized'], - ['uid' => $uid, 'active' => true] + ['uid' => DI::userSession()->getLocalUserId(), 'active' => true] )); - DI::cache()->set('rules_' . $uid, $rules); + DI::cache()->set('rules_' . DI::userSession()->getLocalUserId(), $rules); } if ($rules) { @@ -190,30 +192,9 @@ function advancedcontentfilter_init() if (DI::args()->getArgc() > 1 && DI::args()->getArgv()[1] == 'api') { $slim = \Slim\Factory\AppFactory::create(); - /** - * 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/middlewares.php'; + require __DIR__ . '/src/routes.php'; $slim->run(); exit; @@ -271,7 +252,7 @@ function advancedcontentfilter_content() 'rule_expression' => DI::l10n()->t('Rule Expression'), 'cancel' => DI::l10n()->t('Cancel'), ], - '$current_theme' => DI::appHelper()->getCurrentTheme(), + '$current_theme' => DI::app()->getCurrentTheme(), '$rules' => DBA::toArray(DBA::select('advancedcontentfilter_rules', [], ['uid' => DI::userSession()->getLocalUserId()])), '$form_security_token' => BaseModule::getFormSecurityToken() ]); diff --git a/advancedcontentfilter/lang/it/messages.po b/advancedcontentfilter/lang/it/messages.po index 325be52c..f32c5b94 100644 --- a/advancedcontentfilter/lang/it/messages.po +++ b/advancedcontentfilter/lang/it/messages.po @@ -5,7 +5,7 @@ # # Translators: # fabrixxm , 2018 -# Sylke Vicious , 2023 +# Sylke Vicious , 2021 # #, 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 , 2023\n" +"Last-Translator: Sylke Vicious , 2021\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 "Questo addon richiede che questo nodo abbia almeno un messaggio" +msgstr "" #: 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 d47d7a5a..5cc01739 100644 --- a/advancedcontentfilter/lang/it/strings.php +++ b/advancedcontentfilter/lang/it/strings.php @@ -27,7 +27,6 @@ $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 new file mode 100644 index 00000000..2b831473 --- /dev/null +++ b/advancedcontentfilter/src/middlewares.php @@ -0,0 +1,32 @@ +. + * + */ + +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, DI::logger()); diff --git a/advancedcontentfilter/src/routes.php b/advancedcontentfilter/src/routes.php new file mode 100644 index 00000000..a46f1b4b --- /dev/null +++ b/advancedcontentfilter/src/routes.php @@ -0,0 +1,36 @@ +. + * + */ + +/* @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 2d273a02..3e6193fa 100644 --- a/advancedcontentfilter/vendor/autoload.php +++ b/advancedcontentfilter/vendor/autoload.php @@ -2,24 +2,6 @@ // 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 7824d8f7..03b9bb9c 100644 --- a/advancedcontentfilter/vendor/composer/ClassLoader.php +++ b/advancedcontentfilter/vendor/composer/ClassLoader.php @@ -37,81 +37,26 @@ namespace Composer\Autoload; * * @author Fabien Potencier * @author Jordi Boggiano - * @see https://www.php-fig.org/psr/psr-0/ - * @see https://www.php-fig.org/psr/psr-4/ + * @see http://www.php-fig.org/psr/psr-0/ + * @see http://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)) { @@ -121,42 +66,28 @@ 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 - * - * @return void + * @param array $classMap Class to filename map */ public function addClassMap(array $classMap) { @@ -171,25 +102,22 @@ 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 list|string $paths The PSR-0 root directories - * @param bool $prepend Whether to prepend the directories - * - * @return void + * @param string $prefix The prefix + * @param array|string $paths The PSR-0 root directories + * @param bool $prepend Whether to prepend the directories */ public function add($prefix, $paths, $prepend = false) { - $paths = (array) $paths; if (!$prefix) { if ($prepend) { $this->fallbackDirsPsr0 = array_merge( - $paths, + (array) $paths, $this->fallbackDirsPsr0 ); } else { $this->fallbackDirsPsr0 = array_merge( $this->fallbackDirsPsr0, - $paths + (array) $paths ); } @@ -198,19 +126,19 @@ class ClassLoader $first = $prefix[0]; if (!isset($this->prefixesPsr0[$first][$prefix])) { - $this->prefixesPsr0[$first][$prefix] = $paths; + $this->prefixesPsr0[$first][$prefix] = (array) $paths; return; } if ($prepend) { $this->prefixesPsr0[$first][$prefix] = array_merge( - $paths, + (array) $paths, $this->prefixesPsr0[$first][$prefix] ); } else { $this->prefixesPsr0[$first][$prefix] = array_merge( $this->prefixesPsr0[$first][$prefix], - $paths + (array) $paths ); } } @@ -219,28 +147,25 @@ 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 list|string $paths The PSR-4 base directories - * @param bool $prepend Whether to prepend the directories + * @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 * * @throws \InvalidArgumentException - * - * @return void */ public function addPsr4($prefix, $paths, $prepend = false) { - $paths = (array) $paths; if (!$prefix) { // Register directories for the root namespace. if ($prepend) { $this->fallbackDirsPsr4 = array_merge( - $paths, + (array) $paths, $this->fallbackDirsPsr4 ); } else { $this->fallbackDirsPsr4 = array_merge( $this->fallbackDirsPsr4, - $paths + (array) $paths ); } } elseif (!isset($this->prefixDirsPsr4[$prefix])) { @@ -250,18 +175,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] = $paths; + $this->prefixDirsPsr4[$prefix] = (array) $paths; } elseif ($prepend) { // Prepend directories for an already registered namespace. $this->prefixDirsPsr4[$prefix] = array_merge( - $paths, + (array) $paths, $this->prefixDirsPsr4[$prefix] ); } else { // Append directories for an already registered namespace. $this->prefixDirsPsr4[$prefix] = array_merge( $this->prefixDirsPsr4[$prefix], - $paths + (array) $paths ); } } @@ -270,10 +195,8 @@ 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 list|string $paths The PSR-0 base directories - * - * @return void + * @param string $prefix The prefix + * @param array|string $paths The PSR-0 base directories */ public function set($prefix, $paths) { @@ -288,12 +211,10 @@ 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 list|string $paths The PSR-4 base directories + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param array|string $paths The PSR-4 base directories * * @throws \InvalidArgumentException - * - * @return void */ public function setPsr4($prefix, $paths) { @@ -313,8 +234,6 @@ class ClassLoader * Turns on searching the include path for class files. * * @param bool $useIncludePath - * - * @return void */ public function setUseIncludePath($useIncludePath) { @@ -337,8 +256,6 @@ class ClassLoader * that have not been registered with the class map. * * @param bool $classMapAuthoritative - * - * @return void */ public function setClassMapAuthoritative($classMapAuthoritative) { @@ -359,8 +276,6 @@ 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) { @@ -381,55 +296,33 @@ 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 true|null True if loaded, null otherwise + * @return bool|null True if loaded, null otherwise */ public function loadClass($class) { if ($file = $this->findFile($class)) { - $includeFile = self::$includeFile; - $includeFile($file); + includeFile($file); return true; } - - return null; } /** @@ -474,21 +367,6 @@ 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 @@ -554,26 +432,14 @@ class ClassLoader return false; } - - /** - * @return void - */ - private static function initializeIncludeClosure() - { - if (self::$includeFile !== null) { - return; - } - - /** - * Scope isolated include. - * - * Prevents access to $this/self from included files. - * - * @param string $file - * @return void - */ - self::$includeFile = \Closure::bind(static function($file) { - include $file; - }, null, null); - } +} + +/** + * Scope isolated include. + * + * Prevents access to $this/self from included files. + */ +function includeFile($file) +{ + include $file; } diff --git a/advancedcontentfilter/vendor/composer/InstalledVersions.php b/advancedcontentfilter/vendor/composer/InstalledVersions.php deleted file mode 100644 index 51e734a7..00000000 --- a/advancedcontentfilter/vendor/composer/InstalledVersions.php +++ /dev/null @@ -1,359 +0,0 @@ - - * 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 fe2a622a..9f79be5c 100644 --- a/advancedcontentfilter/vendor/composer/autoload_classmap.php +++ b/advancedcontentfilter/vendor/composer/autoload_classmap.php @@ -2,12 +2,11 @@ // autoload_classmap.php @generated by Composer -$vendorDir = dirname(__DIR__); +$vendorDir = dirname(dirname(__FILE__)); $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', @@ -155,6 +154,7 @@ return array( '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', @@ -188,6 +188,7 @@ 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', @@ -196,6 +197,7 @@ return array( 'Symfony\\Component\\Cache\\Traits\\DoctrineTrait' => $vendorDir . '/symfony/cache/Traits/DoctrineTrait.php', 'Symfony\\Component\\Cache\\Traits\\FilesystemCommonTrait' => $vendorDir . '/symfony/cache/Traits/FilesystemCommonTrait.php', 'Symfony\\Component\\Cache\\Traits\\FilesystemTrait' => $vendorDir . '/symfony/cache/Traits/FilesystemTrait.php', + 'Symfony\\Component\\Cache\\Traits\\LazyValue' => $vendorDir . '/symfony/cache/Traits/PhpFilesTrait.php', 'Symfony\\Component\\Cache\\Traits\\MemcachedTrait' => $vendorDir . '/symfony/cache/Traits/MemcachedTrait.php', 'Symfony\\Component\\Cache\\Traits\\PdoTrait' => $vendorDir . '/symfony/cache/Traits/PdoTrait.php', 'Symfony\\Component\\Cache\\Traits\\PhpArrayTrait' => $vendorDir . '/symfony/cache/Traits/PhpArrayTrait.php', diff --git a/advancedcontentfilter/vendor/composer/autoload_files.php b/advancedcontentfilter/vendor/composer/autoload_files.php index aafd69e1..a5d3b964 100644 --- a/advancedcontentfilter/vendor/composer/autoload_files.php +++ b/advancedcontentfilter/vendor/composer/autoload_files.php @@ -2,7 +2,7 @@ // autoload_files.php @generated by Composer -$vendorDir = dirname(__DIR__); +$vendorDir = dirname(dirname(__FILE__)); $baseDir = dirname($vendorDir); return array( diff --git a/advancedcontentfilter/vendor/composer/autoload_namespaces.php b/advancedcontentfilter/vendor/composer/autoload_namespaces.php index 15a2ff3a..b7fc0125 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(__DIR__); +$vendorDir = dirname(dirname(__FILE__)); $baseDir = dirname($vendorDir); return array( diff --git a/advancedcontentfilter/vendor/composer/autoload_psr4.php b/advancedcontentfilter/vendor/composer/autoload_psr4.php index 4bf247ce..3d716d56 100644 --- a/advancedcontentfilter/vendor/composer/autoload_psr4.php +++ b/advancedcontentfilter/vendor/composer/autoload_psr4.php @@ -2,7 +2,7 @@ // autoload_psr4.php @generated by Composer -$vendorDir = dirname(__DIR__); +$vendorDir = dirname(dirname(__FILE__)); $baseDir = dirname($vendorDir); return array( @@ -16,7 +16,7 @@ return array( 'Slim\\' => array($vendorDir . '/slim/slim/Slim'), '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-message/src', $vendorDir . '/psr/http-factory/src'), + 'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-factory/src', $vendorDir . '/psr/http-message/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 b305aa00..d6532d7d 100644 --- a/advancedcontentfilter/vendor/composer/autoload_real.php +++ b/advancedcontentfilter/vendor/composer/autoload_real.php @@ -22,29 +22,52 @@ 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(\dirname(__DIR__)); + self::$loader = $loader = new \Composer\Autoload\ClassLoader(); spl_autoload_unregister(array('ComposerAutoloaderInitAdvancedContentFilterAddon', 'loadClassLoader')); - require __DIR__ . '/autoload_static.php'; - call_user_func(\Composer\Autoload\ComposerStaticInitAdvancedContentFilterAddon::getInitializer($loader)); + $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); + } + } $loader->register(true); - $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); + if ($useStaticLoader) { + $includeFiles = Composer\Autoload\ComposerStaticInitAdvancedContentFilterAddon::$files; + } else { + $includeFiles = require __DIR__ . '/autoload_files.php'; + } + foreach ($includeFiles as $fileIdentifier => $file) { + composerRequireAdvancedContentFilterAddon($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 8cc48b1a..57172a1a 100644 --- a/advancedcontentfilter/vendor/composer/autoload_static.php +++ b/advancedcontentfilter/vendor/composer/autoload_static.php @@ -83,8 +83,8 @@ class ComposerStaticInitAdvancedContentFilterAddon ), 'Psr\\Http\\Message\\' => array ( - 0 => __DIR__ . '/..' . '/psr/http-message/src', - 1 => __DIR__ . '/..' . '/psr/http-factory/src', + 0 => __DIR__ . '/..' . '/psr/http-factory/src', + 1 => __DIR__ . '/..' . '/psr/http-message/src', ), 'Psr\\Container\\' => array ( @@ -102,7 +102,6 @@ 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', @@ -250,6 +249,7 @@ class ComposerStaticInitAdvancedContentFilterAddon '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', @@ -283,6 +283,7 @@ 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', @@ -291,6 +292,7 @@ class ComposerStaticInitAdvancedContentFilterAddon 'Symfony\\Component\\Cache\\Traits\\DoctrineTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/DoctrineTrait.php', 'Symfony\\Component\\Cache\\Traits\\FilesystemCommonTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/FilesystemCommonTrait.php', 'Symfony\\Component\\Cache\\Traits\\FilesystemTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/FilesystemTrait.php', + 'Symfony\\Component\\Cache\\Traits\\LazyValue' => __DIR__ . '/..' . '/symfony/cache/Traits/PhpFilesTrait.php', 'Symfony\\Component\\Cache\\Traits\\MemcachedTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/MemcachedTrait.php', 'Symfony\\Component\\Cache\\Traits\\PdoTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/PdoTrait.php', 'Symfony\\Component\\Cache\\Traits\\PhpArrayTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/PhpArrayTrait.php', diff --git a/advancedcontentfilter/vendor/composer/installed.json b/advancedcontentfilter/vendor/composer/installed.json index 70c2dc41..07e02c7f 100644 --- a/advancedcontentfilter/vendor/composer/installed.json +++ b/advancedcontentfilter/vendor/composer/installed.json @@ -1,1212 +1,1190 @@ -{ - "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" - }, - "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/" - }, - "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" - ], - "install-path": "../nikic/fast-route" +[ + { + "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" }, - { - "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" - ], - "install-path": "../psr/cache" + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/FastRoute/zipball/181d480e08d9476e61381e04a71b34dc0432e812", + "reference": "181d480e08d9476e61381e04a71b34dc0432e812", + "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": ">=5.4.0" }, - { - "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" + "require-dev": { + "phpunit/phpunit": "^4.8.35|~5.7" }, - { - "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" + "time": "2018-02-13T20:26:39+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "FastRoute\\": "src/" }, - "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" + "files": [ + "src/functions.php" + ] }, - { - "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" - ], - "install-path": "../psr/http-server-handler" + "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" }, - { - "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" + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/cache/zipball/d11b50ad223250cf17b86e38383413f5a6764bf8", + "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8", + "shasum": "" }, - { - "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" + "require": { + "php": ">=5.3.0" }, - { - "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" + "time": "2016-08-06T20:24:11+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } }, - { - "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" + "installation-source": "dist", + "autoload": { + "psr-4": { + "Psr\\Cache\\": "src/" + } }, - { - "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" + "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": "1.1.2", + "version_normalized": "1.1.2.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "513e0666f7216c7459170d56df27dfcefe1689ea" }, - { - "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" + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea", + "reference": "513e0666f7216c7459170d56df27dfcefe1689ea", + "shasum": "" }, - { - "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" + "require": { + "php": ">=7.4.0" }, - { - "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 + "time": "2021-11-05T16:50:12+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } }, - { - "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" + "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" }, - { - "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" + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/e616d01114759c4c489f93b099585439f795fe35", + "reference": "e616d01114759c4c489f93b099585439f795fe35", + "shasum": "" }, - { - "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" + "require": { + "php": ">=7.0.0", + "psr/http-message": "^1.0 || ^2.0" }, - { - "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" + "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": "2.0", + "version_normalized": "2.0.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" + }, + "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" + ] + }, + { + "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": "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" }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/var-exporter/zipball/abb0a151b62d6b07e816487e20040464af96cae7", - "reference": "abb0a151b62d6b07e816487e20040464af96cae7", - "shasum": "" + { + "name": "Andrew Smith", + "email": "a.smith@silentworks.co.uk", + "homepage": "http://silentworks.co.uk" }, - "require": { - "php": ">=7.2.5", - "symfony/polyfill-php80": "^1.16" + { + "name": "Rob Allen", + "email": "rob@akrabat.com", + "homepage": "http://akrabat.com" }, - "require-dev": { - "symfony/var-dumper": "^4.4.9|^5.0.9|^6.0" + { + "name": "Pierre Berube", + "email": "pierre@lgse.com", + "homepage": "http://www.lgse.com" }, - "time": "2024-01-23T13:51:25+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\VarExporter\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] + { + "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" }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" + { + "url": "https://tidelift.com/funding/github/packagist/slim/slim", + "type": "tidelift" + } + ] + }, + { + "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" + } + ] + }, + { + "name": "symfony/cache-contracts", + "version": "v2.5.2", + "version_normalized": "2.5.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/cache-contracts.git", + "reference": "64be4a7acb83b6f2bf6de9a02cee6dad41277ebc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/64be4a7acb83b6f2bf6de9a02cee6dad41277ebc", + "reference": "64be4a7acb83b6f2bf6de9a02cee6dad41277ebc", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "psr/cache": "^1.0|^2.0|^3.0" + }, + "suggest": { + "symfony/cache-implementation": "" + }, + "time": "2022-01-02T09:53:40+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Cache\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to caching", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ] + }, + { + "name": "symfony/deprecation-contracts", + "version": "v2.5.2", + "version_normalized": "2.5.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/e8b495ea28c1d97b5e0c121748d6f9b53d075c66", + "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "time": "2022-01-02T09:53:40+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "installation-source": "dist", + "autoload": { + "files": [ + "function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ] + }, + { + "name": "symfony/expression-language", + "version": "v3.4.47", + "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-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" + } + ] + }, + { + "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" ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } + "psr-4": { + "Symfony\\Polyfill\\Php73\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ] + }, + { + "name": "symfony/polyfill-php80", + "version": "v1.29.0", + "version_normalized": "1.29.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/87b68208d5c1188808dd7839ee1e6c8ec3b02f1b", + "reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "time": "2024-01-29T20:11:03+00:00", + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "installation-source": "dist", + "autoload": { + "files": [ + "bootstrap.php" ], - "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": [] -} + "psr-4": { + "Symfony\\Polyfill\\Php80\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ] + }, + { + "name": "symfony/service-contracts", + "version": "v2.5.2", + "version_normalized": "2.5.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/4b426aac47d6427cc1a1d0f7e2ac724627f5966c", + "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "psr/container": "^1.1", + "symfony/deprecation-contracts": "^2.1|^3" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "suggest": { + "symfony/service-implementation": "" + }, + "time": "2022-05-30T19:17:29+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ] + }, + { + "name": "symfony/var-exporter", + "version": "v5.4.35", + "version_normalized": "5.4.35.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-exporter.git", + "reference": "abb0a151b62d6b07e816487e20040464af96cae7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/abb0a151b62d6b07e816487e20040464af96cae7", + "reference": "abb0a151b62d6b07e816487e20040464af96cae7", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/polyfill-php80": "^1.16" + }, + "require-dev": { + "symfony/var-dumper": "^4.4.9|^5.0.9|^6.0" + }, + "time": "2024-01-23T13:51:25+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\VarExporter\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Allows exporting any serializable PHP data structure to plain PHP code", + "homepage": "https://symfony.com", + "keywords": [ + "clone", + "construct", + "export", + "hydrate", + "instantiate", + "serialize" + ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ] + } +] diff --git a/advancedcontentfilter/vendor/composer/installed.php b/advancedcontentfilter/vendor/composer/installed.php deleted file mode 100644 index 010b1da9..00000000 --- a/advancedcontentfilter/vendor/composer/installed.php +++ /dev/null @@ -1,203 +0,0 @@ - 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 deleted file mode 100644 index 580fa960..00000000 --- a/advancedcontentfilter/vendor/composer/platform_check.php +++ /dev/null @@ -1,26 +0,0 @@ -= 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/simple-cache/.editorconfig b/advancedcontentfilter/vendor/psr/simple-cache/.editorconfig new file mode 100644 index 00000000..48542cbb --- /dev/null +++ b/advancedcontentfilter/vendor/psr/simple-cache/.editorconfig @@ -0,0 +1,12 @@ +; This file is for unifying the coding style for different editors and IDEs. +; More information at http://editorconfig.org + +root = true + +[*] +charset = utf-8 +indent_size = 4 +indent_style = space +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true diff --git a/advancedcontentfilter/vendor/psr/simple-cache/LICENSE.md b/advancedcontentfilter/vendor/psr/simple-cache/LICENSE.md new file mode 100644 index 00000000..e49a7c85 --- /dev/null +++ b/advancedcontentfilter/vendor/psr/simple-cache/LICENSE.md @@ -0,0 +1,21 @@ +# The MIT License (MIT) + +Copyright (c) 2016 PHP Framework Interoperability Group + +> Permission is hereby granted, free of charge, to any person obtaining a copy +> of this software and associated documentation files (the "Software"), to deal +> in the Software without restriction, including without limitation the rights +> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +> copies of the Software, and to permit persons to whom the Software is +> furnished to do so, subject to the following conditions: +> +> The above copyright notice and this permission notice shall be included in +> all copies or substantial portions of the Software. +> +> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +> THE SOFTWARE. diff --git a/advancedcontentfilter/vendor/psr/simple-cache/README.md b/advancedcontentfilter/vendor/psr/simple-cache/README.md new file mode 100644 index 00000000..43641d17 --- /dev/null +++ b/advancedcontentfilter/vendor/psr/simple-cache/README.md @@ -0,0 +1,8 @@ +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 new file mode 100644 index 00000000..2978fa55 --- /dev/null +++ b/advancedcontentfilter/vendor/psr/simple-cache/composer.json @@ -0,0 +1,25 @@ +{ + "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 new file mode 100644 index 00000000..eba53815 --- /dev/null +++ b/advancedcontentfilter/vendor/psr/simple-cache/src/CacheException.php @@ -0,0 +1,10 @@ + 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 new file mode 100644 index 00000000..6a9524a2 --- /dev/null +++ b/advancedcontentfilter/vendor/psr/simple-cache/src/InvalidArgumentException.php @@ -0,0 +1,13 @@ + + * + * 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 new file mode 100644 index 00000000..5758a286 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/AdapterTestCase.php @@ -0,0 +1,175 @@ + + * + * 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 new file mode 100644 index 00000000..f55a1b9b --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/ApcuAdapterTest.php @@ -0,0 +1,124 @@ + + * + * 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 new file mode 100644 index 00000000..e6adc9d0 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/ArrayAdapterTest.php @@ -0,0 +1,56 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\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 new file mode 100644 index 00000000..be811d6f --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/ChainAdapterTest.php @@ -0,0 +1,233 @@ + + * + * 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 new file mode 100644 index 00000000..8f520cb5 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/DoctrineAdapterTest.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\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 new file mode 100644 index 00000000..fa830682 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/FilesystemAdapterTest.php @@ -0,0 +1,61 @@ + + * + * 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 new file mode 100644 index 00000000..536e2c2d --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/MaxIdLengthAdapterTest.php @@ -0,0 +1,87 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\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 new file mode 100644 index 00000000..a9a397dd --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/MemcachedAdapterTest.php @@ -0,0 +1,204 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\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 new file mode 100644 index 00000000..c2714033 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/NamespacedProxyAdapterTest.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\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 new file mode 100644 index 00000000..b771fa0e --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/NullAdapterTest.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\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 new file mode 100644 index 00000000..dd2a9118 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PdoAdapterTest.php @@ -0,0 +1,73 @@ + + * + * 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 new file mode 100644 index 00000000..aa53958c --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PdoDbalAdapterTest.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\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 new file mode 100644 index 00000000..f88a7187 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PhpArrayAdapterTest.php @@ -0,0 +1,135 @@ + + * + * 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 new file mode 100644 index 00000000..0bfd5c39 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PhpArrayAdapterWithFallbackTest.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\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 new file mode 100644 index 00000000..247160d5 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PhpFilesAdapterTest.php @@ -0,0 +1,47 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\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 new file mode 100644 index 00000000..6aadbf26 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PredisAdapterTest.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\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 new file mode 100644 index 00000000..1afabaf1 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PredisClusterAdapterTest.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\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 new file mode 100644 index 00000000..5b09919e --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PredisRedisClusterAdapterTest.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\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 new file mode 100644 index 00000000..810cb31a --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/ProxyAdapterTest.php @@ -0,0 +1,69 @@ + + * + * 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 new file mode 100644 index 00000000..6ec6321a --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/RedisAdapterTest.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\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 new file mode 100644 index 00000000..bd9def32 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/RedisArrayAdapterTest.php @@ -0,0 +1,24 @@ + + * + * 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 new file mode 100644 index 00000000..9c339d2d --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/RedisClusterAdapterTest.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\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 new file mode 100644 index 00000000..d8470a2e --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/SimpleCacheAdapterTest.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\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 new file mode 100644 index 00000000..11907a03 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/TagAwareAdapterTest.php @@ -0,0 +1,338 @@ + + * + * 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 new file mode 100644 index 00000000..b11c1f28 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/TagAwareAndProxyAdapterIntegrationTest.php @@ -0,0 +1,38 @@ +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 new file mode 100644 index 00000000..35eba7d7 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/TraceableAdapterTest.php @@ -0,0 +1,191 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\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 new file mode 100644 index 00000000..5cd4185c --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/TraceableTagAwareAdapterTest.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\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 new file mode 100644 index 00000000..28c681d1 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/CacheItemTest.php @@ -0,0 +1,77 @@ + + * + * 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 new file mode 100644 index 00000000..91a5516a --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/DoctrineProviderTest.php @@ -0,0 +1,45 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\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 new file mode 100644 index 00000000..13b4f330 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Fixtures/ArrayCache.php @@ -0,0 +1,52 @@ +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 new file mode 100644 index 00000000..be1f9901 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Fixtures/ExternalAdapter.php @@ -0,0 +1,76 @@ + + * + * 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 new file mode 100644 index 00000000..7a6cabe8 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/AbstractRedisCacheTest.php @@ -0,0 +1,47 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\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 new file mode 100644 index 00000000..fad0c043 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/ApcuCacheTest.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\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 new file mode 100644 index 00000000..26c3e14d --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/ArrayCacheTest.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\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 new file mode 100644 index 00000000..ff9944a3 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/CacheTestCase.php @@ -0,0 +1,150 @@ + + * + * 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 new file mode 100644 index 00000000..f216bc1f --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/ChainCacheTest.php @@ -0,0 +1,113 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\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 new file mode 100644 index 00000000..af4331d6 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/DoctrineCacheTest.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\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 new file mode 100644 index 00000000..620305a5 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/FilesystemCacheTest.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\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 new file mode 100644 index 00000000..6df682e9 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/MemcachedCacheTest.php @@ -0,0 +1,178 @@ + + * + * 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 new file mode 100644 index 00000000..13865a60 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/MemcachedCacheTextModeTest.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\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 new file mode 100644 index 00000000..31f42c32 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/NullCacheTest.php @@ -0,0 +1,96 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\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 new file mode 100644 index 00000000..f5a26341 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/PdoCacheTest.php @@ -0,0 +1,47 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\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 new file mode 100644 index 00000000..4da2b603 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/PdoDbalCacheTest.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\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 new file mode 100644 index 00000000..bcd7dea5 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/PhpArrayCacheTest.php @@ -0,0 +1,145 @@ + + * + * 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 new file mode 100644 index 00000000..b08c1604 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/PhpArrayCacheWithFallbackTest.php @@ -0,0 +1,57 @@ + + * + * 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 new file mode 100644 index 00000000..936f29a4 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/PhpFilesCacheTest.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\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 new file mode 100644 index 00000000..1bc75c90 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/Psr6CacheTest.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\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 new file mode 100644 index 00000000..ec5e4c06 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/RedisArrayCacheTest.php @@ -0,0 +1,24 @@ + + * + * 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 new file mode 100644 index 00000000..8e3f6088 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/RedisCacheTest.php @@ -0,0 +1,82 @@ + + * + * 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 new file mode 100644 index 00000000..6b7f8039 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/RedisClusterCacheTest.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\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 new file mode 100644 index 00000000..e684caf3 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/TraceableCacheTest.php @@ -0,0 +1,171 @@ + + * + * 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 new file mode 100644 index 00000000..c405de70 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Traits/PdoPruneableTrait.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\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/phpunit.xml.dist b/advancedcontentfilter/vendor/symfony/cache/phpunit.xml.dist new file mode 100644 index 00000000..c35458ca --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/phpunit.xml.dist @@ -0,0 +1,50 @@ + + + + + + + + + + + + ./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/polyfill-apcu/Apcu.php b/advancedcontentfilter/vendor/symfony/polyfill-apcu/Apcu.php new file mode 100644 index 00000000..4dc5bf9a --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/polyfill-apcu/Apcu.php @@ -0,0 +1,106 @@ + + * + * 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/LICENSE b/advancedcontentfilter/vendor/symfony/polyfill-apcu/LICENSE new file mode 100644 index 00000000..6e3afce6 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/polyfill-apcu/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2015-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-apcu/README.md b/advancedcontentfilter/vendor/symfony/polyfill-apcu/README.md new file mode 100644 index 00000000..57f4bf6b --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/polyfill-apcu/README.md @@ -0,0 +1,12 @@ +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 new file mode 100644 index 00000000..96b2706a --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/polyfill-apcu/bootstrap.php @@ -0,0 +1,83 @@ + + * + * 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 new file mode 100644 index 00000000..69e9f160 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/polyfill-apcu/bootstrap80.php @@ -0,0 +1,75 @@ + + * + * 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-apcu/composer.json b/advancedcontentfilter/vendor/symfony/polyfill-apcu/composer.json new file mode 100644 index 00000000..e92524f3 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/polyfill-apcu/composer.json @@ -0,0 +1,35 @@ +{ + "name": "symfony/polyfill-apcu", + "type": "library", + "description": "Symfony polyfill backporting apcu_* functions to lower PHP versions", + "keywords": ["polyfill", "shim", "compatibility", "portable", "apcu"], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": ">=7.1" + }, + "autoload": { + "psr-4": { "Symfony\\Polyfill\\Apcu\\": "" }, + "files": [ "bootstrap.php" ] + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-main": "1.28-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + } +} diff --git a/birdavatar/birdavatar.php b/birdavatar/birdavatar.php index cd49b183..4841ba52 100644 --- a/birdavatar/birdavatar.php +++ b/birdavatar/birdavatar.php @@ -6,7 +6,9 @@ * Author: Fabio */ +use Friendica\App; use Friendica\Core\Hook; +use Friendica\Core\Logger; use Friendica\Core\Renderer; use Friendica\Database\DBA; use Friendica\DI; @@ -26,7 +28,7 @@ function birdavatar_install() Hook::register('addon_settings', __FILE__, 'birdavatar_addon_settings'); Hook::register('addon_settings_post', __FILE__, 'birdavatar_addon_settings_post'); - DI::logger()->info('registered birdavatar'); + Logger::info('registered birdavatar'); } /** diff --git a/blackout/blackout.php b/blackout/blackout.php index ac1ee3e6..55fb8d32 100644 --- a/blackout/blackout.php +++ b/blackout/blackout.php @@ -44,7 +44,9 @@ * THE SOFTWARE. */ +use Friendica\App; use Friendica\Core\Hook; +use Friendica\Core\Logger; use Friendica\Core\Renderer; use Friendica\Core\System; use Friendica\DI; @@ -76,7 +78,7 @@ function blackout_redirect ($b) } if (( $date1 <= $now ) && ( $now <= $date2 )) { - DI::logger()->notice('redirecting user to blackout page'); + Logger::notice('redirecting user to blackout page'); System::externalRedirect($myurl); } } diff --git a/blockbot/blockbot.php b/blockbot/blockbot.php index 71e35c93..e5de1ef3 100644 --- a/blockbot/blockbot.php +++ b/blockbot/blockbot.php @@ -11,10 +11,10 @@ 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'; @@ -69,76 +69,74 @@ function blockbot_init_1() } if (empty($parts)) { - DI::logger()->debug('Known frontend found - accept', $logdata); + Logger::debug('Known frontend found - accept', $logdata); if ($isCrawler) { blockbot_save('badly-parsed-agents', $_SERVER['HTTP_USER_AGENT']); } return; } - blockbot_log_activitypub($_SERVER['REQUEST_URI'], $_SERVER['HTTP_USER_AGENT']); - if (blockbot_is_crawler($parts)) { - DI::logger()->debug('Crawler found - reject', $logdata); + Logger::debug('Crawler found - reject', $logdata); blockbot_reject(); } if (blockbot_is_searchbot($parts)) { - DI::logger()->debug('Search bot found - reject', $logdata); + Logger::debug('Search bot found - reject', $logdata); blockbot_reject(); } if (blockbot_is_unwanted($parts)) { - DI::logger()->debug('Uncategorized unwanted agent found - reject', $logdata); + 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); + Logger::debug('Security checker found - reject', $logdata); blockbot_reject(); } - DI::logger()->debug('Security checker found - accept', $logdata); + Logger::debug('Security checker found - accept', $logdata); return; } if (blockbot_is_social_media($parts)) { - DI::logger()->debug('Social media service found - accept', $logdata); + Logger::debug('Social media service found - accept', $logdata); return; } if (blockbot_is_fediverse_client($parts)) { - DI::logger()->debug('Fediverse client found - accept', $logdata); + Logger::debug('Fediverse client found - accept', $logdata); return; } if (blockbot_is_feed_reader($parts)) { - DI::logger()->debug('Feed reader found - accept', $logdata); + Logger::debug('Feed reader found - accept', $logdata); return; } if (blockbot_is_fediverse_tool($parts)) { - DI::logger()->debug('Fediverse tool found - accept', $logdata); + Logger::debug('Fediverse tool found - accept', $logdata); return; } if (blockbot_is_service_agent($parts)) { - DI::logger()->debug('Service agent found - accept', $logdata); + Logger::debug('Service agent found - accept', $logdata); return; } if (blockbot_is_monitor($parts)) { - DI::logger()->debug('Monitoring service found - accept', $logdata); + Logger::debug('Monitoring service found - accept', $logdata); return; } if (blockbot_is_validator($parts)) { - DI::logger()->debug('Validation service found - accept', $logdata); + Logger::debug('Validation service found - accept', $logdata); return; } if (blockbot_is_good_tool($parts)) { - DI::logger()->debug('Uncategorized helpful service found - accept', $logdata); + Logger::debug('Uncategorized helpful service found - accept', $logdata); return; } @@ -146,10 +144,10 @@ function blockbot_init_1() 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); + Logger::debug('HTTP Library found - reject', $logdata); blockbot_reject(); } - DI::logger()->debug('HTTP Library found - accept', $logdata); + Logger::debug('HTTP Library found - accept', $logdata); return; } @@ -160,18 +158,18 @@ function blockbot_init_1() if (!$isCrawler) { blockbot_save('good-agents', $_SERVER['HTTP_USER_AGENT']); - DI::logger()->debug('Non-bot user agent detected', $logdata); + Logger::debug('Non-bot user agent detected', $logdata); return; } blockbot_save('bad-agents', $_SERVER['HTTP_USER_AGENT']); - DI::logger()->notice('Possible bot found - reject', $logdata); + Logger::notice('Possible bot found - reject', $logdata); blockbot_reject(); } function blockbot_save($database, $userAgent) { - if (!DI::config()->get('blockbot', 'logging') || !function_exists('dba_open')) { + if (!DI::config()->get('blockbot', 'training') || !function_exists('dba_open')) { return; } @@ -183,40 +181,10 @@ function blockbot_save($database, $userAgent) 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); + Logger::debug('Login attempt detected - reject', $logdata); blockbot_reject(); } } @@ -442,7 +410,7 @@ function blockbot_is_monitor(array $parts): bool } /** - * Services in the centralized and decentralized social media environment + * Services in the centralized and decentralized social media environment * * @param array $parts * @return boolean @@ -460,7 +428,7 @@ function blockbot_is_social_media(array $parts): bool $agents = [ 'facebookexternalhit', 'twitterbot', 'mastodon', 'facebookexternalua', - 'friendica', 'diasporafederation', 'buzzrelay', 'activityrelay', 'drupal', + 'friendica', 'diasporafederation', 'buzzrelay', 'activityrelay', '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', @@ -498,7 +466,6 @@ function blockbot_is_fediverse_client(array $parts): bool '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) { diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index aef7156c..ba7c1d65 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -1,7 +1,7 @@ * @@ -10,8 +10,6 @@ * - 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: @@ -26,24 +24,29 @@ */ 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\Conversation; +use Friendica\Model\GServer; 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; @@ -51,6 +54,21 @@ 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'); @@ -62,17 +80,19 @@ 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::appHelper()->getConfigCache()->load($loader->loadAddonConfig('bluesky'), \Friendica\Core\Config\ValueObject\Cache::SOURCE_STATIC); + DI::app()->getConfigCache()->load($loader->loadAddonConfig('bluesky'), \Friendica\Core\Config\ValueObject\Cache::SOURCE_STATIC); } function bluesky_check_item_notification(array &$notification_data) @@ -81,7 +101,7 @@ function bluesky_check_item_notification(array &$notification_data) return; } - $did = DI::atProtocol()->getUserDid($notification_data['uid']); + $did = bluesky_get_user_did($notification_data['uid']); if (empty($did)) { return; } @@ -89,6 +109,61 @@ function bluesky_check_item_notification(array &$notification_data) $notification_data['profiles'][] = $did; } +function bluesky_probe_detect(array &$hookData) +{ + // Don't overwrite an existing result + if (isset($hookData['result'])) { + return; + } + + // Avoid a lookup for the wrong network + if (!in_array($hookData['network'], ['', Protocol::BLUESKY])) { + 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'] = ''; +} + function bluesky_item_by_link(array &$hookData) { // Don't overwrite an existing result @@ -96,25 +171,26 @@ function bluesky_item_by_link(array &$hookData) 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']; + $token = bluesky_get_token($hookData['uid']); + if (empty($token)) { + return; } - $uri = DI::atpProcessor()->fetchMissingPost($uri, $hookData['uid'], Item::PR_FETCHED, 0, 0); - DI::logger()->debug('Got post', ['uri' => $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]); if (!empty($uri)) { $item = Post::selectFirst(['id'], ['uri' => $uri, 'uid' => $hookData['uid']]); if (!empty($item['id'])) { @@ -130,14 +206,21 @@ 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 = DI::atProtocol()->getUserToken($hook_data['uid']); + $token = bluesky_get_token($hook_data['uid']); if (empty($token)) { return; } - DI::logger()->debug('Check if contact is bluesky', ['data' => $hook_data]); + 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; @@ -151,20 +234,20 @@ function bluesky_follow(array &$hook_data) $post = [ 'collection' => 'app.bsky.graph.follow', - 'repo' => DI::atProtocol()->getUserDid($hook_data['uid']), + 'repo' => bluesky_get_user_did($hook_data['uid']), 'record' => $record ]; - $activity = DI::atProtocol()->XRPCPost($hook_data['uid'], 'com.atproto.repo.createRecord', $post); + $activity = bluesky_xrpc_post($hook_data['uid'], 'com.atproto.repo.createRecord', $post); if (!empty($activity->uri)) { $hook_data['contact'] = $contact; - DI::logger()->debug('Successfully start following', ['url' => $contact['url'], 'uri' => $activity->uri]); + Logger::debug('Successfully start following', ['url' => $contact['url'], 'uri' => $activity->uri]); } } function bluesky_unfollow(array &$hook_data) { - $token = DI::atProtocol()->getUserToken($hook_data['uid']); + $token = bluesky_get_token($hook_data['uid']); if (empty($token)) { return; } @@ -173,7 +256,7 @@ function bluesky_unfollow(array &$hook_data) return; } - $data = DI::atProtocol()->XRPCGet('app.bsky.actor.getProfile', ['actor' => $hook_data['contact']['url']], $hook_data['uid']); + $data = bluesky_xrpc_get($hook_data['uid'], 'app.bsky.actor.getProfile', ['actor' => $hook_data['contact']['url']]); if (empty($data->viewer) || empty($data->viewer->following)) { return; } @@ -185,40 +268,42 @@ function bluesky_unfollow(array &$hook_data) function bluesky_block(array &$hook_data) { - $token = DI::atProtocol()->getUserToken($hook_data['uid']); + $token = bluesky_get_token($hook_data['uid']); if (empty($token)) { return; } - if ($hook_data['contact']['network'] != Protocol::BLUESKY) { + 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' => $hook_data['contact']['url'], + 'subject' => $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']), + 'repo' => bluesky_get_user_did($hook_data['uid']), 'record' => $record ]; - $activity = DI::atProtocol()->XRPCPost($hook_data['uid'], 'com.atproto.repo.createRecord', $post); + $activity = bluesky_xrpc_post($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); + $cdata = Contact::getPublicAndUserContactID($hook_data['contact']['id'], $hook_data['uid']); + if (!empty($cdata['user'])) { + Contact::remove($cdata['user']); } - DI::logger()->debug('Successfully blocked contact', ['url' => $hook_data['contact']['url'], 'uri' => $activity->uri]); + 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']); + $token = bluesky_get_token($hook_data['uid']); if (empty($token)) { return; } @@ -227,7 +312,7 @@ function bluesky_unblock(array &$hook_data) return; } - $data = DI::atProtocol()->XRPCGet('app.bsky.actor.getProfile', ['actor' => $hook_data['contact']['url']], $hook_data['uid']); + $data = bluesky_xrpc_get($hook_data['uid'], 'app.bsky.actor.getProfile', ['actor' => $hook_data['contact']['url']]); if (empty($data->viewer) || empty($data->viewer->blocking)) { return; } @@ -258,41 +343,36 @@ 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::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; + $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 = bluesky_get_user_did(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; + $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']); - $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; - } + $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)]; } 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.')], - '$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), + '$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), ]); $data = [ @@ -310,34 +390,33 @@ 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') ?? ATProtocol::STATUS_UNKNOWN; - $message = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'status-message') ?? ''; + $status = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'status') ?? BLUEKSY_STATUS_UNKNOWN; // Fallback mechanism for connection that had been established before the introduction of the status - if ($status == ATProtocol::STATUS_UNKNOWN) { + if ($status == BLUEKSY_STATUS_UNKNOWN) { if (empty($did)) { - $status = ATProtocol::STATUS_DID_FAIL; + $status = BLUEKSY_STATUS_DID_FAIL; } elseif (empty($pds)) { - $status = ATProtocol::STATUS_PDS_FAIL; + $status = BLUEKSY_STATUS_PDS_FAIL; } elseif (!empty($token)) { - $status = ATProtocol::STATUS_TOKEN_OK; + $status = BLUEKSY_STATUS_TOKEN_OK; } else { - $status = ATProtocol::STATUS_TOKEN_FAIL; + $status = BLUEKSY_STATUS_TOKEN_FAIL; } } switch ($status) { - case ATProtocol::STATUS_TOKEN_OK: + case BLUEKSY_STATUS_TOKEN_OK: return DI::l10n()->t("You are authenticated to Bluesky. For security reasons the password isn't stored."); - case ATProtocol::STATUS_SUCCESS: + case BLUEKSY_STATUS_SUCCESS: return DI::l10n()->t('The communication with the personal data server service (PDS) is established.'); - 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: + case BLUEKSY_STATUS_API_FAIL; + return DI::l10n()->t('Communication issues with the personal data server service (PDS).'); + case BLUEKSY_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 ATProtocol::STATUS_PDS_FAIL: + case BLUEKSY_STATUS_PDS_FAIL: return DI::l10n()->t('The personal data server service (PDS) could not be detected.'); - case ATProtocol::STATUS_TOKEN_FAIL: + case BLUEKSY_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 ''; @@ -361,15 +440,14 @@ 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', 'complete_threads', intval($_POST['bluesky_complete_threads'])); - DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'friendica_handle', intval($_POST['bluesky_friendica_handle'] ?? false)); + DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'friendica_handle', intval($_POST['bluesky_friendica_handle'])); if (!empty($handle)) { - $did = DI::atProtocol()->getUserDid(DI::userSession()->getLocalUserId(), empty($old_did) || $old_handle != $handle); + $did = bluesky_get_user_did(DI::userSession()->getLocalUserId(), empty($old_did) || $old_handle != $handle); if (!empty($did) && (empty($old_pds) || $old_handle != $handle)) { - $pds = DI::atProtocol()->getPdsOfDid($did); + $pds = bluesky_get_pds($did); if (empty($pds)) { - DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'status', ATProtocol::STATUS_PDS_FAIL); + DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'status', BLUEKSY_STATUS_PDS_FAIL); } DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'pds', $pds); } else { @@ -378,7 +456,6 @@ 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'); @@ -386,7 +463,7 @@ function bluesky_settings_post(array &$b) } if (!empty($did) && !empty($pds) && !empty($_POST['bluesky_password'])) { - DI::atProtocol()->createUserToken(DI::userSession()->getLocalUserId(), $_POST['bluesky_password']); + bluesky_create_token(DI::userSession()->getLocalUserId(), $_POST['bluesky_password']); } } @@ -420,11 +497,11 @@ function bluesky_cron() if ($last) { $next = $last + ($poll_interval * 60); if ($next > time()) { - DI::logger()->notice('poll interval not reached'); + Logger::notice('poll interval not reached'); return; } } - DI::logger()->notice('cron_start'); + Logger::notice('cron_start'); $abandon_days = intval(DI::config()->get('system', 'account_abandon_days')); if ($abandon_days < 1) { @@ -433,61 +510,48 @@ function bluesky_cron() $abandon_limit = date(DateTimeFormat::MYSQL, time() - $abandon_days * 86400); - $pconfigs = DBA::selectToArray('pconfig', [], ["`cat` = ? AND `k` IN (?, ?) AND `v`", 'bluesky', 'import', 'import_feeds']); + $pconfigs = DBA::selectToArray('pconfig', [], ['cat' => 'bluesky', 'k' => 'import', 'v' => true]); foreach ($pconfigs as $pconfig) { - if (empty(DI::atProtocol()->getUserDid($pconfig['uid']))) { - DI::logger()->debug('User has got no valid DID', ['uid' => $pconfig['uid']]); + if (empty(bluesky_get_user_did($pconfig['uid']))) { continue; } if ($abandon_days != 0) { if (!DBA::exists('user', ["`uid` = ? AND `login_date` >= ?", $pconfig['uid'], $abandon_limit])) { - DI::logger()->notice('abandoned account: timeline from user will not be imported', ['user' => $pconfig['uid']]); + 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 - DI::logger()->debug('Refresh the token', ['uid' => $pconfig['uid']]); - DI::atProtocol()->getUserToken($pconfig['uid']); + bluesky_get_token($pconfig['uid']); - $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'], $last); + 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']); - 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); + Worker::add(['priority' => Worker::PRIORITY_MEDIUM, 'force_priority' => true], 'addon/bluesky/bluesky_feed.php', $pconfig['uid'], $feed, $last); } } - 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())) { - DI::logger()->notice('Start contact cleanup'); + 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()); - DI::logger()->notice('Contact cleanup done'); + Logger::notice('Contact cleanup done'); } - DI::logger()->notice('cron_end'); + Logger::notice('cron_end'); + + DI::keyValue()->set('bluesky_last_poll', time()); } function bluesky_hook_fork(array &$b) @@ -506,13 +570,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['gravity'] != Item::GRAVITY_PARENT) && !Post::exists(['id' => $post['parent'], 'network' => Protocol::BLUESKY])) { - DI::logger()->notice('No bluesky parent found', ['item' => $post['id']]); + if (($post['parent'] != $post['id']) && !Post::exists(['id' => $post['parent'], 'network' => Protocol::BLUESKY])) { + Logger::notice('No bluesky parent found', ['item' => $post['id']]); $b['execute'] = false; return; } - } 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']]); + } 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']]); $b['execute'] = false; return; } @@ -520,11 +584,15 @@ 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['edit'] || ($b['private'] == Item::PRIVATE) || ($b['gravity'] != Item::GRAVITY_PARENT)) { + if ($b['private'] || $b['parent']) { return; } @@ -554,35 +622,35 @@ function bluesky_send(array &$b) } if ($b['gravity'] != Item::GRAVITY_PARENT) { - DI::logger()->debug('Got comment', ['item' => $b]); + Logger::debug('Got comment', ['item' => $b]); if ($b['deleted']) { - $uri = DI::atpProcessor()->getUriClass($b['uri']); + $uri = bluesky_get_uri_class($b['uri']); if (empty($uri)) { - DI::logger()->debug('Not a bluesky post', ['uri' => $b['uri']]); + Logger::debug('Not a bluesky post', ['uri' => $b['uri']]); return; } bluesky_delete_post($b['uri'], $b['uid']); return; } - $root = DI::atpProcessor()->getUriClass($b['parent-uri']); - $parent = DI::atpProcessor()->getUriClass($b['thr-parent']); + $root = bluesky_get_uri_class($b['parent-uri']); + $parent = bluesky_get_uri_class($b['thr-parent']); if (empty($root) || empty($parent)) { - DI::logger()->debug('No bluesky post', ['parent' => $b['parent'], 'thr-parent' => $b['thr-parent']]); + Logger::debug('No bluesky post', ['parent' => $b['parent'], 'thr-parent' => $b['thr-parent']]); return; } if ($b['gravity'] == Item::GRAVITY_COMMENT) { - DI::logger()->debug('Posting comment', ['root' => $root, 'parent' => $parent]); + 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'] == Item::PRIVATE) || !strstr($b['postopts'], 'bluesky')) { + } elseif ($b['private'] || !strstr($b['postopts'], 'bluesky')) { return; } @@ -592,18 +660,16 @@ function bluesky_send(array &$b) function bluesky_create_activity(array $item, stdClass $parent = null) { $uid = $item['uid']; - $token = DI::atProtocol()->getUserToken($uid); + $token = bluesky_get_token($uid); if (empty($token)) { return; } - $did = DI::atProtocol()->getUserDid($uid); + $did = bluesky_get_user_did($uid); if (empty($did)) { return; } - $post = []; - if ($item['verb'] == Activity::LIKE) { $record = [ 'subject' => $parent, @@ -630,20 +696,20 @@ function bluesky_create_activity(array $item, stdClass $parent = null) ]; } - $activity = DI::atProtocol()->XRPCPost($uid, 'com.atproto.repo.createRecord', $post); - if (empty($activity->uri)) { + $activity = bluesky_xrpc_post($uid, 'com.atproto.repo.createRecord', $post); + if (empty($activity)) { return; } - 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]); + 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]); } function bluesky_create_post(array $item, stdClass $root = null, stdClass $parent = null) { $uid = $item['uid']; - $token = DI::atProtocol()->getUserToken($uid); + $token = bluesky_get_token($uid); if (empty($token)) { return; } @@ -672,8 +738,6 @@ 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']; @@ -712,64 +776,37 @@ function bluesky_create_post(array $item, stdClass $root = null, stdClass $paren $post = [ 'collection' => 'app.bsky.feed.post', - 'repo' => DI::atProtocol()->getUserDid($uid), + 'repo' => bluesky_get_user_did($uid), 'record' => $record ]; - $parent = DI::atProtocol()->XRPCPost($uid, 'com.atproto.repo.createRecord', $post); - if (empty($parent->uri)) { + $parent = bluesky_xrpc_post($uid, 'com.atproto.repo.createRecord', $post); + if (empty($parent)) { if ($part == 0) { Worker::defer(); } return; } - DI::logger()->debug('Posting done', ['return' => $parent]); + Logger::debug('Posting done', ['return' => $parent]); if (empty($root)) { $root = $parent; } if (($key == 0) && ($item['gravity'] != Item::GRAVITY_PARENT)) { - $uri = DI::atpProcessor()->getUri($parent); - Item::update(['extid' => $uri], ['guid' => $item['guid']]); - DI::logger()->debug('Set extid', ['id' => $item['id'], 'extid' => $uri]); + $uri = bluesky_get_uri($parent); + Item::update(['extid' => $uri], ['id' => $item['id']]); + Logger::debug('Set extid', ['id' => $item['id'], 'extid' => $uri]); } } } -function bluesky_set_mentions(string $body): string -{ - // 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 { + // Remove all hashtag and mention links + $body = preg_replace("/([@!])\[url\=(.*?)\](.*?)\[\/url\]/ism", '$1$3', $body); + $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) { @@ -854,9 +891,6 @@ 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; } @@ -881,14 +915,7 @@ function bluesky_add_embed(int $uid, array $msg, array $record): array if (empty($blob)) { return []; } - $images[] = [ - 'alt' => $image['description'] ?? '', - 'image' => $blob, - 'aspectRatio' => [ - 'width' => $photo['width'], - 'height' => $photo['height'], - ] - ]; + $images[] = ['alt' => $image['description'] ?? '', 'image' => $blob]; } if (!empty($images)) { $record['embed'] = ['$type' => 'app.bsky.embed.images', 'images' => $images]; @@ -926,41 +953,35 @@ 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 = (string)$picture->asString(); + $content = $picture->asString(); $new_size = strlen($content); - 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]); - } + 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 = 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]); + $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]); return null; } - 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]); + 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 = DI::atpProcessor()->getUriParts($uri); + $parts = bluesky_get_uri_parts($uri); if (empty($parts)) { - DI::logger()->debug('No uri delected', ['uri' => $uri]); + Logger::debug('No uri delected', ['uri' => $uri]); return; } - DI::atProtocol()->XRPCPost($uid, 'com.atproto.repo.deleteRecord', $parts); - DI::logger()->debug('Deleted', ['parts' => $parts]); + bluesky_xrpc_post($uid, 'com.atproto.repo.deleteRecord', $parts); + Logger::debug('Deleted', ['parts' => $parts]); } -function bluesky_fetch_timeline(int $uid) +function bluesky_fetch_timeline(int $uid, int $last_poll) { - $data = DI::atProtocol()->XRPCGet('app.bsky.feed.getTimeline', [], $uid); + $data = bluesky_xrpc_get($uid, 'app.bsky.feed.getTimeline'); if (empty($data)) { return; } @@ -970,40 +991,14 @@ function bluesky_fetch_timeline(int $uid) } foreach (array_reverse($data->feed) as $entry) { - $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); + bluesky_process_post($entry->post, $uid, $uid, Item::PR_NONE, 0, 0, $last_poll); if (!empty($entry->reason)) { - 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); + bluesky_process_reason($entry->reason, bluesky_get_uri($entry->post), $uid); } } - 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; + // @todo Support paging + // [cursor] => 1684670516000::bafyreidq3ilwslmlx72jf5vrk367xcc63s6lrhzlyup2bi3zwcvso6w2vi } function bluesky_process_reason(stdClass $reason, string $uri, int $uid) @@ -1013,15 +1008,15 @@ function bluesky_process_reason(stdClass $reason, string $uri, int $uid) return; } - $contact = DI::atpActor()->getContactByDID($reason->by->did, $uid, 0); + $contact = bluesky_get_contact($reason->by, $uid, $uid); $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'], @@ -1037,96 +1032,91 @@ 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)) { - $pcid = Contact::getPublicContactId($contact['id'], $uid); - Item::update(['post-reason' => Item::PR_ANNOUNCEMENT, 'causer-id' => $pcid], ['uri' => $uri, 'uid' => $uid]); + $cdata = Contact::getPublicAndUserContactID($contact['id'], $uid); + Item::update(['post-reason' => Item::PR_ANNOUNCEMENT, 'causer-id' => $cdata['public']], ['uri' => $uri, 'uid' => $uid]); } } -function bluesky_fetch_notifications(int $uid) +function bluesky_fetch_notifications(int $uid, int $last_poll) { - $data = DI::atProtocol()->XRPCGet('app.bsky.notification.listNotifications', [], $uid); + $data = bluesky_xrpc_get($uid, 'app.bsky.notification.listNotifications'); if (empty($data->notifications)) { return; } - foreach ($data->notifications as $notification) { - $uri = DI::atpProcessor()->getUri($notification); + $uri = bluesky_get_uri($notification); if (Post::exists(['uri' => $uri, 'uid' => $uid]) || Post::exists(['extid' => $uri, 'uid' => $uid])) { - DI::logger()->debug('Notification already processed', ['uid' => $uid, 'reason' => $notification->reason, 'uri' => $uri, 'indexedAt' => $notification->indexedAt]); + Logger::debug('Notification already processed', ['uid' => $uid, 'reason' => $notification->reason, 'uri' => $uri, 'indexedAt' => $notification->indexedAt]); continue; } - DI::logger()->debug('Process notification', ['uid' => $uid, 'reason' => $notification->reason, 'uri' => $uri, 'indexedAt' => $notification->indexedAt]); + Logger::debug('Process notification', ['uid' => $uid, 'reason' => $notification->reason, 'uri' => $uri, 'indexedAt' => $notification->indexedAt]); switch ($notification->reason) { case 'like': - $item = DI::atpProcessor()->getHeaderFromPost($notification, $uri, $uid, Conversation::PARCEL_CONNECTOR); + $item = bluesky_get_header($notification, $uri, $uid, $uid); $item['gravity'] = Item::GRAVITY_ACTIVITY; $item['body'] = $item['verb'] = Activity::LIKE; - $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); + $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); if (!empty($item['thr-parent'])) { $data = Item::insert($item); - DI::logger()->debug('Got like', ['uid' => $uid, 'result' => $data, 'uri' => $uri]); + Logger::debug('Got like', ['uid' => $uid, 'result' => $data, 'uri' => $uri]); } else { - DI::logger()->info('Thread parent not found', ['uid' => $uid, 'parent' => $item['thr-parent'], 'uri' => $uri]); + Logger::info('Thread parent not found', ['uid' => $uid, 'parent' => $item['thr-parent'], 'uri' => $uri]); } break; case 'repost': - $item = DI::atpProcessor()->getHeaderFromPost($notification, $uri, $uid, Conversation::PARCEL_CONNECTOR); + $item = bluesky_get_header($notification, $uri, $uid, $uid); $item['gravity'] = Item::GRAVITY_ACTIVITY; $item['body'] = $item['verb'] = Activity::ANNOUNCE; - $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); + $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); if (!empty($item['thr-parent'])) { $data = Item::insert($item); - DI::logger()->debug('Got repost', ['uid' => $uid, 'result' => $data, 'uri' => $uri]); + Logger::debug('Got repost', ['uid' => $uid, 'result' => $data, 'uri' => $uri]); } else { - DI::logger()->info('Thread parent not found', ['uid' => $uid, 'parent' => $item['thr-parent'], 'uri' => $uri]); + Logger::info('Thread parent not found', ['uid' => $uid, 'parent' => $item['thr-parent'], 'uri' => $uri]); } break; case 'follow': - $contact = DI::atpActor()->getContactByDID($notification->author->did, $uid, $uid); - DI::logger()->debug('New follower', ['uid' => $uid, 'nick' => $contact['nick'], 'uri' => $uri]); + $contact = bluesky_get_contact($notification->author, $uid, $uid); + Logger::debug('New follower', ['uid' => $uid, 'nick' => $contact['nick'], 'uri' => $uri]); break; case 'mention': - $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]); + $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]); break; case 'reply': - $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]); + $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]); break; case 'quote': - $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]); + $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]); break; default: - DI::logger()->notice('Unhandled reason', ['reason' => $notification->reason, 'uri' => $uri]); + Logger::notice('Unhandled reason', ['reason' => $notification->reason, 'uri' => $uri]); break; } } } -function bluesky_fetch_feed(int $uid, string $feed) +function bluesky_fetch_feed(int $uid, string $feed, int $last_poll) { - $data = DI::atProtocol()->XRPCGet('app.bsky.feed.getFeed', ['feed' => $feed], $uid); + $data = bluesky_xrpc_get($uid, 'app.bsky.feed.getFeed', ['feed' => $feed]); if (empty($data)) { return; } @@ -1135,8 +1125,8 @@ function bluesky_fetch_feed(int $uid, string $feed) return; } - $feeddata = DI::atProtocol()->XRPCGet('app.bsky.feed.getFeedGenerator', ['feed' => $feed], $uid); - if (!empty($feeddata) && !empty($feeddata->view)) { + $feeddata = bluesky_xrpc_get($uid, 'app.bsky.feed.getFeedGenerator', ['feed' => $feed]); + if (!empty($feeddata)) { $feedurl = $feeddata->view->uri; $feedname = $feeddata->view->displayName; } else { @@ -1145,49 +1135,585 @@ function bluesky_fetch_feed(int $uid, string $feed) } foreach (array_reverse($data->feed) as $entry) { - $contact = DI::atpActor()->getContactByDID($entry->post->author->did, $uid, 0); + $contact = bluesky_get_contact($entry->post->author, 0, $uid); $languages = $entry->post->record->langs ?? []; if (!Relay::isWantedLanguage($entry->post->record->text, 0, $contact['id'] ?? 0, $languages)) { - DI::logger()->debug('Unwanted language detected', ['languages' => $languages, 'text' => $entry->post->record->text]); + Logger::debug('Unwanted language detected', ['text' => $entry->post->record->text]); continue; } - $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); + $uri_id = bluesky_process_post($entry->post, $uid, $uid, Item::PR_TAG, 0, 0, $last_poll); if (!empty($uri_id)) { $stored = Post\Category::storeFileByURIId($uri_id, $uid, Post\Category::SUBCRIPTION, $feedname, $feedurl); - DI::logger()->debug('Stored tag subscription for user', ['uri-id' => $uri_id, 'uid' => $uid, 'name' => $feedname, 'url' => $feedurl, 'stored' => $stored]); + Logger::debug('Stored tag subscription for user', ['uri-id' => $uri_id, 'uid' => $uid, 'name' => $feedname, 'url' => $feedurl, 'stored' => $stored]); } else { - DI::logger()->notice('Post not found', ['entry' => $entry]); + Logger::notice('Post not found', ['entry' => $entry]); } if (!empty($entry->reason)) { - bluesky_process_reason($entry->reason, DI::atpProcessor()->getUri($entry->post), $uid); + bluesky_process_reason($entry->reason, bluesky_get_uri($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); + } + + $item['restrictions'] = bluesky_get_restrictions_for_user($post, $item, $post_reason); + + 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; + } + + if (!empty($post->labels)) { + foreach ($post->labels as $label) { + // Only flag posts as sensitive based on labels that had been provided by the author. + // When "ver" is set to "1" it was flagged by some automated process. + if (empty($label->ver)) { + $item['sensitive'] = true; + Logger::debug('Sensitive content', ['uri-id' => $item['uri-id'], 'label' => $label]); + } + } + } + + return $item; +} + +function bluesky_get_restrictions_for_user(stdClass $post, array $item, int $post_reason): ?int +{ + if (!empty($post->viewer->replyDisabled)) { + return Item::CANT_REPLY; + } + + if (empty($post->threadgate)) { + return null; + } + + if (!isset($post->threadgate->record->allow)) { + return null; + } + + if ($item['uid'] == 0) { + return Item::CANT_REPLY; + } + + $restrict = true; + $type = '$type'; + foreach ($post->threadgate->record->allow as $allow) { + switch ($allow->$type) { + case 'app.bsky.feed.threadgate#followingRule': + // Only followers can reply. + if (Contact::isFollower($item['author-id'], $item['uid'])) { + $restrict = false; + } + break; + case 'app.bsky.feed.threadgate#mentionRule': + // Only mentioned accounts can reply. + if ($post_reason == Item::PR_TO) { + $restrict = false; + } + break; + case 'app.bsky.feed.threadgate#listRule'; + // Only accounts in the provided list can reply. We don't support this at the moment. + break; + } + } + + return $restrict ? Item::CANT_REPLY : null; +} + +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); + if (empty($class)) { + return $fallback; + } + + $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#savedFeedsPrefV2') { - $pinned = []; - foreach ($preference->items as $item) { - if (($item->type == 'feed') && $item->pinned) { - $pinned[] = $item->value; - } - } - return $pinned; + if ($preference->$type == 'app.bsky.actor.defs#savedFeedsPref') { + return $preference->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); @@ -1195,11 +1721,249 @@ function bluesky_get_preferences(int $uid): ?stdClass return $data; } - $data = DI::atProtocol()->XRPCGet('app.bsky.actor.getPreferences', [], $uid); - if (empty($data)) { - return null; - } + $data = bluesky_xrpc_get($uid, 'app.bsky.actor.getPreferences'); 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_did(int $uid, bool $refresh = false): ?string +{ + if (!$refresh) { + $did = DI::pConfig()->get($uid, 'bluesky', 'did'); + if (!empty($did)) { + return $did; + } + } + + $handle = DI::pConfig()->get($uid, 'bluesky', 'handle'); + if (empty($handle)) { + return null; + } + + $did = bluesky_get_did($handle); + if (empty($did)) { + return null; + } + + Logger::debug('Got DID for user', ['uid' => $uid, 'handle' => $handle, 'did' => $did]); + DI::pConfig()->set($uid, 'bluesky', 'did', $did); + return $did; +} + +function bluesky_get_user_pds(int $uid): ?string +{ + $pds = DI::pConfig()->get($uid, 'bluesky', 'pds'); + if (!empty($pds)) { + return $pds; + } + + $did = bluesky_get_user_did($uid); + if (empty($did)) { + return null; + } + + $pds = bluesky_get_pds($did); + if (empty($pds)) { + return null; + } + + 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 = bluesky_get_user_did($uid); + if (empty($did)) { + return ''; + } + + $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 +{ + $pds = bluesky_get_user_pds($uid); + if (empty($pds)) { + return null; + } + + try { + $curlResult = DI::httpClient()->post($pds . $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); + } + + $pds = bluesky_get_user_pds($uid); + if (empty($pds)) { + return null; + } + + $data = bluesky_get($pds . '/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', ['url' => $url, 'exception' => $e]); + return null; + } + + if (!$curlResult->isSuccess()) { + Logger::notice('API Error', ['url' => $url, '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 e4aa3fdc..c9a54223 100644 --- a/bluesky/bluesky_feed.php +++ b/bluesky/bluesky_feed.php @@ -1,16 +1,16 @@ 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]]); + Logger::debug('Importing feed - start', ['user' => $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]]); } diff --git a/bluesky/bluesky_notifications.php b/bluesky/bluesky_notifications.php index e1bf2047..ad35dfe0 100644 --- a/bluesky/bluesky_notifications.php +++ b/bluesky/bluesky_notifications.php @@ -1,16 +1,16 @@ notice('importing notifications - start', ['user' => $argv[1]]); - bluesky_fetch_notifications($argv[1]); - DI::logger()->notice('importing notifications - done', ['user' => $argv[1]]); + Logger::notice('importing notifications - start', ['user' => $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]]); } diff --git a/bluesky/bluesky_timeline.php b/bluesky/bluesky_timeline.php index 37b22d99..22ef2224 100644 --- a/bluesky/bluesky_timeline.php +++ b/bluesky/bluesky_timeline.php @@ -1,16 +1,16 @@ notice('importing timeline - start', ['user' => $argv[1]]); - bluesky_fetch_timeline($argv[1]); - DI::logger()->notice('importing timeline - done', ['user' => $argv[1]]); + Logger::notice('importing timeline - start', ['user' => $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]]); } diff --git a/bluesky/lang/C/messages.po b/bluesky/lang/C/messages.po index d573972c..9521ab89 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-09-29 18:16+0000\n" +"POT-Creation-Date: 2024-03-22 05:31+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,117 +17,131 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: bluesky.php:335 +#: bluesky.php:325 msgid "Save Settings" msgstr "" -#: bluesky.php:336 +#: bluesky.php:326 msgid "Allow your users to use your hostname for their Bluesky handles" msgstr "" -#: bluesky.php:336 +#: bluesky.php:326 #, 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." +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:365 +#: bluesky.php:354 #, php-format msgid "Allow to use %s as your Bluesky handle." msgstr "" -#: bluesky.php:365 +#: bluesky.php:354 #, 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\"." +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 +#: bluesky.php:361 msgid "Enable Bluesky Post Addon" msgstr "" -#: bluesky.php:376 +#: bluesky.php:362 msgid "Post to Bluesky by default" msgstr "" -#: bluesky.php:377 +#: bluesky.php:363 msgid "Import the remote timeline" msgstr "" -#: bluesky.php:378 +#: bluesky.php:364 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." +#: bluesky.php:364 +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 +#: bluesky.php:366 msgid "Personal Data Server" msgstr "" -#: bluesky.php:381 +#: bluesky.php:366 msgid "The personal data server (PDS) is the system that hosts your profile." msgstr "" -#: bluesky.php:382 +#: bluesky.php:367 msgid "Bluesky handle" msgstr "" -#: bluesky.php:383 +#: bluesky.php:368 msgid "Bluesky DID" msgstr "" -#: bluesky.php:383 -msgid "This is the unique identifier. It will be fetched automatically, when the handle is entered." +#: bluesky.php:368 +msgid "" +"This is the unique identifier. It will be fetched automatically, when the " +"handle is entered." msgstr "" -#: bluesky.php:384 +#: bluesky.php:369 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." +#: bluesky.php:369 +msgid "" +"Please don't add your real password here, but instead create a specific app " +"password in the Bluesky settings." msgstr "" -#: bluesky.php:390 +#: bluesky.php:375 msgid "Bluesky Import/Export" msgstr "" -#: bluesky.php:400 -msgid "You are not authenticated. Please enter your handle and the app password." +#: bluesky.php:385 +msgid "" +"You are not authenticated. Please enter your handle and the app password." msgstr "" -#: bluesky.php:420 -msgid "You are authenticated to Bluesky. For security reasons the password isn't stored." +#: bluesky.php:405 +msgid "" +"You are authenticated to Bluesky. For security reasons the password isn't " +"stored." msgstr "" -#: bluesky.php:422 -msgid "The communication with the personal data server service (PDS) is established." +#: bluesky.php:407 +msgid "" +"The communication with the personal data server service (PDS) is established." msgstr "" -#: bluesky.php:424 +#: bluesky.php:409 msgid "Communication issues with the personal data server service (PDS)." msgstr "" -#: bluesky.php:426 -msgid "The DID for the provided handle could not be detected. Please check if you entered the correct handle." +#: bluesky.php:411 +msgid "" +"The DID for the provided handle could not be detected. Please check if you " +"entered the correct handle." msgstr "" -#: bluesky.php:428 +#: bluesky.php:413 msgid "The personal data server service (PDS) could not be detected." msgstr "" -#: bluesky.php:430 -msgid "The authentication with the provided handle and password failed. Please check if you entered the correct password." +#: bluesky.php:415 +msgid "" +"The authentication with the provided handle and password failed. Please " +"check if you entered the correct password." msgstr "" -#: bluesky.php:492 +#: bluesky.php:484 msgid "Post to Bluesky" msgstr "" diff --git a/bluesky/templates/connector_settings.tpl b/bluesky/templates/connector_settings.tpl index a85bcd89..3ebea827 100644 --- a/bluesky/templates/connector_settings.tpl +++ b/bluesky/templates/connector_settings.tpl @@ -3,7 +3,6 @@ {{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 b7dd6504..78fb8bef 100644 --- a/buglink/buglink.php +++ b/buglink/buglink.php @@ -6,6 +6,7 @@ * Author: Mike Macgirvin */ +use Friendica\App; use Friendica\Core\Hook; use Friendica\DI; diff --git a/calc/calc.php b/calc/calc.php index 76d1805c..a8a340c4 100644 --- a/calc/calc.php +++ b/calc/calc.php @@ -6,6 +6,7 @@ * Author: Mike Macgirvin */ +use Friendica\App; use Friendica\Core\Hook; use Friendica\DI; @@ -15,7 +16,7 @@ function calc_install() { function calc_app_menu(array &$b) { - $b['app_menu'][] = ''; + $b['app_menu'][] = ''; } /** @@ -295,7 +296,7 @@ $o .= <<< EOT

Calculator



-
+
@@ -322,7 +323,7 @@ $o .= <<< EOT - + @@ -344,13 +345,13 @@ $o .= <<< EOT - +
diff --git a/catavatar/catavatar.php b/catavatar/catavatar.php index 7b5f05c0..2116ac44 100644 --- a/catavatar/catavatar.php +++ b/catavatar/catavatar.php @@ -6,8 +6,11 @@ * 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; @@ -26,7 +29,7 @@ function catavatar_install() Hook::register('addon_settings', __FILE__, 'catavatar_addon_settings'); Hook::register('addon_settings_post', __FILE__, 'catavatar_addon_settings_post'); - DI::logger()->notice('registered catavatar'); + Logger::notice('registered catavatar'); } /** diff --git a/catavatar/lang/it/messages.po b/catavatar/lang/it/messages.po index 9155bb48..e05bd277 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 , 2023 +# Sylke Vicious , 2021 # #, fuzzy msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-11-21 19:14-0500\n" +"POT-Creation-Date: 2020-12-29 00:53+0000\n" "PO-Revision-Date: 2018-04-07 05:23+0000\n" -"Last-Translator: Sylke Vicious , 2023\n" -"Language-Team: Italian (https://app.transifex.com/Friendica/teams/12172/it/)\n" +"Last-Translator: Sylke Vicious , 2021\n" +"Language-Team: Italian (https://www.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=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" #: catavatar.php:48 -msgid "Set default profile avatar or randomize the cat." -msgstr "Imposta l'immagine di profilo predefinita o crea un gatto casuale." - -#: 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:49 +msgid "More Random Cat!" +msgstr "Altro Gatto a caso!" -#: catavatar.php:58 +#: catavatar.php:50 msgid "Reset to email Cat" msgstr "Reimposta Gatto" -#: catavatar.php:77 +#: 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 msgid "The cat hadn't found itself." msgstr "Il gatto non ha trovato sé stesso." -#: catavatar.php:86 +#: catavatar.php:87 msgid "There was an error, the cat ran away." msgstr "Si è verificato un errore, il gatto è scappato." -#: catavatar.php:92 +#: catavatar.php:93 msgid "Profile Photos" msgstr "Foto del profilo" -#: catavatar.php:102 +#: catavatar.php:108 msgid "Meow!" msgstr "Miao!" diff --git a/catavatar/lang/it/strings.php b/catavatar/lang/it/strings.php index 8f78b3fe..3a33374a 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); - if ($n == 1) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; } + return intval($n != 1); }} -$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['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['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 d4fef6c5..5ca4c932 100644 --- a/cld/cld.php +++ b/cld/cld.php @@ -7,6 +7,7 @@ */ use Friendica\Core\Hook; +use Friendica\Core\Logger; use Friendica\DI; function cld_install() @@ -17,17 +18,7 @@ function cld_install() function cld_detect_languages(array &$data) { if (!in_array('cld2', get_loaded_extensions())) { - 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.'); + Logger::warning('CLD2 is not installed.'); return; } @@ -52,7 +43,7 @@ function cld_detect_languages(array &$data) } if (!$result['is_reliable']) { - 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']]); + 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; } @@ -62,12 +53,12 @@ function cld_detect_languages(array &$data) $available = array_keys(DI::l10n()->getLanguageCodes()); if (!in_array($detected, $available)) { - 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']]); + 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) { - 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']]); + 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 a3650e9b..d7933a8f 100644 --- a/convert/UnitConvertor.php +++ b/convert/UnitConvertor.php @@ -169,6 +169,7 @@ 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) @@ -279,4 +280,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 2545974c..57ce6ea8 100644 --- a/convert/convert.php +++ b/convert/convert.php @@ -6,6 +6,7 @@ * Author: Mike Macgirvin */ +use Friendica\App; use Friendica\Core\Hook; function convert_install() { @@ -25,7 +26,7 @@ function convert_content() { // @TODO Let's one day rewrite this to a modern composer package include 'UnitConvertor.php'; - $conv = new class('en') extends UnitConvertor + class TP_Converter extends UnitConvertor { public function __construct(string $lang = 'en') { @@ -42,7 +43,7 @@ function convert_content() { private function findBaseUnit($from, $to) { - foreach ($this->bases as $skey => $sval) { + while (list($skey, $sval) = each($this->bases)) { if ($skey == $from || $to == $skey || in_array($to, $sval) || in_array($from, $sval)) { return $skey; } @@ -62,7 +63,7 @@ function convert_content() { $cells[] = $cell; // We now have the base unit and value now lets produce the table; - foreach ($this->bases[$base_unit] as $val) { + while (list($key, $val) = each($this->bases[$base_unit])) { $cell ['value'] = $this->convert($value, $from_unit, $val, $precision) . ' ' . $val; $cell ['class'] = ($val == $from_unit || $val == $to_unit) ? 'framedred' : ''; $cells[] = $cell; @@ -85,7 +86,9 @@ function convert_content() { return $string; } - }; + } + + $conv = new TP_Converter('en'); $conversions = [ 'Temperature' => ['base' => 'Celsius', @@ -173,15 +176,15 @@ function convert_content() { ] ]; - foreach ($conversions as $key => $val) { + while (list($key, $val) = each($conversions)) { $conv->addConversion($val['base'], $val['conv']); $list[$key][] = $val['base']; - foreach ($val['conv'] as $ukey => $uval) { + while (list($ukey, $uval) = each($val['conv'])) { $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)) . '

'; @@ -199,9 +202,10 @@ function convert_content() { $o .= ''; $o .= ' - - - - - - {{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 4523d911..731cf003 100644 --- a/rendertime/rendertime.php +++ b/rendertime/rendertime.php @@ -7,6 +7,7 @@ * */ +use Friendica\App; use Friendica\Core\Hook; use Friendica\Core\Renderer; use Friendica\DI; @@ -59,7 +60,7 @@ function rendertime_page_end(string &$o) if (DI::userSession()->isSiteAdmin() && (($_GET['mode'] ?? '') != 'minimal') && !DI::mode()->isMobile() && !DI::mode()->isMobile() && !$ignored) { - $o = $o . '
'; //Add css to header - $css_file = __DIR__ . '/view/' . DI::appHelper()->getCurrentTheme() . '.css'; + $css_file = __DIR__ . '/view/' . DI::app()->getCurrentTheme() . '.css'; if (!file_exists($css_file)) { $css_file = __DIR__ . '/view/default.css'; } @@ -104,7 +105,7 @@ function smileybutton_jot_tool(string &$body) DI::page()->registerStylesheet($css_file); //Get the correct image for the theme - $image = 'addon/smileybutton/view/' . DI::appHelper()->getCurrentTheme() . '.png'; + $image = 'addon/smileybutton/view/' . DI::app()->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 4a80168d..e8af21e1 100644 --- a/smilies_adult/smilies_adult.php +++ b/smilies_adult/smilies_adult.php @@ -4,11 +4,12 @@ * 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 558af473..e4d80c0c 100644 --- a/startpage/startpage.php +++ b/startpage/startpage.php @@ -7,6 +7,7 @@ * */ +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 bffca163..020c69c4 100644 --- a/statusnet/library/codebirdsn.php +++ b/statusnet/library/codebirdsn.php @@ -31,10 +31,11 @@ use Friendica\Core\System; /** * Define constants */ -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 = explode(' ', 'OBJECT ARRAY JSON'); +foreach ($constants as $i => $id) { + $id = 'CODEBIRD_RETURNFORMAT_' . $id; + defined($id) or define($id, $i); +} $constants = array( 'CURLE_SSL_CERTPROBLEM' => 58, 'CURLE_SSL_CACERT' => 60, @@ -54,8 +55,6 @@ unset($id); * * @package codebird * @subpackage codebird-php - * - * @method object statuses_update(array $postdata) */ class CodebirdSN { @@ -118,7 +117,7 @@ class CodebirdSN * Returns singleton class instance * Always use this method unless you're working with multiple authenticated users at once * - * @return CodebirdSN The instance + * @return Codebird The instance */ public static function getInstance() { @@ -422,7 +421,6 @@ class CodebirdSN } break; case CODEBIRD_RETURNFORMAT_OBJECT: - /** @var object $reply */ $reply->httpstatus = $httpstatus; if ($httpstatus == 200) { self::setBearerToken($reply->access_token); @@ -493,7 +491,7 @@ class CodebirdSN /** * Generates a (hopefully) unique random string * - * @param int $length The optional length of the string to generate + * @param int optional $length The length of the string to generate * * @return string The random string */ @@ -508,9 +506,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 $params optional 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 optional $params The API call parameters, associative * * @return string Authorization HTTP header */ @@ -764,13 +762,13 @@ class CodebirdSN * @param string $method The API method to call * @param array $params The parameters to send along * - * @return string + * @return void */ protected function _buildMultipart($method, $params) { // well, files will only work in multipart methods if (! $this->_detectMultipart($method)) { - return ''; + return; } // only check specific parameters @@ -785,19 +783,18 @@ 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 @@ -874,12 +871,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 $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 + * @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 * * @return mixed The API reply, encoded in the set return_format */ @@ -921,7 +918,7 @@ class CodebirdSN $authorization = 'Authorization: Bearer ' . self::$_oauth_bearer_token; } $request_headers = array(); - if ($authorization !== '') { + if (isset($authorization)) { $request_headers[] = $authorization; $request_headers[] = 'Expect:'; } @@ -962,7 +959,6 @@ 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; @@ -976,7 +972,7 @@ class CodebirdSN * @param string $method The method that has been called * @param string $reply The actual reply, JSON-encoded or URL-encoded * - * @return string|array|object The parsed reply + * @return array|object The parsed reply */ protected function _parseApiReply($method, $reply) { diff --git a/statusnet/library/statusnetoauth.php b/statusnet/library/statusnetoauth.php index da21be58..c9bb0163 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 { - public function get_maxlength() + 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; } - public function accessTokenURL() + function accessTokenURL() { return $this->host . 'oauth/access_token'; } - public function authenticateURL() + function authenticateURL() { return $this->host . 'oauth/authenticate'; } - public function authorizeURL() + function authorizeURL() { return $this->host . 'oauth/authorize'; } - public function requestTokenURL() + function requestTokenURL() { return $this->host . 'oauth/request_token'; } - public function __construct($apipath, $consumer_key, $consumer_secret, $oauth_token = NULL, $oauth_token_secret = NULL) + 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,9 +52,14 @@ class StatusNetOAuth extends TwitterOAuth * * Copied here from the TwitterOAuth library and complemented by applying the proxy settings of Friendica * - * @return array|object|mixed API results + * @param string $method + * @param string $host + * @param string $path + * @param array $parameters + * + * @return array|object API results */ - public function http($url, $method, $postfields = NULL) + 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 bab66195..b33b5f9d 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 array + * @var string */ public $http_info; - /** @var OAuthToken|null */ + /** @var OAuthToken */ private $token; /** @var OAuthConsumer */ private $consumer; @@ -59,27 +59,27 @@ class TwitterOAuth /** * Set API URLS */ - public function accessTokenURL() + function accessTokenURL() { return 'https://api.twitter.com/oauth/access_token'; } - public function authenticateURL() + function authenticateURL() { return 'https://twitter.com/oauth/authenticate'; } - public function authorizeURL() + function authorizeURL() { return 'https://twitter.com/oauth/authorize'; } - public function requestTokenURL() + function requestTokenURL() { return 'https://api.twitter.com/oauth/request_token'; } - public function __construct($consumer_key, $consumer_secret, $oauth_token = null, $oauth_token_secret = null) + 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 callable $oauth_callback + * @param callback $oauth_callback * @return array */ - public function getRequestToken($oauth_callback = null) + function getRequestToken($oauth_callback = null) { $parameters = []; if (!empty($oauth_callback)) { @@ -112,9 +112,11 @@ class TwitterOAuth /** * Get the authorize URL * + * @param array $token + * @param bool $sign_in_with_tumblr * @return string */ - public function getAuthorizeURL($token, $sign_in_with_twitter = TRUE) + function getAuthorizeURL($token, $sign_in_with_twitter = TRUE) { if (is_array($token)) { $token = $token['oauth_token']; @@ -137,7 +139,7 @@ class TwitterOAuth * "user_id" => "9436992", * "screen_name" => "abraham") */ - public function getAccessToken($oauth_verifier = FALSE) + function getAccessToken($oauth_verifier = FALSE) { $parameters = []; if (!empty($oauth_verifier)) { @@ -162,7 +164,7 @@ class TwitterOAuth * "screen_name" => "abraham", * "x_auth_expires" => "0") */ - public function getXAuthToken($username, $password) + function getXAuthToken($username, $password) { $parameters = []; $parameters['x_auth_username'] = $username; @@ -182,7 +184,7 @@ class TwitterOAuth * @param array $parameters * @return mixed|string */ - public function get($url, $parameters = []) + function get($url, $parameters = []) { $response = $this->oAuthRequest($url, 'GET', $parameters); if ($this->format === 'json' && $this->decode_json) { @@ -199,7 +201,7 @@ class TwitterOAuth * @param array $parameters * @return mixed|string */ - public function post($url, $parameters = []) + function post($url, $parameters = []) { $response = $this->oAuthRequest($url, 'POST', $parameters); if ($this->format === 'json' && $this->decode_json) { @@ -216,7 +218,7 @@ class TwitterOAuth * @param array $parameters * @return mixed|string */ - public function delete($url, $parameters = []) + function delete($url, $parameters = []) { $response = $this->oAuthRequest($url, 'DELETE', $parameters); if ($this->format === 'json' && $this->decode_json) { @@ -234,7 +236,7 @@ class TwitterOAuth * @param array $parameters * @return mixed|string */ - public function oAuthRequest($url, $method, $parameters) + function oAuthRequest($url, $method, $parameters) { if (strrpos($url, 'https://') !== 0 && strrpos($url, 'http://') !== 0) { $url = "{$this->host}{$url}.{$this->format}"; @@ -258,9 +260,9 @@ class TwitterOAuth * @param string $url * @param string $method * @param mixed $postfields - * @return string|bool|mixed API results + * @return string API results */ - public function http($url, $method, $postfields = null) + function http($url, $method, $postfields = null) { $this->http_info = []; $ci = curl_init(); @@ -305,7 +307,7 @@ class TwitterOAuth * @param string $header * @return int */ - public function getHeader($ch, $header) + function getHeader($ch, $header) { $i = strpos($header, ':'); if (!empty($i)) { diff --git a/statusnet/statusnet.php b/statusnet/statusnet.php index 8663aaea..f0372852 100644 --- a/statusnet/statusnet.php +++ b/statusnet/statusnet.php @@ -38,8 +38,10 @@ 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; @@ -57,7 +59,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'); - DI::logger()->notice('installed GNU Social'); + Logger::notice('installed GNU Social'); } function statusnet_jot_nets(array &$jotnets_fields) @@ -294,7 +296,7 @@ function statusnet_hook_fork(array &$b) $post = $b['data']; - if ($post['deleted'] || ($post['created'] !== $post['edited']) || strpos($post['postopts'] ?? '', 'statusnet') === false || ($post['gravity'] != Item::GRAVITY_PARENT) || ($post['private'] == Item::PRIVATE)) { + if ($post['deleted'] || ($post['created'] !== $post['edited']) || strpos($post['postopts'] ?? '', 'statusnet') === false || ($post['parent'] != $post['id']) || $post['private']) { $b['execute'] = false; return; } @@ -334,7 +336,7 @@ function statusnet_post_hook(array &$b) /** * Post to GNU Social */ - if ($b['deleted'] || ($b['private'] == Item::PRIVATE) || ($b['created'] !== $b['edited'])) { + if ($b['deleted'] || $b['private'] || ($b['created'] !== $b['edited'])) { return; } @@ -354,7 +356,7 @@ function statusnet_post_hook(array &$b) return; } - DI::logger()->notice('GNU Socialpost invoked'); + Logger::notice('GNU Socialpost invoked'); DI::pConfig()->load($b['uid'], 'statusnet'); @@ -364,8 +366,6 @@ 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); - DI::logger()->info('statusnet_post send, result: ' . print_r($result, true) . + 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)) { - DI::logger()->notice('Send to GNU Social failed: "' . $result->error . '"'); + Logger::notice('Send to GNU Social failed: "' . $result->error . '"'); } elseif ($iscomment) { - DI::logger()->notice('statusnet_post: Update extid ' . $result->id . ' for post id ' . $b['id']); + 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,13 +439,11 @@ 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 a07c690c..b3e1feb6 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'); - DI::logger()->notice('installed tesseract'); + Logger::notice('installed tesseract'); } function tesseract_ocr_detection(&$media) @@ -26,13 +26,12 @@ 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) { - DI::logger()->info('Error calling TesseractOCR', ['message' => $th->getMessage()]); - } + Logger::info('Error calling TesseractOCR', ['message' => $th->getMessage()]); + } } diff --git a/testdrive/testdrive.php b/testdrive/testdrive.php index 90fb5918..55645284 100644 --- a/testdrive/testdrive.php +++ b/testdrive/testdrive.php @@ -6,6 +6,7 @@ * Author: Mike Macgirvin */ +use Friendica\App; use Friendica\Core\Hook; use Friendica\Core\Search; use Friendica\Database\DBA; @@ -26,7 +27,7 @@ function testdrive_install() function testdrive_load_config(ConfigFileManager $loader) { - DI::appHelper()->getConfigCache()->load($loader->loadAddonConfig('testdrive'), \Friendica\Core\Config\ValueObject\Cache::SOURCE_STATIC); + DI::app()->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 082b58c1..0f9f4fb6 100644 --- a/tictac/tictac.php +++ b/tictac/tictac.php @@ -7,6 +7,7 @@ * Status: unsupported */ +use Friendica\App; use Friendica\Core\Hook; use Friendica\DI; @@ -29,12 +30,7 @@ function tictac_module() {} function tictac_content() { - $o = ''; - $dimen = 3; - $handicap = 0; - $mefirst = 0; - $yours = ''; - $mine = ''; + $o = ''; if($_POST['move']) { $handicap = DI::args()->get(1); @@ -49,6 +45,9 @@ function tictac_content() { $handicap = DI::args()->get(1); $dimen = 3; } + else { + $dimen = 3; + } $o .= '

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


'; @@ -71,7 +70,6 @@ class tictac { private $dimen; private $first_move = true; private $handicap = 0; - private $mefirst; private $yours; private $mine; private $winning_play; @@ -163,10 +161,10 @@ class tictac { ]; - function __construct($dimen, $handicap, $mefirst, $yours, $mine) { - $this->dimen = $dimen; - $this->handicap = $handicap ? 1 : 0; - $this->mefirst = $mefirst ? 1 : 0; + function __construct($dimen,$handicap,$mefirst,$yours,$mine) { + $this->dimen = 3; + $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'); @@ -177,7 +175,6 @@ class tictac { } function play() { - $o = ''; if($this->first_move) { if(rand(0,1) == 1) { @@ -229,8 +226,6 @@ class tictac { } function parse_moves($player) { - $str = ''; - if($player == 'me') $str = $this->mine; if($player == 'you') @@ -634,7 +629,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 48a9e8cb..7879231d 100644 --- a/tumblr/lang/ar/messages.po +++ b/tumblr/lang/ar/messages.po @@ -8,81 +8,64 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "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: FULL NAME \n" -"Language-Team: Arabic (http://app.transifex.com/Friendica/friendica/language/ar/)\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" "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:243 +#: tumblr.php:40 msgid "Permission denied." msgstr "الطلب مرفوض." -#: tumblr.php:296 +#: tumblr.php:70 tumblr.php:284 msgid "Save Settings" msgstr "Save Settings" -#: tumblr.php:297 +#: tumblr.php:72 msgid "Consumer Key" msgstr "" -#: tumblr.php:298 +#: tumblr.php:73 msgid "Consumer Secret" msgstr "" -#: tumblr.php:299 -msgid "Maximum tags" +#: tumblr.php:178 +msgid "You are now authenticated to tumblr." msgstr "" -#: tumblr.php:299 -msgid "" -"Maximum number of tags that a user can follow. Enter 0 to deactivate the " -"feature." +#: tumblr.php:179 +msgid "return to the connector page" +msgstr "الرجوع إلى صفحة الموصل" + +#: tumblr.php:195 +msgid "Post to Tumblr" msgstr "" -#: tumblr.php:336 -msgid "Post to page:" +#: tumblr.php:225 tumblr.php:229 +msgid "Tumblr Export" msgstr "" -#: tumblr.php:342 +#: tumblr.php:233 msgid "(Re-)Authenticate your tumblr page" msgstr "" -#: tumblr.php:343 -msgid "You are not authenticated to tumblr" -msgstr "" - -#: tumblr.php:348 +#: tumblr.php:237 msgid "Enable Tumblr Post Addon" msgstr "" -#: tumblr.php:349 +#: tumblr.php:243 msgid "Post to Tumblr by default" msgstr "" -#: tumblr.php:350 -msgid "Import the remote timeline" +#: tumblr.php:264 +msgid "Post to page:" 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" +#: tumblr.php:278 +msgid "You are not authenticated to tumblr" msgstr "" diff --git a/tumblr/lang/ar/strings.php b/tumblr/lang/ar/strings.php index 3f7ca4e4..ffd3337c 100644 --- a/tumblr/lang/ar/strings.php +++ b/tumblr/lang/ar/strings.php @@ -7,3 +7,4 @@ 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 cb6f91e6..4e031be6 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: 2023-04-29 06:56+0000\n" +"POT-Creation-Date: 2021-11-21 19:17-0500\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,71 +21,54 @@ 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:243 +#: tumblr.php:39 msgid "Permission denied." msgstr "Přístup odmítnut." -#: tumblr.php:296 +#: tumblr.php:69 msgid "Save Settings" msgstr "" -#: tumblr.php:297 +#: tumblr.php:71 msgid "Consumer Key" msgstr "" -#: tumblr.php:298 +#: tumblr.php:72 msgid "Consumer Secret" msgstr "" -#: tumblr.php:299 -msgid "Maximum tags" -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 number of tags that a user can follow. Enter 0 to deactivate the " -"feature." -msgstr "" +#: tumblr.php:178 +msgid "return to the connector page" +msgstr "návrat ke stránce konektor" -#: tumblr.php:336 +#: tumblr.php:194 +msgid "Post to Tumblr" +msgstr "Posílat na Tumblr" + +#: tumblr.php:225 msgid "Post to page:" msgstr "Posílat na stránku:" -#: tumblr.php:342 +#: tumblr.php:231 msgid "(Re-)Authenticate your tumblr page" msgstr "(Znovu) přihlásit k Vaší stránce Tumblr" -#: tumblr.php:343 +#: tumblr.php:232 msgid "You are not authenticated to tumblr" msgstr "Nyní nejste přihlášen/a k Tumblr." -#: tumblr.php:348 +#: tumblr.php:237 msgid "Enable Tumblr Post Addon" msgstr "Povolit doplněk Tumblr Post" -#: tumblr.php:349 +#: tumblr.php:238 msgid "Post to Tumblr by default" msgstr "Ve výchozím stavu posílat příspěvky na Tumblr" -#: tumblr.php:350 -msgid "Import the remote timeline" +#: tumblr.php:244 +msgid "Tumblr Export" 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 3135b0b8..2f5f8115 100644 --- a/tumblr/lang/cs/strings.php +++ b/tumblr/lang/cs/strings.php @@ -6,9 +6,11 @@ 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 c41ba45f..8056174d 100644 --- a/tumblr/lang/de/messages.po +++ b/tumblr/lang/de/messages.po @@ -4,8 +4,6 @@ # # # Translators: -# Raroun, 2023 -# Raroun, 2023 # Tobias Diekershoff , 2014-2015 # Tobias Diekershoff , 2018,2021 # Ulf Rompe , 2019 @@ -13,9 +11,9 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-04-29 06:56+0000\n" +"POT-Creation-Date: 2021-11-21 19:17-0500\n" "PO-Revision-Date: 2014-06-23 12:58+0000\n" -"Last-Translator: Raroun, 2023\n" +"Last-Translator: Tobias Diekershoff , 2018,2021\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" @@ -23,71 +21,54 @@ msgstr "" "Language: de\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: tumblr.php:243 +#: tumblr.php:39 msgid "Permission denied." msgstr "Zugriff verweigert." -#: tumblr.php:296 +#: tumblr.php:69 msgid "Save Settings" msgstr "Einstellungen speichern" -#: tumblr.php:297 +#: tumblr.php:71 msgid "Consumer Key" msgstr "Consumer Key" -#: tumblr.php:298 +#: tumblr.php:72 msgid "Consumer Secret" msgstr "Consumer Secret" -#: tumblr.php:299 -msgid "Maximum tags" -msgstr "Maximale Anzahl an Tags" +#: tumblr.php:177 +msgid "You are now authenticated to tumblr." +msgstr "Du bist nun auf tumblr authentifiziert." -#: 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:178 +msgid "return to the connector page" +msgstr "zurück zur Connector-Seite" -#: tumblr.php:336 +#: tumblr.php:194 +msgid "Post to Tumblr" +msgstr "Auf Tumblr veröffentlichen" + +#: tumblr.php:225 msgid "Post to page:" msgstr "Auf tumblr veröffentlichen" -#: tumblr.php:342 +#: tumblr.php:231 msgid "(Re-)Authenticate your tumblr page" msgstr "(Re-)Authentifizierung deiner tumblr-Seite" -#: tumblr.php:343 +#: tumblr.php:232 msgid "You are not authenticated to tumblr" msgstr "Du bist gegenüber tumblr nicht authentifiziert" -#: tumblr.php:348 +#: tumblr.php:237 msgid "Enable Tumblr Post Addon" msgstr "Tumblr-Post-Addon aktivieren" -#: tumblr.php:349 +#: tumblr.php:238 msgid "Post to Tumblr by default" msgstr "Standardmäßig bei Tumblr veröffentlichen" -#: 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" +#: tumblr.php:244 +msgid "Tumblr Export" +msgstr "Tumblr Export" diff --git a/tumblr/lang/de/strings.php b/tumblr/lang/de/strings.php index ed9af957..ce43615c 100644 --- a/tumblr/lang/de/strings.php +++ b/tumblr/lang/de/strings.php @@ -9,15 +9,12 @@ $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['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['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['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['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'; +$a->strings['Tumblr Export'] = 'Tumblr Export'; diff --git a/tumblr/lang/fr/messages.po b/tumblr/lang/fr/messages.po index 43dba8e3..ef2f0e3c 100644 --- a/tumblr/lang/fr/messages.po +++ b/tumblr/lang/fr/messages.po @@ -5,7 +5,7 @@ # # Translators: # bob lebonche , 2021 -# cracrayol, 2023-2024 +# Florent C., 2023 # 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: cracrayol, 2023-2024\n" +"Last-Translator: Florent C., 2023\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 "Étiquettes maximum" +msgstr "Tags maximum" #: tumblr.php:299 msgid "" "Maximum number of tags that a user can follow. Enter 0 to deactivate the " "feature." -msgstr "Nombre maximum d'étiquettes qu'un utilisateur peut suivre. Entrez 0 pour désactiver cette fonctionnalité." +msgstr "Nombre maximum de tags 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 "Étiquettes suivies" +msgstr "Tags suivis" #: tumblr.php:351 #, php-format msgid "" "Comma separated list of up to %d tags that will be imported additionally to " "the timeline" -msgstr "Liste contenant jusqu'à %d étiquettes, séparées par des virgules, qui seront importées dans le flux" +msgstr "Liste séparée par des virgules contenant jusqu'à %d tags qui seront importés 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 f23c9c44..ece76c74 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'] = 'É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['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['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'] = 'É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['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['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 0f7e2237..f3d1df55 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: 2023-04-29 06:56+0000\n" +"POT-Creation-Date: 2021-11-21 19:17-0500\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,71 +20,54 @@ msgstr "" "Language: it\n" "Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" -#: tumblr.php:243 +#: tumblr.php:39 msgid "Permission denied." msgstr "Permesso negato." -#: tumblr.php:296 +#: tumblr.php:69 msgid "Save Settings" msgstr "Salva Impostazioni" -#: tumblr.php:297 +#: tumblr.php:71 msgid "Consumer Key" msgstr "Consumer Key" -#: tumblr.php:298 +#: tumblr.php:72 msgid "Consumer Secret" msgstr "Consumer Secret" -#: tumblr.php:299 -msgid "Maximum tags" -msgstr "" +#: tumblr.php:177 +msgid "You are now authenticated to tumblr." +msgstr "Sei autenticato su Tumblr." -#: tumblr.php:299 -msgid "" -"Maximum number of tags that a user can follow. Enter 0 to deactivate the " -"feature." -msgstr "" +#: tumblr.php:178 +msgid "return to the connector page" +msgstr "ritorna alla pagina del connettore" -#: tumblr.php:336 +#: tumblr.php:194 +msgid "Post to Tumblr" +msgstr "Invia a Tumblr" + +#: tumblr.php:225 msgid "Post to page:" msgstr "Invia alla pagina:" -#: tumblr.php:342 +#: tumblr.php:231 msgid "(Re-)Authenticate your tumblr page" msgstr "(Ri)Autenticati con la tua pagina Tumblr" -#: tumblr.php:343 +#: tumblr.php:232 msgid "You are not authenticated to tumblr" msgstr "Non sei autenticato su Tumblr" -#: tumblr.php:348 +#: tumblr.php:237 msgid "Enable Tumblr Post Addon" msgstr "Abilita componente aggiuntivo di invio a Tumblr" -#: tumblr.php:349 +#: tumblr.php:238 msgid "Post to Tumblr by default" msgstr "Invia sempre a 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" +#: tumblr.php:244 +msgid "Tumblr Export" +msgstr "Esporta Tumblr" diff --git a/tumblr/lang/it/strings.php b/tumblr/lang/it/strings.php index e58ab31c..d4d4e257 100644 --- a/tumblr/lang/it/strings.php +++ b/tumblr/lang/it/strings.php @@ -9,9 +9,12 @@ $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['Post to Tumblr'] = 'Invia a Tumblr'; +$a->strings['Tumblr Export'] = 'Esporta Tumblr'; diff --git a/tumblr/lang/pl/messages.po b/tumblr/lang/pl/messages.po index a8676455..27a44e15 100644 --- a/tumblr/lang/pl/messages.po +++ b/tumblr/lang/pl/messages.po @@ -10,81 +10,64 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-04-29 06:56+0000\n" +"POT-Creation-Date: 2021-11-21 19:17-0500\n" "PO-Revision-Date: 2014-06-23 12:58+0000\n" "Last-Translator: Piotr Strębski , 2022\n" -"Language-Team: Polish (http://app.transifex.com/Friendica/friendica/language/pl/)\n" +"Language-Team: Polish (http://www.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:243 +#: tumblr.php:39 msgid "Permission denied." msgstr "Odmowa dostępu." -#: tumblr.php:296 +#: tumblr.php:69 msgid "Save Settings" msgstr "Zapisz ustawienia" -#: tumblr.php:297 +#: tumblr.php:71 msgid "Consumer Key" msgstr "Klucz klienta" -#: tumblr.php:298 +#: tumblr.php:72 msgid "Consumer Secret" msgstr "Tajny klucz klienta" -#: tumblr.php:299 -msgid "Maximum tags" -msgstr "" +#: tumblr.php:177 +msgid "You are now authenticated to tumblr." +msgstr "Jesteś teraz uwierzytelniony na tumblr." -#: tumblr.php:299 -msgid "" -"Maximum number of tags that a user can follow. Enter 0 to deactivate the " -"feature." -msgstr "" +#: tumblr.php:178 +msgid "return to the connector page" +msgstr "powrót do strony łącza" -#: tumblr.php:336 +#: tumblr.php:194 +msgid "Post to Tumblr" +msgstr "Opublikuj w Tumblr" + +#: tumblr.php:225 msgid "Post to page:" msgstr "Opublikuj na stronie:" -#: tumblr.php:342 +#: tumblr.php:231 msgid "(Re-)Authenticate your tumblr page" msgstr "(Re-) Uwierzytelnij swoją stronę tumblr" -#: tumblr.php:343 +#: tumblr.php:232 msgid "You are not authenticated to tumblr" msgstr "Nie jesteś uwierzytelniony w tumblr" -#: tumblr.php:348 +#: tumblr.php:237 msgid "Enable Tumblr Post Addon" msgstr "Włącz dodatek Tumblr" -#: tumblr.php:349 +#: tumblr.php:238 msgid "Post to Tumblr by default" msgstr "Wyślij domyślnie 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" +#: tumblr.php:244 +msgid "Tumblr Export" +msgstr "Eksportuj do Tumblr" diff --git a/tumblr/lang/pl/strings.php b/tumblr/lang/pl/strings.php index 896b21ba..a9f3bfb5 100644 --- a/tumblr/lang/pl/strings.php +++ b/tumblr/lang/pl/strings.php @@ -9,9 +9,12 @@ $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['Post to Tumblr'] = 'Opublikuj w Tumblr'; +$a->strings['Tumblr Export'] = 'Eksportuj do Tumblr'; diff --git a/tumblr/lang/sv/messages.po b/tumblr/lang/sv/messages.po index 3ff328a8..fe631007 100644 --- a/tumblr/lang/sv/messages.po +++ b/tumblr/lang/sv/messages.po @@ -10,81 +10,64 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "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: Kristoffer Grundström , 2022\n" -"Language-Team: Swedish (http://app.transifex.com/Friendica/friendica/language/sv/)\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" "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:243 +#: tumblr.php:39 msgid "Permission denied." msgstr "Åtkomst nekad." -#: tumblr.php:296 +#: tumblr.php:69 msgid "Save Settings" msgstr "" -#: tumblr.php:297 +#: tumblr.php:71 msgid "Consumer Key" msgstr "" -#: tumblr.php:298 +#: tumblr.php:72 msgid "Consumer Secret" msgstr "" -#: tumblr.php:299 -msgid "Maximum tags" +#: 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" msgstr "" -#: tumblr.php:299 -msgid "" -"Maximum number of tags that a user can follow. Enter 0 to deactivate the " -"feature." +#: tumblr.php:194 +msgid "Post to Tumblr" msgstr "" -#: tumblr.php:336 +#: tumblr.php:225 msgid "Post to page:" msgstr "" -#: tumblr.php:342 +#: tumblr.php:231 msgid "(Re-)Authenticate your tumblr page" msgstr "" -#: tumblr.php:343 +#: tumblr.php:232 msgid "You are not authenticated to tumblr" msgstr "Du är inte autentiserad till tumblr" -#: tumblr.php:348 +#: tumblr.php:237 msgid "Enable Tumblr Post Addon" msgstr "" -#: tumblr.php:349 +#: tumblr.php:238 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" +#: tumblr.php:244 +msgid "Tumblr Export" msgstr "" diff --git a/tumblr/lang/sv/strings.php b/tumblr/lang/sv/strings.php index 84a0e774..4d39d3c2 100644 --- a/tumblr/lang/sv/strings.php +++ b/tumblr/lang/sv/strings.php @@ -6,4 +6,5 @@ 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 9e691bf2..04f6a0a4 100644 --- a/tumblr/tumblr.php +++ b/tumblr/tumblr.php @@ -14,6 +14,7 @@ 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; @@ -21,7 +22,6 @@ 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,6 +31,7 @@ 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; @@ -59,12 +60,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'); - DI::logger()->info('installed tumblr'); + Logger::info('installed tumblr'); } function tumblr_load_config(ConfigFileManager $loader) { - DI::appHelper()->getConfigCache()->load($loader->loadAddonConfig('tumblr'), \Friendica\Core\Config\ValueObject\Cache::SOURCE_STATIC); + DI::app()->getConfigCache()->load($loader->loadAddonConfig('tumblr'), \Friendica\Core\Config\ValueObject\Cache::SOURCE_STATIC); } function tumblr_check_item_notification(array &$notification_data) @@ -120,19 +121,18 @@ function tumblr_item_by_link(array &$hookData) return; } - DI::logger()->debug('Found tumblr post', ['url' => $hookData['uri'], 'blog' => $matches[1], 'id' => $matches[2]]); + 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) { - DI::logger()->notice('Error fetching status', ['meta' => $result->meta, 'response' => $result->response, 'errors' => $result->errors, 'blog' => $matches[1], 'id' => $matches[2]]); + Logger::notice('Error fetching status', ['meta' => $result->meta, 'response' => $result->response, 'errors' => $result->errors, 'blog' => $matches[1], 'id' => $matches[2]]); return []; } - DI::logger()->debug('Got post', ['blog' => $matches[1], 'id' => $matches[2], 'result' => $result->response->posts]); + 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; } - DI::logger()->debug('Check if contact is Tumblr', ['url' => $hook_data['url']]); + Logger::debug('Check if contact is Tumblr', ['url' => $hook_data['url']]); $fields = tumblr_get_contact_by_url($hook_data['url'], $uid); if (empty($fields)) { - DI::logger()->debug('Contact is not a Tumblr contact', ['url' => $hook_data['url']]); + 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; - DI::logger()->debug('Successfully start following', ['url' => $fields['url']]); + Logger::debug('Successfully start following', ['url' => $fields['url']]); } else { - DI::logger()->notice('Following failed', ['meta' => $result->meta, 'response' => $result->response, 'errors' => $result->errors, 'url' => $fields['url']]); + 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']) { - $ucid = Contact::getUserContactId($hook_data['contact']['id'], $hook_data['uid']); - if ($ucid) { - Contact::remove($ucid); + $cdata = Contact::getPublicAndUserContactID($hook_data['contact']['id'], $hook_data['uid']); + if (!empty($cdata['user'])) { + Contact::remove($cdata['user']); } } } @@ -238,7 +238,9 @@ 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() { @@ -391,17 +393,12 @@ 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 = array_slice( - array_filter( - array_map( - function($tag) { return trim($tag, ' #');}, - explode(',', $_POST['tags']) ?: [] - ) - ), - 0, - $max_tags, - ); + $tags = []; + foreach (explode(',', $_POST['tags']) as $tag) { + if (count($tags) < $max_tags) { + $tags[] = trim($tag, ' #'); + } + } DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'tumblr', 'tags', $tags); } @@ -419,11 +416,11 @@ function tumblr_cron() if ($last) { $next = $last + ($poll_interval * 60); if ($next > time()) { - DI::logger()->notice('poll interval not reached'); + Logger::notice('poll interval not reached'); return; } } - DI::logger()->notice('cron_start'); + Logger::notice('cron_start'); $abandon_days = intval(DI::config()->get('system', 'account_abandon_days')); if ($abandon_days < 1) { @@ -436,30 +433,30 @@ function tumblr_cron() foreach ($pconfigs as $pconfig) { if ($abandon_days != 0) { if (!DBA::exists('user', ["`uid` = ? AND `login_date` >= ?", $pconfig['uid'], $abandon_limit])) { - DI::logger()->notice('abandoned account: timeline from user will not be imported', ['user' => $pconfig['uid']]); + Logger::notice('abandoned account: timeline from user will not be imported', ['user' => $pconfig['uid']]); continue; } } - DI::logger()->notice('importing timeline - start', ['user' => $pconfig['uid']]); + Logger::notice('importing timeline - start', ['user' => $pconfig['uid']]); tumblr_fetch_dashboard($pconfig['uid'], $last); tumblr_fetch_tags($pconfig['uid'], $last); - DI::logger()->notice('importing timeline - done', ['user' => $pconfig['uid']]); + Logger::notice('importing timeline - done', ['user' => $pconfig['uid']]); } $last_clean = DI::keyValue()->get('tumblr_last_clean'); if (empty($last_clean) || ($last_clean + 86400 < time())) { - DI::logger()->notice('Start contact cleanup'); + 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()); - DI::logger()->notice('Contact cleanup done'); + Logger::notice('Contact cleanup done'); } - DI::logger()->notice('cron_end'); + Logger::notice('cron_end'); DI::keyValue()->set('tumblr_last_poll', time()); } @@ -481,13 +478,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['gravity'] != Item::GRAVITY_PARENT) && !Post::exists(['id' => $post['parent'], 'network' => Protocol::TUMBLR])) { - DI::logger()->notice('No tumblr parent found', ['item' => $post['id']]); + if (($post['parent'] != $post['id']) && !Post::exists(['id' => $post['parent'], 'network' => Protocol::TUMBLR])) { + Logger::notice('No tumblr parent found', ['item' => $post['id']]); $b['execute'] = false; return; } - } 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']]); + } 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']]); $b['execute'] = false; return; } @@ -495,11 +492,15 @@ 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['edit'] || ($b['private'] == Item::PRIVATE) || ($b['gravity'] != Item::GRAVITY_PARENT)) { + if ($b['private'] || $b['parent']) { return; } @@ -529,20 +530,20 @@ function tumblr_send(array &$b) } if ($b['gravity'] != Item::GRAVITY_PARENT) { - DI::logger()->debug('Got comment', ['item' => $b]); + Logger::debug('Got comment', ['item' => $b]); $parent = tumblr_get_post_from_uri($b['thr-parent']); if (empty($parent)) { - DI::logger()->notice('No tumblr post', ['thr-parent' => $b['thr-parent']]); + Logger::notice('No tumblr post', ['thr-parent' => $b['thr-parent']]); return; } - DI::logger()->debug('Parent found', ['parent' => $parent]); + Logger::debug('Parent found', ['parent' => $parent]); $page = tumblr_get_page($b['uid']); if ($b['gravity'] == Item::GRAVITY_COMMENT) { - DI::logger()->notice('Commenting is not supported (yet)'); + Logger::notice('Commenting is not supported (yet)'); } else { if (($b['verb'] == Activity::LIKE) && !$b['deleted']) { $params = ['id' => $parent['id'], 'reblog_key' => $parent['reblog_key']]; @@ -566,16 +567,16 @@ function tumblr_send(array &$b) } if ($result->meta->status < 400) { - DI::logger()->info('Successfully performed activity', ['verb' => $b['verb'], 'deleted' => $b['deleted'], 'meta' => $result->meta, 'response' => $result->response]); + 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], ['guid' => $b['guid']]); + Item::update(['extid' => 'tumblr::' . $result->response->id_string], ['id' => $b['id']]); } } else { - DI::logger()->notice('Error while performing activity', ['verb' => $b['verb'], 'deleted' => $b['deleted'], 'meta' => $result->meta, 'response' => $result->response, 'errors' => $result->errors, 'params' => $params]); + 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'] == Item::PRIVATE) || !strstr($b['postopts'], 'tumblr')) { + } elseif ($b['private'] || !strstr($b['postopts'], 'tumblr')) { return; } @@ -607,15 +608,6 @@ 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); @@ -656,7 +648,7 @@ function tumblr_send_legacy(array $b) } else { $params['type'] = 'text'; $params['title'] = $title; - $params['body'] = BBCode::convertForUriId($b['uri-id'], $body, BBCode::CONNECTORS); + $params['body'] = BBCode::convertForUriId($b['uri-id'], $b['body'], BBCode::CONNECTORS); } if (isset($params['caption']) && (trim($title) != '')) { @@ -669,9 +661,9 @@ function tumblr_send_legacy(array $b) $result = tumblr_post($b['uid'], 'blog/' . $page . '/post', $params); if ($result->meta->status < 400) { - DI::logger()->info('Success (legacy)', ['blog' => $page, 'meta' => $result->meta, 'response' => $result->response]); + Logger::info('Success (legacy)', ['blog' => $page, 'meta' => $result->meta, 'response' => $result->response]); } else { - DI::logger()->notice('Error posting blog (legacy)', ['blog' => $page, 'meta' => $result->meta, 'response' => $result->response, 'errors' => $result->errors, 'params' => $params]); + Logger::notice('Error posting blog (legacy)', ['blog' => $page, 'meta' => $result->meta, 'response' => $result->response, 'errors' => $result->errors, 'params' => $params]); } } @@ -680,7 +672,7 @@ function tumblr_send_npf(array $post): bool $page = tumblr_get_page($post['uid']); if (empty($page)) { - DI::logger()->notice('Missing page, post will not be send to Tumblr.', ['uid' => $post['uid'], 'page' => $page, 'id' => $post['id']]); + 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; } @@ -711,10 +703,10 @@ function tumblr_send_npf(array $post): bool $result = tumblr_post($post['uid'], 'blog/' . $page . '/posts', $params); if ($result->meta->status < 400) { - DI::logger()->info('Success (NPF)', ['blog' => $page, 'meta' => $result->meta, 'response' => $result->response]); + Logger::info('Success (NPF)', ['blog' => $page, 'meta' => $result->meta, 'response' => $result->response]); return true; } else { - DI::logger()->notice('Error posting blog (NPF)', ['blog' => $page, 'meta' => $result->meta, 'response' => $result->response, 'errors' => $result->errors, 'params' => $params]); + Logger::notice('Error posting blog (NPF)', ['blog' => $page, 'meta' => $result->meta, 'response' => $result->response, 'errors' => $result->errors, 'params' => $params]); return false; } } @@ -747,26 +739,14 @@ 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)) { - DI::logger()->debug('Tag post imported', ['tag' => $tag, 'id' => $id]); + 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); - DI::logger()->debug('Stored tag subscription for user', ['uri-id' => $post['uri-id'], 'uid' => $uid, 'tag' => $tag, 'stored' => $stored]); - Item::incrementInbound(Protocol::TUMBLR); + Logger::debug('Stored tag subscription for user', ['uri-id' => $post['uri-id'], 'uid' => $uid, 'tag' => $tag, 'stored' => $stored]); } } } @@ -790,8 +770,8 @@ function tumblr_fetch_dashboard(int $uid, int $last_poll) $dashboard = tumblr_get($uid, 'user/dashboard', $parameters); if ($dashboard->meta->status > 399) { - DI::logger()->notice('Error fetching dashboard', ['meta' => $dashboard->meta, 'response' => $dashboard->response, 'errors' => $dashboard->errors]); - return; + Logger::notice('Error fetching dashboard', ['meta' => $dashboard->meta, 'response' => $dashboard->response, 'errors' => $dashboard->errors]); + return []; } if (empty($dashboard->response->posts)) { @@ -803,10 +783,9 @@ function tumblr_fetch_dashboard(int $uid, int $last_poll) $last = $post->id; } - DI::logger()->debug('Importing post', ['uid' => $uid, 'created' => date(DateTimeFormat::MYSQL, $post->timestamp), 'id' => $post->id_string]); + 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); } @@ -861,7 +840,6 @@ 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, @@ -1078,7 +1056,7 @@ function tumblr_get_type_replacement(array $data, string $plink): string } default: - DI::logger()->notice('Unknown type', ['type' => $data['type'], 'data' => $data, 'plink' => $plink]); + Logger::notice('Unknown type', ['type' => $data['type'], 'data' => $data, 'plink' => $plink]); $body = ''; } @@ -1133,9 +1111,9 @@ function tumblr_get_contact(stdClass $blog, int $uid): array $cid = $contact['id']; Contact::update($fields, ['id' => $cid], true); } - DI::logger()->debug('Get user contact', ['id' => $cid, 'uid' => $uid, 'update' => $update]); + Logger::debug('Get user contact', ['id' => $cid, 'uid' => $uid, 'update' => $update]); } else { - DI::logger()->debug('Get public contact', ['id' => $cid, 'uid' => $uid, 'update' => $update]); + Logger::debug('Get public contact', ['id' => $cid, 'uid' => $uid, 'update' => $update]); } if (!empty($avatar)) { @@ -1171,16 +1149,15 @@ function tumblr_get_contact_fields(stdClass $blog, int $uid, bool $update): arra ]; if (!$update) { - DI::logger()->debug('Got contact fields', ['uid' => $uid, 'url' => $fields['url']]); + 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) { - DI::logger()->notice('Error fetching blog info', ['meta' => $info->meta, 'response' => $info->response, 'errors' => $info->errors]); + 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)) { @@ -1199,7 +1176,7 @@ function tumblr_get_contact_fields(stdClass $blog, int $uid, bool $update): arra $fields['header'] = $info->response->blog->theme->header_image_focused; - DI::logger()->debug('Got updated contact fields', ['uid' => $uid, 'url' => $fields['url']]); + Logger::debug('Got updated contact fields', ['uid' => $uid, 'url' => $fields['url']]); return $fields; } @@ -1241,12 +1218,10 @@ function tumblr_get_blogs(int $uid): array { $userinfo = tumblr_get($uid, 'user/info'); if ($userinfo->meta->status > 399) { - DI::logger()->notice('Error fetching blogs', ['meta' => $userinfo->meta, 'response' => $userinfo->response, 'errors' => $userinfo->errors]); + 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; @@ -1297,17 +1272,16 @@ function tumblr_get_contact_by_url(string $url, int $uid): ?array return null; } - DI::logger()->debug('Update Tumblr blog data', ['url' => $url, 'blog' => $blog, 'uid' => $uid]); + Logger::debug('Update Tumblr blog data', ['url' => $url, 'blog' => $blog, 'uid' => $uid]); $info = tumblr_get($uid, 'blog/' . $blog . '/info'); if ($info->meta->status > 399) { - DI::logger()->notice('Error fetching blog info', ['meta' => $info->meta, 'response' => $info->response, 'errors' => $info->errors, 'blog' => $blog, 'uid' => $uid]); + 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; @@ -1372,7 +1346,6 @@ 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)]]); @@ -1434,7 +1407,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()))) { - DI::logger()->debug('Got token', ['uid' => $uid, 'expires_at' => date('c', $expires_at)]); + Logger::debug('Got token', ['uid' => $uid, 'expires_at' => date('c', $expires_at)]); return $access_token; } @@ -1446,11 +1419,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)) { - DI::logger()->info('Invalid result while exchanging token', ['uid' => $uid]); + Logger::info('Invalid result while exchanging token', ['uid' => $uid]); return ''; } $expires_at = time() + $result->expires_in; - DI::logger()->debug('Updated token from OAuth1 to OAuth2', ['uid' => $uid, 'expires_at' => date('c', $expires_at)]); + Logger::debug('Updated token from OAuth1 to OAuth2', ['uid' => $uid, 'expires_at' => date('c', $expires_at)]); } else { if (!empty($code)) { $parameters['code'] = $code; @@ -1462,18 +1435,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()) { - DI::logger()->info('Error fetching token', ['uid' => $uid, 'code' => $code, 'result' => $curlResult->getBodyString(), 'parameters' => $parameters]); + Logger::info('Error fetching token', ['uid' => $uid, 'code' => $code, 'result' => $curlResult->getBodyString(), 'parameters' => $parameters]); return ''; } $result = json_decode($curlResult->getBodyString()); if (empty($result)) { - DI::logger()->info('Invalid result when updating token', ['uid' => $uid]); + Logger::info('Invalid result when updating token', ['uid' => $uid]); return ''; } $expires_at = time() + $result->expires_in; - DI::logger()->debug('Renewed token', ['uid' => $uid, 'expires_at' => date('c', $expires_at)]); + Logger::debug('Renewed token', ['uid' => $uid, 'expires_at' => date('c', $expires_at)]); } DI::pConfig()->set($uid, 'tumblr', 'access_token', $result->access_token); @@ -1517,7 +1490,7 @@ function tumblr_exchange_token(int $uid): stdClass $response = $client->post('oauth2/exchange', ['auth' => 'oauth']); return json_decode($response->getBody()->getContents()); } catch (RequestException $exception) { - DI::logger()->notice('Exchange failed', ['code' => $exception->getCode(), 'message' => $exception->getMessage()]); + Logger::notice('Exchange failed', ['code' => $exception->getCode(), 'message' => $exception->getMessage()]); return new stdClass; } } diff --git a/twitter/twitter.php b/twitter/twitter.php index a9654405..11c163ef 100644 --- a/twitter/twitter.php +++ b/twitter/twitter.php @@ -38,6 +38,7 @@ 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; @@ -66,7 +67,7 @@ function twitter_install() function twitter_load_config(ConfigFileManager $loader) { - DI::appHelper()->getConfigCache()->load($loader->loadAddonConfig('twitter'), \Friendica\Core\Config\ValueObject\Cache::SOURCE_STATIC); + DI::app()->getConfigCache()->load($loader->loadAddonConfig('twitter'), \Friendica\Core\Config\ValueObject\Cache::SOURCE_STATIC); } function twitter_jot_nets(array &$jotnets_fields) @@ -169,7 +170,7 @@ function twitter_hook_fork(array &$b) $post = $b['data']; if ( - $post['deleted'] || ($post['private'] == Item::PRIVATE) || ($post['created'] !== $post['edited']) || + $post['deleted'] || $post['private'] || ($post['created'] !== $post['edited']) || !strstr($post['postopts'], 'twitter') || ($post['gravity'] != Item::GRAVITY_PARENT) ) { $b['execute'] = false; @@ -183,7 +184,7 @@ function twitter_post_local(array &$b) return; } - if ($b['edit'] || ($b['private'] == Item::PRIVATE) || ($b['gravity'] != Item::GRAVITY_PARENT)) { + if ($b['edit'] || $b['private'] || $b['parent']) { return; } @@ -210,13 +211,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'] == Item::PRIVATE) || $b['deleted'] || ($b['created'] !== $b['edited'])) { + if (($b['gravity'] != Item::GRAVITY_PARENT) || !strstr($b['postopts'], 'twitter') || $b['private'] || $b['deleted'] || ($b['created'] !== $b['edited'])) { return; } $b['body'] = Post\Media::addAttachmentsToBody($b['uri-id'], DI::contentItem()->addSharedPost($b)); - DI::logger()->notice('twitter post invoked', ['id' => $b['id'], 'guid' => $b['guid']]); + Logger::notice('twitter post invoked', ['id' => $b['id'], 'guid' => $b['guid']]); DI::pConfig()->load($b['uid'], 'twitter'); @@ -226,17 +227,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)) { - DI::logger()->info('Missing keys, secrets or tokens.'); + Logger::info('Missing keys, secrets or tokens.'); return; } $msgarr = Plaintext::getPost($b, 280, true, BBCode::TWITTER); - DI::logger()->debug('Got plaintext', ['id' => $b['id'], 'message' => $msgarr]); + Logger::debug('Got plaintext', ['id' => $b['id'], 'message' => $msgarr]); $media_ids = []; if (!empty($msgarr['images']) || !empty($msgarr['remote_images'])) { - DI::logger()->info('Got images', ['id' => $b['id'], 'images' => $msgarr['images'] ?? []]); + Logger::info('Got images', ['id' => $b['id'], 'images' => $msgarr['images'] ?? []]); $retrial = Worker::getRetrial(); if ($retrial > 4) { @@ -249,7 +250,7 @@ function twitter_post_hook(array &$b) try { $media_ids[] = twitter_upload_image($b['uid'], $image, $retrial); } catch (RequestException $exception) { - DI::logger()->warning('Error while uploading image', ['image' => $image, 'code' => $exception->getCode(), 'message' => $exception->getMessage()]); + Logger::warning('Error while uploading image', ['image' => $image, 'code' => $exception->getCode(), 'message' => $exception->getMessage()]); Worker::defer(); return; } @@ -258,13 +259,13 @@ function twitter_post_hook(array &$b) $in_reply_to_tweet_id = 0; - DI::logger()->debug('Post message', ['id' => $b['id'], 'parts' => count($msgarr['parts'])]); + 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); - DI::logger()->info('twitter_post send', ['part' => $key, 'id' => $b['id'], 'result' => $id]); + Logger::info('twitter_post send', ['part' => $key, 'id' => $b['id'], 'result' => $id]); } catch (RequestException $exception) { - DI::logger()->warning('Error while posting message', ['part' => $key, 'id' => $b['id'], 'code' => $exception->getCode(), 'message' => $exception->getMessage()]); + 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(), @@ -318,9 +319,9 @@ function twitter_upload_image(int $uid, array $image, int $retrial) $picturedata = $picture->asString(); $new_size = strlen($picturedata); - 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]); + 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)]); - 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]); + 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; @@ -333,10 +334,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); - DI::logger()->info('Metadata create', ['uid' => $uid, 'data' => $data, 'return' => $ret]); + Logger::info('Metadata create', ['uid' => $uid, 'data' => $data, 'return' => $ret]); } } else { - DI::logger()->error('Failed upload', ['uid' => $uid, 'size' => strlen($picturedata), 'image' => $image['url'], 'return' => $media]); + Logger::error('Failed upload', ['uid' => $uid, 'size' => strlen($picturedata), 'image' => $image['url'], 'return' => $media]); throw new Exception('Failed upload of ' . $image['url']); } @@ -372,7 +373,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; - DI::logger()->debug('Success', ['content' => $content]); + Logger::debug('Success', ['content' => $content]); return $content; } @@ -401,7 +402,7 @@ function twitter_test_connection(int $uid) 'content' => $response->getBody()->getContents() ]; DI::pConfig()->set(1, 'twitter', 'last_status', $status); - DI::logger()->info('Test successful', ['uid' => $uid]); + Logger::info('Test successful', ['uid' => $uid]); } catch (RequestException $exception) { $status = [ 'code' => $exception->getCode(), @@ -409,6 +410,6 @@ function twitter_test_connection(int $uid) 'content' => $exception->getMessage() ]; DI::pConfig()->set(1, 'twitter', 'last_status', $status); - DI::logger()->info('Test failed', ['uid' => $uid]); + Logger::info('Test failed', ['uid' => $uid]); } } diff --git a/unicode_smilies/unicode_smilies.php b/unicode_smilies/unicode_smilies.php index 8ec47175..3bd30644 100644 --- a/unicode_smilies/unicode_smilies.php +++ b/unicode_smilies/unicode_smilies.php @@ -2,11 +2,12 @@ /* * 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.3 + * Version: 1.1.2 * Author: Michael Vogel * Author: Matthias Ebers */ +use Friendica\App; use Friendica\Content\Smilies; use Friendica\Core\Hook; @@ -24,7 +25,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', '😛'); @@ -53,350 +54,353 @@ 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, ':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, ':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:', '🤙'); // 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, ':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, ':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:', '👄'); // 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 @@ -407,83 +411,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:', '🐞'); @@ -491,958 +495,957 @@ 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, ':asterism:', '⁂'); - Smilies::add($b, ':outlines white star:', '颅'); + 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:', '📡'); // 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:', '≈'); @@ -1453,408 +1456,407 @@ 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 bd07b541..c4d21ccb 100644 --- a/viewsrc/viewsrc.php +++ b/viewsrc/viewsrc.php @@ -7,6 +7,7 @@ * */ +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 320b06a2..2236e97a 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 = []; + $this->authOptions = null; if (!empty($this->config->get('webdav', 'username'))) { $this->authOptions = [ diff --git a/webdav_storage/webdav_storage.php b/webdav_storage/webdav_storage.php index fd2eb0d9..adcbea29 100644 --- a/webdav_storage/webdav_storage.php +++ b/webdav_storage/webdav_storage.php @@ -8,10 +8,11 @@ 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() +function webdav_storage_install($a) { 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 e5d4ce6e..e142b374 100644 --- a/webrtc/webrtc.php +++ b/webrtc/webrtc.php @@ -7,6 +7,7 @@ * 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 de216806..e27079aa 100644 --- a/wppost/wppost.php +++ b/wppost/wppost.php @@ -9,6 +9,7 @@ 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; @@ -107,8 +108,8 @@ function wppost_hook_fork(array &$b) $post = $b['data']; if ( - $post['deleted'] || ($post['private'] == Item::PRIVATE) || ($post['created'] !== $post['edited']) || - !strstr($post['postopts'] ?? '', 'wppost') || ($post['gravity'] != Item::GRAVITY_PARENT) + $post['deleted'] || $post['private'] || ($post['created'] !== $post['edited']) || + !strstr($post['postopts'] ?? '', 'wppost') || ($post['parent'] != $post['id']) ) { $b['execute'] = false; return; @@ -117,12 +118,18 @@ 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; } - // 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)) { + if ($b['private'] || $b['parent']) { return; } @@ -145,9 +152,12 @@ function wppost_post_local(array &$b) $b['postopts'] .= 'wppost'; } + + + function wppost_send(array &$b) { - if ($b['deleted'] || ($b['private'] == Item::PRIVATE) || ($b['created'] !== $b['edited'])) { + if ($b['deleted'] || $b['private'] || ($b['created'] !== $b['edited'])) { return; } @@ -256,13 +266,11 @@ function wppost_send(array &$b) EOT; - DI::logger()->debug('wppost: data: ' . $xml); - - $x = ''; + Logger::debug('wppost: data: ' . $xml); if ($wp_blog !== 'test') { $x = DI::httpClient()->post($wp_blog, $xml)->getBodyString(); } - DI::logger()->info('posted to wordpress: ' . $x); + Logger::info('posted to wordpress: ' . (($x) ? $x : '')); } }